From 3d96b5be6207ae9e93fa2662ac2bbfe6a474bb0f Mon Sep 17 00:00:00 2001 From: JSONbored <49853598+JSONbored@users.noreply.github.com> Date: Fri, 24 Jul 2026 13:39:03 -0700 Subject: [PATCH 1/2] refactor(ui): tokenize raw z-index one-offs into a semantic layering scale ~56 sites across both packages used bare Tailwind z-* steps (z-10/20/30/40/50 plus z-[60]/z-[100]) with no documented layering system -- undocumented stacking is how a future component silently lands behind a modal or above a toast. Author a named --mg-z-* scale in packages/ui-kit/src/styles.css: --mg-z-sticky(10)/raised(20)/nav(30)/overlay(40)/modal(50)/progress(60)/ skip-link(100), matching Radix's own z-50 default so its portalled primitives (dialog/sheet/popover/tooltip/hover-card) need no override. Sweep all 50 non-exception sites onto z-[var(--mg-z-*)]. Two sites didn't transliterate 1:1: a column-customizer.tsx click-outside backdrop and a page-actions.tsx overflow menu were both bare z-30, but neither is nav chrome -- they're popover-style overlays, so both moved to --mg-z-overlay (their DOM order already keeps the visible panel above its own backdrop at equal z-index). Left the 6 z-[1]/z-[2] sticky-cell sites in the two compare drawers alone -- local stacking context (a sticky corner cell over its own sticky row/col), not a global layer -- and added a comment on each explaining why. Guardrail (warn-tier) in both eslint configs flags any remaining bare z-10/20/30/40/50 or z-[N] step, including the 6 documented exceptions (same residual-worklist convention the shadow-token rule already uses). Documented the full scale in apps/ui/CONTRIBUTING.md's Bone & Ink section. Verified via getComputedStyle: all 7 --mg-z-* custom properties resolve to their intended numeric values, and the sticky table header / site nav report the correct 10/30 z-index in a live preview. Closes #7841 --- apps/ui/CONTRIBUTING.md | 18 ++++++++ apps/ui/eslint.config.ts | 12 +++++ .../metagraphed/analytics/coverage-matrix.tsx | 4 +- .../src/components/metagraphed/app-shell.tsx | 4 +- .../metagraphed/blocks/shortcuts-dialog.tsx | 2 +- .../call-module-extrinsics-table.tsx | 2 +- .../metagraphed/charts/latency-heatmap.tsx | 4 +- .../charts/validator-subnet-heatmap.tsx | 4 +- .../metagraphed/endpoint-operational-list.tsx | 4 +- .../metagraphed/entity-hover-card.tsx | 2 +- .../components/metagraphed/nav-mega-menu.tsx | 2 +- .../components/metagraphed/nav-omnibox.tsx | 2 +- .../components/metagraphed/profile-tabs.tsx | 2 +- .../metagraphed/shortcuts-popover.tsx | 2 +- .../metagraphed/subnets-compare-drawer.tsx | 3 +- .../validator-nominators-table.tsx | 2 +- .../metagraphed/validators-compare-drawer.tsx | 3 +- apps/ui/src/routes/__root.tsx | 2 +- apps/ui/src/routes/blocks.index.tsx | 2 +- apps/ui/src/routes/endpoints.tsx | 2 +- apps/ui/src/routes/extrinsics.index.tsx | 2 +- apps/ui/src/routes/index.tsx | 4 +- apps/ui/src/routes/providers.index.tsx | 2 +- packages/ui-kit/dist/index.cjs | 46 +++++++++---------- packages/ui-kit/dist/index.css | 9 ++++ packages/ui-kit/dist/index.js | 46 +++++++++---------- packages/ui-kit/eslint.config.ts | 9 ++++ .../components/metagraphed/back-to-top.tsx | 2 +- .../metagraphed/charts/candlestick-mini.tsx | 2 +- .../metagraphed/charts/sparkline.tsx | 2 +- .../metagraphed/column-customizer.tsx | 4 +- .../components/metagraphed/filter-sheet.tsx | 4 +- .../components/metagraphed/hover-preview.tsx | 2 +- .../src/components/metagraphed/list-shell.tsx | 2 +- .../components/metagraphed/page-actions.tsx | 2 +- .../components/metagraphed/query-progress.tsx | 7 +-- .../components/metagraphed/scroll-shadow.tsx | 4 +- .../components/metagraphed/sticky-toolbar.tsx | 2 +- packages/ui-kit/src/components/ui/dialog.tsx | 4 +- .../ui-kit/src/components/ui/hover-card.tsx | 2 +- packages/ui-kit/src/components/ui/popover.tsx | 2 +- packages/ui-kit/src/components/ui/sheet.tsx | 4 +- packages/ui-kit/src/components/ui/tooltip.tsx | 2 +- packages/ui-kit/src/styles.css | 16 +++++++ 44 files changed, 163 insertions(+), 96 deletions(-) diff --git a/apps/ui/CONTRIBUTING.md b/apps/ui/CONTRIBUTING.md index ded4849606..51698e4b94 100644 --- a/apps/ui/CONTRIBUTING.md +++ b/apps/ui/CONTRIBUTING.md @@ -69,6 +69,24 @@ budget — keep new dependencies/imports lean. than hand-rolling `rounded border bg-card`. - External links: use `` from `@jsonbored/ui-kit`, not a raw `` — it sets `rel=noreferrer` and filters unsafe/private URLs. + - Stacking order: use one of the named `--mg-z-*` layer tokens + (`packages/ui-kit/src/styles.css`), never a bare `z-10`/`z-20`/etc. or a + one-off `z-[N]`. From lowest to highest: + + | Token | Value | Use for | + |---|---|---| + | `--mg-z-sticky` | 10 | Sticky theads/toolbars, scroll shadows, in-flow progress bars | + | `--mg-z-raised` | 20 | Elements that must clear sticky content within the same page section | + | `--mg-z-nav` | 30 | Site header/nav chrome | + | `--mg-z-overlay` | 40 | Drawers, back-to-top, hover cards, lightweight menus | + | `--mg-z-modal` | 50 | Dialogs, popovers, sheets, command palette (matches Radix's own default) | + | `--mg-z-progress` | 60 | Route-transition progress bar — must beat modal | + | `--mg-z-skip-link` | 100 | a11y skip-link — must beat everything | + + The only standing exception: the sticky corner cell in the two compare + drawers (`subnets-compare-drawer.tsx`, `validators-compare-drawer.tsx`) uses + raw `z-[1]`/`z-[2]` for micro-stacking inside the table's own local + stacking context — not a global layer, so it doesn't belong on this scale. - See `docs/ssr-safety.md` for the hydration-safety rules (also partly ESLint-enforced). - Keep diffs focused. Don't reformat or refactor unrelated files in a feature PR. diff --git a/apps/ui/eslint.config.ts b/apps/ui/eslint.config.ts index 75e9291ecc..ac03ad6c0e 100644 --- a/apps/ui/eslint.config.ts +++ b/apps/ui/eslint.config.ts @@ -116,6 +116,17 @@ const ELEVATION_RULES = [ }, ]; +// #7841: bare z-* stacking steps collapsed into a named --mg-z-* layer scale +// (packages/ui-kit/src/styles.css). Also flags the 6 documented z-[1]/z-[2] +// sticky-cell micro-stacking exceptions in the two compare drawers -- that's +// intentional (matches the residual-worklist convention other guardrails use). +const Z_INDEX_RULES = [ + { + selector: "Literal[value=/\\bz-(\\[[0-9]+\\]|[0-9]+\\b)/]", + message: "Raw z-index step. Use one of the --mg-z-* layer tokens (see styles.css).", + }, +]; + export default tseslint.config( // .source is fumadocs-mdx's generated content collection output (see // source.config.ts) -- codegen, not authored code, same treatment as dist. @@ -184,6 +195,7 @@ export default tseslint.config( ...PRIMITIVE_STEER_RULES, ...SSR_SAFETY_RULES, ...ELEVATION_RULES, + ...Z_INDEX_RULES, ], }, }, diff --git a/apps/ui/src/components/metagraphed/analytics/coverage-matrix.tsx b/apps/ui/src/components/metagraphed/analytics/coverage-matrix.tsx index 2d7e47d5c8..fa7175198c 100644 --- a/apps/ui/src/components/metagraphed/analytics/coverage-matrix.tsx +++ b/apps/ui/src/components/metagraphed/analytics/coverage-matrix.tsx @@ -137,7 +137,7 @@ export function CoverageMatrix({ topN = 24 }: { topN?: number }) { - {KINDS.map((k) => ( @@ -159,7 +159,7 @@ export function CoverageMatrix({ topN = 24 }: { topN?: number }) { key={r.netuid} className="border-b border-border last:border-b-0 hover:bg-paper/30" > -
+ Subnet +
Skip to main content {/* Top bar */}