Files
scadaproj/components/ui-theme/current-state/scadabridge/CURRENT-STATE.md
T
2026-06-01 05:15:38 -04:00

8.3 KiB
Raw Blame History

UI Theme — current state: ScadaBridge

Repo: ~/Desktop/ScadaBridge. Stack: .NET 10, Blazor SSR (Akka.NET cluster + central UI). UI surfaces: src/ZB.MOM.WW.ScadaBridge.CentralUI/ (RCL) and src/ZB.MOM.WW.ScadaBridge.Host/ (the Blazor host that references it). All paths below are relative to the repo root. Verified against source on 2026-06-01.

Summary: ScadaBridge uses a sidebar nav layout and the Technical-Light tokens, with the correct font-path prefix. The sidebar uses .sidebar / .nav-link classes (same idiom as MxGateway), not .side-rail / .rail-link. Adoption is medium effort — sidebar-class migration + MainLayout replacement, no layout redesign. ScadaBridge has several scoped .razor.css files that stay per-project.


1. CSS / design tokens

theme.css — 379-line hand copy of the Technical-Light design system.

  • Path: src/ZB.MOM.WW.ScadaBridge.CentralUI/wwwroot/css/theme.css
  • Font path: url('../fonts/ibm-plex-sans-400.woff2') (lines 24, 29, 34)
  • Correct path — resolves from wwwroot/css/ to wwwroot/fonts/ without 404. This is the canonical url('../fonts/…') that the RCL also uses.
  • Wired in the Host's App.razor line 9: <link href="_content/ZB.MOM.WW.ScadaBridge.CentralUI/css/theme.css" rel="stylesheet" />.

site.css — 128 lines of per-app page layout (sidebar shell, nav overrides).

  • Path: src/ZB.MOM.WW.ScadaBridge.CentralUI/wwwroot/css/site.css
  • Wired in the Host's App.razor line 11: <link href="_content/ZB.MOM.WW.ScadaBridge.CentralUI/css/site.css" rel="stylesheet" />.
  • Contains: .sidebar layout block (~495), Bootstrap-icons integration for nav items.
  • After adoption: the .sidebar layout section is superseded by RCL layout.css. The remaining rules (Bootstrap-icons, misc overrides) stay in site.css.

Note: ScadaBridge uses the _content/ZB.MOM.WW.ScadaBridge.CentralUI/… static-web-asset path for its own CentralUI RCL assets — the same mechanism ZB.MOM.WW.Theme will use.


2. IBM Plex fonts

Three .woff2 files vendored into: src/ZB.MOM.WW.ScadaBridge.CentralUI/wwwroot/fonts/

  • ibm-plex-sans-400.woff2
  • ibm-plex-sans-600.woff2
  • ibm-plex-mono-500.woff2

After adoption: delete all three from CentralUI/wwwroot/fonts/; the RCL serves them from _content/ZB.MOM.WW.Theme/fonts/.


3. Layout shell

MainLayout.razor — 29-line static layout. @inherits LayoutComponentBase. No @rendermode directive (static SSR).

  • Path: src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Layout/MainLayout.razor
  • Root element: <div class="d-flex flex-column flex-lg-row" style="min-height: 100vh;">. No .app-shell class.
  • Renders <NavMenu /> inside a Bootstrap collapse div, <main class="flex-grow-1 p-3">, plus <DialogHost /> and <SessionExpiry /> at the bottom.

NavMenu.razor — 200+ line interactive sidebar component. @implements IDisposable.

  • Path: src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Layout/NavMenu.razor
  • Brand: <div class="brand"><span class="mark">&#9646;</span> ScadaBridge</div> (lines ~99).
  • Nav structure: <nav class="sidebar d-flex flex-column"> with <ul class="nav flex-column"> and <NavSection> groups ("Admin", "Data", "Audit", etc.) with <NavLink class="nav-link"> children. Uses AuthorizeView + AuthorizeView Policy="…" to gate admin sections.
  • Nav state: JS-based expand-state persistence (same pattern as OtOpcUa and MxGateway).

NavSection.razor (same name as OtOpcUa/MxGateway, independent per-project copy).

  • Path: src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Layout/NavSection.razor

4. Login page

