48af177dce
.app-shell min-height is now 100vh with a 100dvh override (the 3.3rem was a donor-app top-bar leftover; ThemeShell has no top bar) and the lg+ sticky rail is 100vh/100dvh. Source bumped to 0.5.3, UNPUBLISHED. Adds a static regression test and fixes the CS8602 in NavStateScriptTests (0 warnings). Browser-checked via Overview on local 0.5.2 vs 0.5.3 packages: at 390x844 a short page went from a 791px shell (53px gap) to 844px, no extra scroll; 1440x900 rail stays sticky full-height. Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
105 lines
11 KiB
Markdown
105 lines
11 KiB
Markdown
# ZB.MOM.WW.Theme
|
||
|
||
Shared UI kit (Razor Class Library — Technical-Light tokens, IBM Plex, side-rail shell, widgets) for the **ZB.MOM.WW SCADA family**; five consumers. Build/test from this directory: `dotnet test`. Component spec + gaps: `../components/ui-theme/`.
|
||
|
||
**Backlog / open work:** lives in Gitea issues on `dohertj2/scadaproj` (`tea issues list --repo dohertj2/scadaproj`) — currently #9 (roll `0.5.0` to the other consumers); #10 (`calc(100vh - 3.3rem)`) is fixed in 0.5.3 source. The history below is a record, not a status tracker; file new follow-ups as issues.
|
||
|
||
## 0.5.3 (2026-11-09, UNPUBLISHED)
|
||
|
||
Fixes scadaproj#10. `.app-shell` was `min-height: calc(100vh - 3.3rem)` — the 3.3rem is a donor-app top-bar
|
||
leftover (ThemeShell renders no top bar), so below lg a short page stopped 53 px short of the viewport, and plain
|
||
`100vh` overshoots on mobile browsers with collapsing toolbars. Now `min-height: 100vh; min-height: 100dvh;`
|
||
(100vh = fallback), and the lg+ sticky `#theme-rail` is `height: 100vh; height: 100dvh;`. The column layout's
|
||
`flex: 1` on the page was already supplied by `.app-shell .page`, so the page takes the height left under the
|
||
hamburger row. Static test `Shell_fills_the_dynamic_viewport_with_no_topbar_offset`; also fixed the CS8602 in
|
||
`NavStateScriptTests` (0 warnings). Browser check (Overview on local 0.5.2 vs 0.5.3 packages, iframe viewports):
|
||
390x844 short page — before shell 791 px tall with a 53 px gap under the page, after shell/page reach 844,
|
||
`scrollHeight == innerHeight` both times (no extra scroll); 1440x900 — rail sticky at 0–900 after scrolling a
|
||
1133 px page, short page fills 900, before and after. Consumers: mxgw's `body.dashboard-body { min-height: 100vh }`
|
||
and ScadaBridge's lg+ `#theme-rail > .side-rail { height: 100% }` don't conflict; neither app still has an inline
|
||
`min-height:100vh` shell wrapper on its default branch. Version bumped in `Directory.Build.props`, not packed or pushed.
|
||
|
||
## 0.5.2 (2026-11-09, UNPUBLISHED)
|
||
|
||
Also adds the opt-in `ThemeShell ScrollNav` parameter (ScadaBridge#61, upstreamed from ScadaBridge's local `.rail-scroll`):
|
||
default false = markup/CSS unchanged for every consumer; true = `Nav` wrapped in `.rail-scroll`, `nav` gets
|
||
`side-rail-scroll`, and layout.css (lg+ only) fills the rail and scrolls just the pane. Not yet adopted by ScadaBridge.
|
||
|
||
Version bumped in `Directory.Build.props`, not packed or pushed. Fixes Theme-008 (scadaproj#48): `nav-state.js` tracks
|
||
wired sections in a JS `WeakSet` instead of the `data-zbnav-initialized` DOM attribute, which Blazor's enhanced-navigation
|
||
DOM sync strips (toggle listeners stacked and the transient active-link reveal was persisted). Regression test
|
||
`NavStateScriptTests` runs `nav-state.test.js` under Node (skips if Node is absent).
|
||
|
||
## 0.5.1 (2026-11-09, UNPUBLISHED)
|
||
|
||
Version bumped in `Directory.Build.props`, not packed or pushed. Fixes Theme-007 (scadaproj#44):
|
||
`TechButton` now ORs a caller-splatted `disabled` with `Busy` (it was overwritten by the trailing
|
||
`disabled="@Busy"` and dropped whenever `Busy` was false). No API change. Tests: 65 pass.
|
||
|
||
## Published 0.5.0 (2026-11-04)
|
||
|
||
Published the tested ignitionoee backlog package to the shared Gitea feed on
|
||
2026-11-04. Independent download matched the reviewed artifact SHA256
|
||
`374511ebaaa15be71024051e896c8e7e59a8951b0d51a990fa48fbe378ac6485`.
|
||
The ignitionoee router deployed this package to CR on 2026-11-04. No other
|
||
consumer was deployed in this task (rollout → #9). Do not repack or replace published 0.5.0.
|
||
Retains 0.4.2's `.rise` fill-mode fix. Adds the remaining shared application CSS
|
||
from ignitionoee (including `td.row-actions`), composable `TechButton.Class` and
|
||
`ButtonSize`, plus `ITreeRow`/stateless `TreeTable<TRow>` in `ZB.MOM.WW.Theme`.
|
||
Tree styles live once in `layout.css`, with arbitrary-depth indentation and
|
||
keyboard-focus styling. Caller-owned filtering/collapse behavior stays intact.
|
||
|
||
Test harness migrated to bUnit 2.7.2 with AngleSharp 1.5.0 to address the existing
|
||
NU1902 advisory without disabling audit. Runtime package dependencies are unchanged.
|
||
Local verification: Release build passed with zero warnings/errors; Release tests
|
||
passed 60 tests, none skipped. `build/pack.sh` produced the local 0.5.0 nupkg.
|
||
All 19 remaining ignitionoee app.css rule blocks are present verbatim in the
|
||
shared stylesheet; the Impeccable detector reported no findings on changed UI files.
|
||
Browser QA also exposed a pre-existing mobile shell bug: closed navigation hid
|
||
the page through Chromium's disclosure wrapper. The wrapper override now applies
|
||
at all widths, with an explicit mobile rule hiding only the rail and author
|
||
display rules for older browsers. Two regression tests cover CSS placement and
|
||
closed-shell component structure; computed mobile/desktop behavior was checked in
|
||
the disposable ignitionoee local browser fixture.
|
||
Browser QA confirmed the visibility fix and isolated an additional mobile
|
||
min-content sizing issue: bounding the direct page to 100% width/max-width with
|
||
border-box reduced the page/document from 1055px to the 390px viewport and kept
|
||
wide-table scrolling inside its wrapper. That measured constraint is included.
|
||
See README's 0.5.0 migration section; deployed consumer validation remains separate
|
||
from local source/package/browser verification.
|
||
|
||
## Index history (migrated from the scadaproj root CLAUDE.md)
|
||
|
||
> Moved verbatim out of the scadaproj root `CLAUDE.md` on 2026-09-03 so it loads only when needed. **This file is now the authoritative place for this history — append new entries here and keep the root index row short.**
|
||
|
||
### Component-table row as it read in the index
|
||
|
||
| Component | Status | Goal | Design | Implementation |
|
||
|---|---|---|---|---|
|
||
| UI Theme (layout / tokens / components) | Adopted (feed `0.2.0`–`0.4.1`). **`0.4.0` (2026-08-11) upstreamed the Bootstrap `.btn`/`.btn-sm` sizing block** that all **five** consumers had independently written into their own stylesheets (Bootstrap hard-codes `--bs-btn-font-size: 1rem`, oversized against the kit's 0.9rem body) — sized by `--bs-btn-*` variable override **only**, never by redeclaring box properties, because `.btn-group`'s seam/radius machinery reads those same variables and a literal `font-size` at equal specificity silently flattens `.btn-sm` into a padding-only difference (a real defect found in mxgw's local copy). Same release added the `rail-btn-block` full-width rail-foot modifier; **`0.4.1` fixes it** — 0.4.0 shipped `width: auto`, which fills for an `<a>` but shrink-wraps a `<button>` (measured 114px short in the same rail), now `calc(100% - 1.2rem)` to clear `.rail-btn`'s side margins. **Consumers are five, not four** — the ignitionoee router joined. **All five consumers are on `0.4.1` and all five are PUSHED** (2026-08-11): ignitionoee `main @ 38aa5c1`, OtOpcUa `master @ e82881c1`, mxgw `main @ 0a9715d`. The two whose sweeps were not deploy-ready pushed to **branches**, deliberately leaving their default branch untouched: HistorianGateway `dashboard-ui-sweep-theme-0.4.1` — **MERGED to `main` (ff to `e42ff31`) + pushed 2026-08-13**, carrying Theme 0.4.1 + Health 0.3.0 + Secrets 0.6.2 + Auth 0.2.1 and ScadaBridge `ui/central-ui-cleanup-sweep @ 9e243493` (`main` was then `b6f383a2`). **ScadaBridge's caveat is now CLOSED and its sweep is merged, deployed and live** (2026-08-11): the branch landed on `main`, and the two follow-ups `d14e0ee4` + `3eb7df74` fixed exactly the four detail-modal surfaces the caveat named — the modal is now gated on **user intent (the held id)**, never on the row still resolving, so a background refresh that drops the row leaves it mounted and says why the summary is missing instead of unmounting the subtree and disposing Close's own handler mid-click. That disposal *was* the intermittent `GetRequiredEventBindingEntry`, and `NotificationReportDetailModalTests.Modal_StaysOpen_WhenItsRowLeavesThePage` now pins it. **Deployed to wonder-app-vd03: OtOpcUa `e82881c1`, and ScadaBridge `3eb7df74` (2026-08-11 — theme.css/layout.css/nav-state.js served from `_content/ZB.MOM.WW.Theme` and referenced by the pages; all six changed routes 200). HistorianGateway on wonder still runs `e9c31da` = Theme 0.3.1 — its 0.4.1 is now on `main` (merged 2026-08-13) but not yet deployed to the box.** **On bump, TRIM the local `.btn` block, don't delete it** — four of the five were pure sizing, but mxgw's also carried `border-radius`/`font-weight`/`white-space` that a blind delete would have dropped. | Shared `ZB.MOM.WW.Theme` RCL | [`components/ui-theme/`](components/ui-theme/) | [`ZB.MOM.WW.Theme/`](ZB.MOM.WW.Theme/) |
|
||
|
||
### Narrative
|
||
|
||
The UI-theme component is fully populated: a normalized [`spec`](components/ui-theme/spec/SPEC.md),
|
||
a [`design-tokens`](components/ui-theme/spec/DESIGN-TOKENS.md) reference, a
|
||
[`shared-contract`](components/ui-theme/shared-contract/ZB.MOM.WW.Theme.md), three
|
||
[`current-state`](components/ui-theme/current-state/) docs, and an adoption [`GAPS`](components/ui-theme/GAPS.md)
|
||
backlog. Shared = Technical-Light tokens + IBM Plex fonts + side-rail shell + widgets; left
|
||
per-project = each app's `site.css` page layout, route content, scoped `.razor.css`.
|
||
|
||
The shared RCL is **built and lives in this repo** at [`ZB.MOM.WW.Theme/`](ZB.MOM.WW.Theme/)
|
||
(.NET 10 Razor Class Library; single package; 48 bUnit tests (re-verified 2026-08-11 at `0.4.1`); feed carries `0.2.0`–`0.4.1`,
|
||
**published to the Gitea feed**). The build plan is at
|
||
[`docs/plans/2026-06-01-zb-mom-ww-theme-shared-library.md`](docs/plans/2026-06-01-zb-mom-ww-theme-shared-library.md);
|
||
the adoption plan at [`docs/plans/2026-06-03-ui-theme-adoption.md`](docs/plans/2026-06-03-ui-theme-adoption.md).
|
||
**Adopted across all three apps on 2026-06-03** (full canonical cutover, SPEC §7) on each repo's
|
||
`feat/adopt-zb-theme` branch — committed + spec/code-reviewed, then **fast-forward-merged into each repo's local
|
||
default (master/main) and PUSHED to origin (gitea)** (in sync; `feat/*` kept locally as history): OtOpcUa
|
||
→`lmxopcua` `master`@`11de14d`, ScadaBridge `main`@`58352a6`, MxGateway→`mxaccessgw` `main`@`73e54e2`. The `0.1.0 → 0.2.0` bump first promoted nav-expand persistence
|
||
into the kit (`NavRailSection.Key`/`data-nav-key` + a localStorage `nav-state.js` enhancer emitted by a new
|
||
`<ThemeScripts/>`), so all three apps share one persistence mechanism (OtOpcUa's bespoke cookie/JS-interop nav
|
||
island retired); MxGateway additionally gained a net-new Blazor `<LoginCard>` `/login` page over its existing
|
||
hardened endpoint. Per-app result in [`components/ui-theme/GAPS.md`](components/ui-theme/GAPS.md).
|
||
Build/test from `ZB.MOM.WW.Theme/`: `dotnet test`. Consumer matrix: all three apps consume
|
||
the single `ZB.MOM.WW.Theme` package (OtOpcUa AdminUI, MxGateway Server, ScadaBridge Host + CentralUI).
|