Files
scadaproj/ZB.MOM.WW.Theme/CLAUDE.md
T
Joseph Doherty 48af177dce fix(theme): shell fills the dynamic viewport — drop calc(100vh - 3.3rem) (scadaproj#10)
.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
2026-11-09 22:36:20 -05:00

105 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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).