Login.razor — 36-line static login page. @layout LoginLayout, @attribute [AllowAnonymous].

  • Path: src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Login.razor
  • Form: <form method="post" action="/auth/login" data-enhance="false"> (line 16).
  • Uses Bootstrap .card / .card-body markup — not the Technical-Light .panel / .login-wrap idiom used in OtOpcUa. Does not use a <LoginCard> yet.
  • Error notice: Bootstrap .alert alert-danger (line 12) rather than .panel.notice.

5. Scoped .razor.css files (stays per-project)

ScadaBridge ships several component-scoped CSS files. These are not shared and stay in the CentralUI RCL after adoption:

File Path
MultiSelectDropdown.razor.css src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/
TreeView.razor.css src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Shared/
AuditDrilldownDrawer.razor.css src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/
AuditEventDetail.razor.css src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/
ExecutionDetailModal.razor.css src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/
ExecutionTree.razor.css src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/
AuditResultsGrid.razor.css src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Audit/
NodeBrowserDialog.razor.css src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Dialogs/

These scoped styles are component-specific overrides and are unaffected by theme adoption.


6. Divergences from spec

Item Current state Spec
theme.css Hand copy, 379 lines Single canonical copy in RCL
Font-path url() url('../fonts/…')correct url('../fonts/…') — same
IBM Plex fonts Vendored 3× in wwwroot/fonts/ Single copy in RCL wwwroot/fonts/
Shell class d-flex … (no .app-shell) ThemeShell + .app-shell
Nav class idiom .sidebar + .nav-link + <ul>/<li> .side-rail + .rail-link + <a>
Nav items <NavLink class="nav-link"> inside <li> <NavRailItem>
Nav sections NavSection (EventCallback OnToggle + JS) NavRailSection (<details>, CSS-only)
Status chip None (uses raw .chip-* classes inline) StatusPill (StatusState enum)
Login card Bootstrap .card markup (not Technical-Light .panel) <LoginCard>
Scoped .razor.css 8 component-scoped files Stays per-project (no change)

7. Adoption plan

Effort: Medium. Risk: Medium. The font path is already correct so no 404 fix needed. The sidebar idiom migration (.sidebar.side-rail, .nav-link.rail-link) and the MainLayout replacement are the main work. The scoped .razor.css files are unaffected.

Steps:

  1. Delete copies. Remove src/ZB.MOM.WW.ScadaBridge.CentralUI/wwwroot/css/theme.css and wwwroot/fonts/ibm-plex-*.woff2 from CentralUI.

  2. Reference RCL. Add <PackageReference Include="ZB.MOM.WW.Theme" /> to ZB.MOM.WW.ScadaBridge.CentralUI.csproj. Add @using ZB.MOM.WW.Theme to CentralUI's _Imports.razor.

  3. Wire ThemeHead. In Host's App.razor, replace line 9 (<link href="_content/…/css/theme.css">) with <ThemeHead /> (which now resolves via ZB.MOM.WW.Theme). Keep the site.css link on line 11.

  4. Replace MainLayout. Replace the 29-line MainLayout.razor with a thin wrapper around <ThemeShell Product="ScadaBridge">. Carry <NavMenu /> into the Nav slot (or replace it — see step 5). Keep <DialogHost /> and <SessionExpiry /> below the ThemeShell or inside ChildContent as needed.

  5. Port nav. Migrate NavMenu.razor from nav.sidebar + <ul>/<li> + .nav-link to <NavRailSection> + <NavRailItem>. The AuthorizeView policy gating on admin sections stays — wrap <NavRailSection> inside the appropriate <AuthorizeView> just as today.

  6. Clean site.css. Remove the .sidebar layout block. Keep Bootstrap-icons integration and any domain-specific overrides.

  7. Replace login card. In Login.razor, replace the Bootstrap .card/.card-body markup with <LoginCard Product="ScadaBridge" Action="/auth/login" ReturnUrl="@ReturnUrl" Error="@ErrorMessage"><AntiforgeryToken /></LoginCard>. Align error display with the Technical-Light .panel.notice style from LoginCard.

  8. Keep: all scoped .razor.css files (8 files listed above); site.css domain rules; auth and session endpoints; all page components.

Risk note: ScadaBridge's AuthorizeView policy-gated nav sections require careful testing — verify that <NavRailSection> inside <AuthorizeView> renders correctly and that the section is fully hidden when the policy fails (not just collapsed).