91 lines
5.1 KiB
Markdown
91 lines
5.1 KiB
Markdown
# UI Theme — gaps & adoption backlog
|
||
|
||
Divergence of each project from [`spec/SPEC.md`](spec/SPEC.md), and the ordered backlog to
|
||
reach adoption of the `ZB.MOM.WW.Theme` shared RCL. Status legend: ⛔ gap · 🟡 partial · ✅ matches.
|
||
|
||
---
|
||
|
||
## Divergence vs spec
|
||
|
||
### §1 Design tokens — `theme.css`
|
||
|
||
| Item | OtOpcUa | MxAccessGateway | ScadaBridge |
|
||
|---|---|---|---|
|
||
| Tokens identical to canonical | ✅ identical | ✅ identical | ✅ identical |
|
||
| File maintained in one place (RCL) | ⛔ own copy | ⛔ own copy | ⛔ own copy |
|
||
| Font path `url('../fonts/…')` | ⛔ `url('fonts/…')` — **latent 404** | 🟡 `url('/fonts/…')` — absolute, not portable | ✅ `url('../fonts/…')` — correct |
|
||
| IBM Plex fonts in one place | ⛔ own `wwwroot/fonts/` | ⛔ own `wwwroot/fonts/` | ⛔ own `wwwroot/fonts/` |
|
||
|
||
→ **Gap T1:** All three apps maintain a copy of `theme.css` — the single-source guarantee
|
||
is broken today. Any token change must be applied in four places (three apps + the RCL)
|
||
once the RCL exists.
|
||
→ **Gap T2:** OtOpcUa `url('fonts/…')` is a latent 404 masked by system-font fallback.
|
||
Adoption fixes it automatically.
|
||
→ **Gap T3:** Each app vendors fonts — 3× duplication. The RCL eliminates it.
|
||
|
||
### §2 Typography
|
||
|
||
All three apps reference IBM Plex via the token stacks. No typography divergence — the
|
||
token values are identical. Gap is delivery (T3 above).
|
||
|
||
### §3 Canonical side-rail layout
|
||
|
||
| Item | OtOpcUa | MxAccessGateway | ScadaBridge |
|
||
|---|---|---|---|
|
||
| `.app-shell` root element | ✅ `div.app-shell` | ⛔ `div.d-flex …` (no `.app-shell`) | ⛔ `div.d-flex …` (no `.app-shell`) |
|
||
| Rail CSS class | ✅ `.side-rail` | ⛔ `.sidebar` | ⛔ `.sidebar` |
|
||
| Nav item CSS class | ✅ `.rail-link` | ⛔ `.nav-link` | ⛔ `.nav-link` |
|
||
| Nav item element | ✅ `<a>` (NavLink) | ⛔ `<li><NavLink>` inside `<ul>` | ⛔ `<li><NavLink>` inside `<ul>` |
|
||
| Shell component | ⛔ bespoke `MainLayout` + `NavSidebar` | ⛔ combined `MainLayout` (210 lines) | ⛔ `MainLayout` + `NavMenu` |
|
||
| Thin-MainLayout pattern | ⛔ not yet | ⛔ not yet | ⛔ not yet |
|
||
|
||
→ **Gap L1:** OtOpcUa already uses the right CSS classes but the component structure
|
||
doesn't use `ThemeShell`. Low-risk migration.
|
||
→ **Gap L2:** MxAccessGateway and ScadaBridge use `.sidebar` / `.nav-link` / `<ul><li>`.
|
||
Migration requires class name changes throughout their nav markup and `site.css` sidebar
|
||
blocks. Medium (ScadaBridge) to high (MxGateway combined layout) risk.
|
||
|
||
### §4 Component contract
|
||
|
||
| Component | OtOpcUa | MxAccessGateway | ScadaBridge |
|
||
|---|---|---|---|
|
||
| `StatusPill` (vs bespoke `StatusBadge`) | ⛔ `StatusBadge` (string CSS class) | ⛔ `StatusBadge` (string text → class) | ⛔ raw `.chip-*` classes inline |
|
||
| `LoginCard` | ⛔ inline markup in `Login.razor` | ⛔ no Blazor login page | ⛔ Bootstrap `.card` markup in `Login.razor` |
|
||
| `NavRailItem` / `NavRailSection` | ⛔ `NavLink` + `NavSection` (interactive) | ⛔ `NavLink`+`<li>` + `NavSection` | ⛔ `NavLink`+`<li>` + `NavSection` |
|
||
| `ThemeShell` / thin `MainLayout` | ⛔ not yet | ⛔ not yet | ⛔ not yet |
|
||
| `ThemeHead` | ⛔ manual `<link>` tags | ⛔ manual `<link>` tags | ⛔ manual `<link>` tags |
|
||
|
||
### §5 Delivery
|
||
|
||
| Item | OtOpcUa | MxAccessGateway | ScadaBridge |
|
||
|---|---|---|---|
|
||
| Asset via `_content/ZB.MOM.WW.Theme/…` | ⛔ `_content/…AdminUI/css/…` | ⛔ root-relative `/css/…` | ⛔ `_content/…CentralUI/css/…` |
|
||
| `<ThemeHead />` in `<head>` | ⛔ manual `<link>` tags | ⛔ manual `<link>` tags | ⛔ manual `<link>` tags |
|
||
|
||
---
|
||
|
||
## Adoption backlog (ordered)
|
||
|
||
| # | Item | Projects | Priority | Effort | Risk | Notes |
|
||
|---|---|---|---|---|---|---|
|
||
| 1 | Build `ZB.MOM.WW.Theme` RCL | scadaproj | High | M | Low | **DONE** — `0.1.0` built + tested in this repo |
|
||
| 2 | Adopt in OtOpcUa AdminUI | OtOpcUa | High | S | Low | Already rail; fix latent font 404; cookie nav-state optional retain |
|
||
| 3 | Adopt in ScadaBridge CentralUI + Host | ScadaBridge | Med | M | Med | Sidebar class migration + `MainLayout` replace; scoped `.razor.css` unchanged |
|
||
| 4 | Adopt in MxAccessGateway Dashboard | MxAccessGateway | Low | L | High | Combined `MainLayout` migration; sidebar idiom change; largest UX-visible change — verify visually |
|
||
|
||
**Sequencing:** #2 first (lowest risk, validates the adoption pattern); #3 next (medium
|
||
effort, no design change); #4 last (highest risk — verify dashboard UX thoroughly before
|
||
merging). Each adoption is a per-repo PR, independent.
|
||
|
||
---
|
||
|
||
## Open questions
|
||
|
||
- **MxGateway login:** No Blazor login page today. If one is added during adoption (#4),
|
||
use `<LoginCard>`. If the server-redirect pattern is kept, `<LoginCard>` is not needed.
|
||
- **OtOpcUa cookie nav state:** Decide whether to retain `otopcua_nav` cookie persistence
|
||
(keep bespoke interactive `NavSection` alongside `ThemeShell`'s `Nav` slot) or drop it
|
||
(CSS-only `NavRailSection` replaces it, losing expand-state persistence across page loads).
|
||
- **ScadaBridge `AuthorizeView` policy gating in nav:** Verify `<NavRailSection>` inside
|
||
`<AuthorizeView>` renders + hides correctly with the canonical SSR rendering model.
|