docs+frontend: strengthen anti-nesting chrome invariant and dApp pass #653

Closed
opened 2026-08-26 01:11:04 +00:00 by PlasticDigits · 37 comments
PlasticDigits commented 2026-08-26 01:11:04 +00:00 (Migrated from gitlab.com)

Summary

The design system already says “One chrome layer per region” (#561 L561-2, docs/design-system.md), but the wording explicitly allows nested card-glass inside a page shell-panel for “distinct inner blocks.” That exception is how /protocol Global stats became a panel wrapping eleven StatBox card-glass tiles (same pattern on Protocol fees, Charts overview strip, Trader summary). The invariant is documented but too weak, not enforced, and not applied to metric grids.

Bundle into one issue: strengthen the anti-nesting / one-chrome-layer invariant in docs + skills, add a checkable rule (what is forbidden vs allowlisted), and run a dApp chrome pass that flattens remaining metric-grid nests. Do not split “update the sentence” vs “audit Charts” vs “change StatBox.”

/protocol Global stats + fees flattening (inline Δ%, volume %, daily chart) is #652 — implement that page there. This ticket owns the invariant and the rest of the app.

Related: #652 (Protocol inline Δ% + flatten that page), #561 (Trade one-chrome; L561-2 lists Swap/Pool/Limits/Charts as audited — Protocol was not), #488 (design system), #489 (copy density; nested cards add visual noise), #550 / #569 / #586 (Protocol stats chrome).

Current codebase

Layer Behavior today
Spec docs/design-system.md Principles table: “Do not wrap shell-panel / shell-panel-strong / card-glass in another of the same family for the same visual region. Page background → one section surface → content. Nested card-glass inside a page shell-panel is OK for distinct inner blocks (Swap IO cards). First applied on /trade (#561).” There is no “excessive nesting” / metric-grid clause.
Skill AGENTS_FRONTEND_DESIGN_SYSTEM.md rule 3 repeats the same exception.
Frontend.md L561-2 (“One chrome layer”) lives under Trade desktop workspace, not a global UI invariant. It claims Swap / Pool / Limits / Charts were audited; Charts overview is still shell-panel + StatBox cards.
StatBox StatBox.tsx always applies card-glass !p-3. Any StatBox inside shell-panel is automatic nest.
Known nests (metric grids) ProtocolGlobalStats.tsx (11 tiles); ProtocolFeeStats.tsx (6 tiles); ProtocolOracleCard.tsx (StatBox grid + optional inner card-glass table); ChartsPage.tsx overview strip (shell-panel grid + StatBoxes) and pair 24h stats panel; TraderSummaryStats.tsx (shell-panel + 4 StatBoxes).
Allowlisted distinct blocks (keep) Swap Pay/Receive swap-io-card-* card-glass inside the swap shell-panel — two interactive IO regions. Trade ticket / book / chart are sibling shell-panel* cells, not a panel-of-panels for the same region (L561-1 chart must not wrap PriceChart in card-glass).
Primitives .shell-panel and .card-glass both use 24px radius, border, blur, and a surface fill. Stacking them on a stats grid reads as a card of cards.
Tests StatBox.test.tsx does not assert chrome class. No rg / ESLint rule for shell-panel wrapping card-glass. python3 scripts/check_design_tokens.py does not cover nesting.
QA QA_TEMPLATE.md §10 is theme/tokens, not nesting depth.

Why this is needed

  1. The written rule blesses the bug. Agents following the skill will keep dropping StatBox into section panels. Protocol production UI is the exhibit: a bordered section of bordered tiles.
  2. #561’s audit list is stale / incomplete. L561-2 says Charts was audited; the overview strip is the same nest. Protocol, Trader, and oracle cards were never in scope.
  3. Cognitive load. Extra chrome rings compete with the number. #489 already fights copy overload; visual nesting is the layout twin.
  4. Without a pass, Protocol-only flatten will regress. The next stats feature will copy StatBox default card-glass. The invariant must be global, with a short allowlist, plus a mechanical check.

Constraints / guardrails

  1. Do not flatten Swap IO cards. Pay/Receive card-glass inside the swap panel stays the canonical exception (distinct interactive blocks). Document it as the exception, not the default.
  2. Do not flatten Trade sibling panels. Book / chart / ticket / tape remain separate shell-panel* regions (L561-1–L561-3). Do not wrap PriceChart (shell-panel-strong) in card-glass. Do not reintroduce PanelResizeHandle.
  3. Protocol Global stats + fees are owned by the sibling /protocol stats issue (inline Δ% + volume chart). This pass must not fight that layout: consume the shared StatBox variant="flat" (or equivalent) those changes add; if this lands first, introduce flat here and leave Protocol tiles visually flat even before Δ% merges.
  4. Metric grids are not “distinct inner blocks.” A label+value census tile is content, not a second chrome region. Forbidden: shell-panel / shell-panel-strong containing a grid of card-glass (including default StatBox) for stats. Allowed: one section surface + typographic rows / hairline dividers / CSS grid without a second radius+border+blur.
  5. Tables / lists inside a panel may use a single inner surface or none (Protocol fee source table is already a bare <table> — keep). Do not wrap every <tr> in card-glass.
  6. One extra layer max, and only when the inner block is interactive or media. Examples that may keep card-glass inside shell-panel: Swap IO, pre-submit summaries, connect-wallet rows, a single chart/table well. Not: 4–11 repeated stat chips.
  7. No new color system. Tokens stay #488 (--ink, --line, --panel-bg, --card-bg). Gold is not a fill. Light + dark both verified.
  8. Do not change JSON / indexer / copy semantics except chrome + a11y (title / aria-label must survive if StatBox markup changes). Charts USD-only (#548), trailing-window titles (#576), hub/oracle order (#550) stay.
  9. Backward compatible StatBox. Default remains card so isolated uses (if any) do not silently lose a surface. Call sites inside a panel must pass flat (or a wrapper). Prefer fixing call sites over a silent default flip that restyles every page at once without review.
  10. Mechanical guard. Add a cheap check (Vitest inventory, rg script, or ESLint) that fails when StatBox (card default) is a descendant of shell-panel* in listed pages — or document an allowlist file. Do not bind-mount indexer/ for cargo. Frontend-only verify is enough for this ticket.
  11. No lecture copy. Strengthening the invariant is docs/skills, not a retail banner.
  12. Scope the pass. In scope: Protocol oracle/hub stat grids (if still nested after the sibling issue), Charts overview + pair 24h StatBox grids, Trader summary, any other shell-panel+StatBox hit from rg. Out of scope: marketing OG (#578), wallet modals as such, community-tax manager forms unless they are the same metric-grid pattern.

Relevant files

Path Role
docs/design-system.md Strengthen principle; add forbidden / allowlist
skills/AGENTS_FRONTEND_DESIGN_SYSTEM.md Agent rule 3 rewrite
docs/frontend.md Promote one-chrome to a global subsection; keep L561-2 as Trade application
QA_TEMPLATE.md §10 Nesting checkbox
frontend-dapp/src/components/ui/StatBox.tsx flat variant
frontend-dapp/src/pages/ChartsPage.tsx Overview + pair stats flatten
frontend-dapp/src/components/trader/TraderSummaryStats.tsx Flatten
frontend-dapp/src/components/protocol/ProtocolOracleCard.tsx Flatten StatBox grid; keep one table well if needed
frontend-dapp/src/components/protocol/ProtocolDexHubPrices.tsx Audit
frontend-dapp/src/index.css Optional .stat-flat primitive
scripts/check_design_tokens.py or new scripts/check_chrome_nesting.py Mechanical guard
Charts / Trader / Protocol tests + make verify-issue-561 / 548 / 550 / 551 / 553 No layout-testid regressions
  1. Rewrite the principle (same place as today, plus docs/frontend.md global §):
    • Stack: page --bg-* → one shell-panel* per region → content.
    • Forbidden: shell-panel* wrapping another shell-panel*, or wrapping a grid of card-glass / default StatBox, for the same region.
    • Allowlist: Swap IO cards; a single inner well for a table/chart; Trade sibling panels (not nested).
    • Metric tiles use StatBox variant="flat" (or .stat-flat): typography + optional Δ%, no second radius/border/blur.
  2. Implement flat once (shared with the Protocol stats sibling). Default card unchanged.
  3. Pass: Charts overview, Charts pair 24h stats, Trader summary, Protocol oracle/hub stat grids. Skip Swap IO. Protocol Global stats / fees: land in the sibling issue or apply flat here if that issue has not merged.
  4. Guard: script or test that lists remaining shell-panel+card-glass descendants and fails on new hits outside the allowlist file.
  5. Verify matrix: /, /charts, /charts/:pair, /trader/:addr, /protocol, /trade (L561), /pool, /limits — light + dark, 375 and 1280.

Acceptance criteria

  • Design-system principle + skill rule 3 no longer say nested card-glass is generally OK. Exception list is explicit and short.
  • docs/frontend.md has a global one-chrome / anti-nesting subsection (Trade L561-2 points at it).
  • StatBox supports flat (or successor). Metric grids in scope use it.
  • Charts overview strip and pair 24h stats: no card-glass chips inside the section panel.
  • Trader profile summary: same.
  • Protocol oracle / hub stat chips: same (unless they are a single distinct well).
  • Swap Pay/Receive cards still card-glass. Trade chart still a single shell-panel-strong (L561-1).
  • Mechanical check in CI / make verify-issue-* for this ticket (or hooked into check_design_tokens / lint-frontend).
  • QA_TEMPLATE §10 includes a nesting checkbox.
  • Light + dark; 375px / 1280px: numbers still readable; no “empty ring” tiles.
  • No indexer / overview JSON changes required by this ticket.

Test plan (all paths)

  • rg 'shell-panel' -g '*.tsx' inventory: each hit classified allowlist vs flattened; snapshot the allowlist in the check script.
  • RTL: Charts overview testids (charts-overview-volume-usd, …) still present; values unchanged (#548 / #576 titles).
  • Trader trader-total-volume-usd still compact USD (#553 / #551).
  • Protocol oracle tabs + StatBox values (#515 / #571 / #580) still render; ?ticker= allowlist unchanged.
  • make verify-issue-561 (Trade chrome), 548 (Charts), 550 / sibling Protocol issue, 551 / 553 / 560 (trader/portfolio).
  • StatBox unit: default still has card-glass; flat does not.
  • Keyboard focus on any newly flattened controls still --focus-ring.
  • Theme toggle: no leftover brown/gold fills (#488).

Test plan (attack, hack, and abuse)

  • No new attack surface. This is CSS/DOM. Do not add HTML from indexer strings when restyling (XSS already covered by text nodes — keep it).
  • Do not weaken allowlists (?ticker=, factory addresses) while touching Protocol oracle markup.
  • Click / hit-target regression. Flattened stats must not become accidental buttons or swallow clicks meant for tabs/links.
  • Contrast. Flat tiles on --panel-bg must still meet existing ink contrast (no --ink-subtle on --card-bg leftovers that disappear when card-glass is removed).
  • Script injection via classNames. Allowlist file / check script must not eval page source; parse statically.
  • Do not hide outage banners while collapsing chrome (#215).

Verification criteria

  • make lint-frontend + make test-frontend (or scoped Protocol/Charts/Trader/StatBox) green.
  • python3 scripts/check_design_tokens.py (and new nesting check) green.
  • make verify-issue-561 green.
  • Manual walk: Swap (IO cards still nested — correct), Trade (no chart card-in-card), Charts overview, Trader, Protocol oracle — 375px + 1280px, light + dark.
  • Docs/skills/QA template match the allowlist. Agents grepping “nested card-glass is OK” should hit the exception list, not a blanket yes.
  • Sibling #652 linked; no duplicate restyle of Global stats after that merge.
## Summary The design system already says **“One chrome layer per region”** ([#561](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/561) **L561-2**, [`docs/design-system.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/docs/design-system.md)), but the wording **explicitly allows** nested `card-glass` inside a page `shell-panel` for “distinct inner blocks.” That exception is how `/protocol` **Global stats** became a panel wrapping **eleven** `StatBox` `card-glass` tiles (same pattern on Protocol fees, Charts overview strip, Trader summary). The invariant is documented but **too weak**, not enforced, and not applied to metric grids. Bundle into **one** issue: **strengthen** the anti-nesting / one-chrome-layer invariant in docs + skills, add a **checkable** rule (what is forbidden vs allowlisted), and run a **dApp chrome pass** that flattens remaining metric-grid nests. Do **not** split “update the sentence” vs “audit Charts” vs “change StatBox.” `/protocol` Global stats + fees flattening (inline Δ%, volume %, daily chart) is **[#652](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/652)** — implement that page there. This ticket owns the **invariant** and the **rest of the app**. Related: [#652](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/652) (Protocol inline Δ% + flatten that page), [#561](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/561) (Trade one-chrome; L561-2 lists Swap/Pool/Limits/Charts as audited — Protocol was not), [#488](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/488) (design system), [#489](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/489) (copy density; nested cards add visual noise), [#550](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/550) / [#569](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/569) / [#586](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/586) (Protocol stats chrome). ## Current codebase | Layer | Behavior today | |-------|----------------| | **Spec** | [`docs/design-system.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/docs/design-system.md) Principles table: “Do **not** wrap `shell-panel` / `shell-panel-strong` / `card-glass` in another of the same family for the **same visual region**. Page background → one section surface → content. **Nested `card-glass` inside a page `shell-panel` is OK for distinct inner blocks (Swap IO cards).** First applied on `/trade` (#561).” There is **no** “excessive nesting” / metric-grid clause. | | **Skill** | [`AGENTS_FRONTEND_DESIGN_SYSTEM.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/skills/AGENTS_FRONTEND_DESIGN_SYSTEM.md) rule 3 repeats the same exception. | | **Frontend.md** | **L561-2** (“One chrome layer”) lives under **Trade desktop workspace**, not a global UI invariant. It claims Swap / Pool / Limits / Charts were audited; Charts overview is still `shell-panel` + `StatBox` cards. | | **StatBox** | [`StatBox.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/ui/StatBox.tsx) **always** applies `card-glass !p-3`. Any `StatBox` inside `shell-panel` is automatic nest. | | **Known nests (metric grids)** | [`ProtocolGlobalStats.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/protocol/ProtocolGlobalStats.tsx) (11 tiles); [`ProtocolFeeStats.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/protocol/ProtocolFeeStats.tsx) (6 tiles); [`ProtocolOracleCard.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/protocol/ProtocolOracleCard.tsx) (StatBox grid + optional inner `card-glass` table); [`ChartsPage.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/pages/ChartsPage.tsx) overview strip (`shell-panel grid` + StatBoxes) and pair 24h stats panel; [`TraderSummaryStats.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/trader/TraderSummaryStats.tsx) (`shell-panel` + 4 StatBoxes). | | **Allowlisted distinct blocks (keep)** | Swap Pay/Receive [`swap-io-card-*`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/index.css) `card-glass` inside the swap `shell-panel` — two **interactive** IO regions. Trade ticket / book / chart are **sibling** `shell-panel*` cells, not a panel-of-panels for the same region (**L561-1** chart must not wrap `PriceChart` in `card-glass`). | | **Primitives** | [`.shell-panel`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/index.css) and `.card-glass` both use 24px radius, border, blur, and a surface fill. Stacking them on a stats grid reads as a card of cards. | | **Tests** | [`StatBox.test.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/ui/__tests__/StatBox.test.tsx) does not assert chrome class. No `rg` / ESLint rule for `shell-panel` wrapping `card-glass`. `python3 scripts/check_design_tokens.py` does not cover nesting. | | **QA** | [`QA_TEMPLATE.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/QA_TEMPLATE.md) §10 is theme/tokens, not nesting depth. | ## Why this is needed 1. **The written rule blesses the bug.** Agents following the skill will keep dropping `StatBox` into section panels. Protocol production UI is the exhibit: a bordered section of bordered tiles. 2. **#561’s audit list is stale / incomplete.** L561-2 says Charts was audited; the overview strip is the same nest. Protocol, Trader, and oracle cards were never in scope. 3. **Cognitive load.** Extra chrome rings compete with the number. #489 already fights copy overload; visual nesting is the layout twin. 4. **Without a pass, Protocol-only flatten will regress.** The next stats feature will copy `StatBox` default `card-glass`. The invariant must be **global**, with a short allowlist, plus a mechanical check. ## Constraints / guardrails 1. **Do not flatten Swap IO cards.** Pay/Receive `card-glass` inside the swap panel stays the **canonical exception** (distinct interactive blocks). Document it as the exception, not the default. 2. **Do not flatten Trade sibling panels.** Book / chart / ticket / tape remain separate `shell-panel*` regions (**L561-1–L561-3**). Do **not** wrap `PriceChart` (`shell-panel-strong`) in `card-glass`. Do not reintroduce `PanelResizeHandle`. 3. **Protocol Global stats + fees** are owned by the sibling `/protocol` stats issue (inline Δ% + volume chart). This pass **must not** fight that layout: consume the shared `StatBox variant="flat"` (or equivalent) those changes add; if this lands first, introduce `flat` here and leave Protocol tiles visually flat even before Δ% merges. 4. **Metric grids are not “distinct inner blocks.”** A label+value census tile is **content**, not a second chrome region. Forbidden: `shell-panel` / `shell-panel-strong` **containing** a grid of `card-glass` (including default `StatBox`) for stats. Allowed: one section surface + typographic rows / hairline dividers / CSS grid **without** a second radius+border+blur. 5. **Tables / lists** inside a panel may use a **single** inner surface **or** none (Protocol fee source table is already a bare `<table>` — keep). Do not wrap every `<tr>` in `card-glass`. 6. **One extra layer max, and only when the inner block is interactive or media.** Examples that may keep `card-glass` inside `shell-panel`: Swap IO, pre-submit summaries, connect-wallet rows, a single chart/table well. Not: 4–11 repeated stat chips. 7. **No new color system.** Tokens stay #488 (`--ink`, `--line`, `--panel-bg`, `--card-bg`). Gold is not a fill. Light + dark both verified. 8. **Do not change JSON / indexer / copy semantics** except chrome + a11y (`title` / `aria-label` must survive if StatBox markup changes). Charts USD-only (#548), trailing-window titles (#576), hub/oracle order (#550) stay. 9. **Backward compatible `StatBox`.** Default remains `card` so isolated uses (if any) do not silently lose a surface. Call sites **inside** a panel must pass `flat` (or a wrapper). Prefer fixing call sites over a silent default flip that restyles every page at once without review. 10. **Mechanical guard.** Add a cheap check (Vitest inventory, `rg` script, or ESLint) that fails when `StatBox` (card default) is a descendant of `shell-panel*` in listed pages — or document an allowlist file. Do not bind-mount `indexer/` for cargo. Frontend-only verify is enough for this ticket. 11. **No lecture copy.** Strengthening the invariant is docs/skills, not a retail banner. 12. **Scope the pass.** In scope: Protocol oracle/hub **stat grids** (if still nested after the sibling issue), Charts overview + pair 24h StatBox grids, Trader summary, any other `shell-panel`+`StatBox` hit from `rg`. Out of scope: marketing OG (#578), wallet modals as such, community-tax manager forms unless they are the same metric-grid pattern. ## Relevant files | Path | Role | |------|------| | [`docs/design-system.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/docs/design-system.md) | Strengthen principle; add forbidden / allowlist | | [`skills/AGENTS_FRONTEND_DESIGN_SYSTEM.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/skills/AGENTS_FRONTEND_DESIGN_SYSTEM.md) | Agent rule 3 rewrite | | [`docs/frontend.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/docs/frontend.md) | Promote one-chrome to a **global** subsection; keep L561-2 as Trade application | | [`QA_TEMPLATE.md`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/QA_TEMPLATE.md) §10 | Nesting checkbox | | [`frontend-dapp/src/components/ui/StatBox.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/ui/StatBox.tsx) | `flat` variant | | [`frontend-dapp/src/pages/ChartsPage.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/pages/ChartsPage.tsx) | Overview + pair stats flatten | | [`frontend-dapp/src/components/trader/TraderSummaryStats.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/trader/TraderSummaryStats.tsx) | Flatten | | [`frontend-dapp/src/components/protocol/ProtocolOracleCard.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/protocol/ProtocolOracleCard.tsx) | Flatten StatBox grid; keep one table well if needed | | [`frontend-dapp/src/components/protocol/ProtocolDexHubPrices.tsx`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/components/protocol/ProtocolDexHubPrices.tsx) | Audit | | [`frontend-dapp/src/index.css`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/frontend-dapp/src/index.css) | Optional `.stat-flat` primitive | | [`scripts/check_design_tokens.py`](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/blob/main/scripts/check_design_tokens.py) or new `scripts/check_chrome_nesting.py` | Mechanical guard | | Charts / Trader / Protocol tests + `make verify-issue-561` / `548` / `550` / `551` / `553` | No layout-testid regressions | ## Recommended direction 1. **Rewrite the principle** (same place as today, plus `docs/frontend.md` global §): - Stack: page `--bg-*` → **one** `shell-panel*` per region → **content**. - **Forbidden:** `shell-panel*` wrapping another `shell-panel*`, or wrapping a **grid of** `card-glass` / default `StatBox`, for the same region. - **Allowlist:** Swap IO cards; a **single** inner well for a table/chart; Trade **sibling** panels (not nested). - **Metric tiles** use `StatBox variant="flat"` (or `.stat-flat`): typography + optional Δ%, no second radius/border/blur. 2. **Implement `flat` once** (shared with the Protocol stats sibling). Default `card` unchanged. 3. **Pass:** Charts overview, Charts pair 24h stats, Trader summary, Protocol oracle/hub stat grids. Skip Swap IO. Protocol Global stats / fees: land in the sibling issue or apply `flat` here if that issue has not merged. 4. **Guard:** script or test that lists remaining `shell-panel`+`card-glass` descendants and fails on new hits outside the allowlist file. 5. **Verify matrix:** `/`, `/charts`, `/charts/:pair`, `/trader/:addr`, `/protocol`, `/trade` (L561), `/pool`, `/limits` — light + dark, 375 and 1280. ## Acceptance criteria - [ ] Design-system principle + skill rule 3 no longer say nested `card-glass` is generally OK. Exception list is explicit and short. - [ ] `docs/frontend.md` has a **global** one-chrome / anti-nesting subsection (Trade L561-2 points at it). - [ ] `StatBox` supports `flat` (or successor). Metric grids in scope use it. - [ ] Charts overview strip and pair 24h stats: no `card-glass` chips inside the section panel. - [ ] Trader profile summary: same. - [ ] Protocol oracle / hub stat chips: same (unless they are a single distinct well). - [ ] Swap Pay/Receive cards still `card-glass`. Trade chart still a single `shell-panel-strong` (**L561-1**). - [ ] Mechanical check in CI / `make verify-issue-*` for this ticket (or hooked into `check_design_tokens` / lint-frontend). - [ ] QA_TEMPLATE §10 includes a nesting checkbox. - [ ] Light + dark; 375px / 1280px: numbers still readable; no “empty ring” tiles. - [ ] No indexer / overview JSON changes required by this ticket. ## Test plan (all paths) - [ ] `rg 'shell-panel' -g '*.tsx'` inventory: each hit classified allowlist vs flattened; snapshot the allowlist in the check script. - [ ] RTL: Charts overview testids (`charts-overview-volume-usd`, …) still present; values unchanged (#548 / #576 titles). - [ ] Trader `trader-total-volume-usd` still compact USD (#553 / #551). - [ ] Protocol oracle tabs + StatBox values (#515 / #571 / #580) still render; `?ticker=` allowlist unchanged. - [ ] `make verify-issue-561` (Trade chrome), `548` (Charts), `550` / sibling Protocol issue, `551` / `553` / `560` (trader/portfolio). - [ ] StatBox unit: default still has `card-glass`; `flat` does not. - [ ] Keyboard focus on any newly flattened controls still `--focus-ring`. - [ ] Theme toggle: no leftover brown/gold fills (#488). ## Test plan (attack, hack, and abuse) - [ ] **No new attack surface.** This is CSS/DOM. Do not add HTML from indexer strings when restyling (XSS already covered by text nodes — keep it). - [ ] **Do not weaken allowlists** (`?ticker=`, factory addresses) while touching Protocol oracle markup. - [ ] **Click / hit-target regression.** Flattened stats must not become accidental buttons or swallow clicks meant for tabs/links. - [ ] **Contrast.** Flat tiles on `--panel-bg` must still meet existing ink contrast (no `--ink-subtle` on `--card-bg` leftovers that disappear when `card-glass` is removed). - [ ] **Script injection via classNames.** Allowlist file / check script must not `eval` page source; parse statically. - [ ] **Do not hide outage banners** while collapsing chrome (#215). ## Verification criteria - [ ] `make lint-frontend` + `make test-frontend` (or scoped Protocol/Charts/Trader/StatBox) green. - [ ] `python3 scripts/check_design_tokens.py` (and new nesting check) green. - [ ] `make verify-issue-561` green. - [ ] Manual walk: Swap (IO cards **still** nested — correct), Trade (no chart card-in-card), Charts overview, Trader, Protocol oracle — 375px + 1280px, light + dark. - [ ] Docs/skills/QA template match the allowlist. Agents grepping “nested card-glass is OK” should hit the **exception list**, not a blanket yes. - [ ] Sibling [#652](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/issues/652) linked; no duplicate restyle of Global stats after that merge.
PlasticDigits commented 2026-08-26 01:11:10 +00:00 (Migrated from gitlab.com)

mentioned in issue #652

mentioned in issue #652
PlasticDigits commented 2026-08-26 01:35:08 +00:00 (Migrated from gitlab.com)

mentioned in commit 30234a125f

mentioned in commit 30234a125f06e4952a0da2ef8d63310fe887a9f4
PlasticDigits commented 2026-08-26 01:37:11 +00:00 (Migrated from gitlab.com)

mentioned in merge request !1151

mentioned in merge request !1151
PlasticDigits commented 2026-08-26 01:48:57 +00:00 (Migrated from gitlab.com)

mentioned in merge request !1152

mentioned in merge request !1152
PlasticDigits commented 2026-08-26 01:57:31 +00:00 (Migrated from gitlab.com)

mentioned in commit 7245ac1c74

mentioned in commit 7245ac1c74fe87eb122ad44ac714839365ba7a09
PlasticDigits commented 2026-08-26 01:57:33 +00:00 (Migrated from gitlab.com)

mentioned in commit c90c893493

mentioned in commit c90c893493c228199fee61bf49fc8b97ccd5579b
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-08-26 01:57:34 +00:00
PlasticDigits commented 2026-08-26 01:58:32 +00:00 (Migrated from gitlab.com)

mentioned in issue #654

mentioned in issue #654
PlasticDigits commented 2026-08-26 01:58:33 +00:00 (Migrated from gitlab.com)

marked as related to #654

marked as related to #654
PlasticDigits commented 2026-08-26 01:58:44 +00:00 (Migrated from gitlab.com)

Merge !1151 is on main (c90c8934) after resolving conflicts onto !1153 + !1152 (7245ac1c). Resolution kept #652 inline Δ% / daily chart on Protocol tiles and #653 StatBox stat-flat + hint + chrome guard. Local make verify-issue-653 on the source tip was 14/14. After the conflict resolve: StatBox + Protocol + Charts + Trader RTL 82/82, check_chrome_nesting.py and check_design_tokens.py green.

Problems / leftovers (tracked on #654 — do not reopen this issue unless a merged invariant is wrong):

  • GitLab CI on !1151 failed ci_quota_exceeded (not a code defect). Did not wait for CI.
  • Manual walk (/charts, /trader/:addr, /protocol, /, Swap IO still card-glass, Trade chart still single shell-panel-strong, 375 + 1280, light + dark, theme toggle) was not run.
Merge !1151 is on `main` (`c90c8934`) after resolving conflicts onto !1153 + !1152 (`7245ac1c`). Resolution kept #652 inline Δ% / daily chart on Protocol tiles and #653 `StatBox` `stat-flat` + `hint` + chrome guard. Local `make verify-issue-653` on the source tip was 14/14. After the conflict resolve: StatBox + Protocol + Charts + Trader RTL 82/82, `check_chrome_nesting.py` and `check_design_tokens.py` green. Problems / leftovers (tracked on #654 — do not reopen this issue unless a merged invariant is wrong): - GitLab CI on !1151 failed `ci_quota_exceeded` (not a code defect). Did not wait for CI. - Manual walk (`/charts`, `/trader/:addr`, `/protocol`, `/`, Swap IO still `card-glass`, Trade chart still single `shell-panel-strong`, 375 + 1280, light + dark, theme toggle) was not run.
PlasticDigits commented 2026-08-26 03:06:33 +00:00 (Migrated from gitlab.com)

mentioned in issue #655

mentioned in issue #655
PlasticDigits commented 2026-08-26 03:07:40 +00:00 (Migrated from gitlab.com)

mentioned in issue #656

mentioned in issue #656
PlasticDigits commented 2026-08-26 03:08:08 +00:00 (Migrated from gitlab.com)

mentioned in issue #657

mentioned in issue #657
PlasticDigits commented 2026-08-26 03:08:10 +00:00 (Migrated from gitlab.com)

marked as related to #657

marked as related to #657
PlasticDigits commented 2026-08-26 04:08:08 +00:00 (Migrated from gitlab.com)

mentioned in issue #659

mentioned in issue #659
PlasticDigits commented 2026-08-26 04:11:19 +00:00 (Migrated from gitlab.com)

mentioned in issue #660

mentioned in issue #660
PlasticDigits commented 2026-08-26 04:11:24 +00:00 (Migrated from gitlab.com)

marked as related to #660

marked as related to #660
PlasticDigits commented 2026-08-26 04:13:29 +00:00 (Migrated from gitlab.com)

mentioned in issue #662

mentioned in issue #662
PlasticDigits commented 2026-08-26 04:13:33 +00:00 (Migrated from gitlab.com)

mentioned in issue #663

mentioned in issue #663
PlasticDigits commented 2026-08-26 04:15:27 +00:00 (Migrated from gitlab.com)

mentioned in issue #664

mentioned in issue #664
PlasticDigits commented 2026-08-26 04:16:13 +00:00 (Migrated from gitlab.com)

mentioned in issue #665

mentioned in issue #665
PlasticDigits commented 2026-08-26 04:17:22 +00:00 (Migrated from gitlab.com)

mentioned in issue #666

mentioned in issue #666
PlasticDigits commented 2026-08-26 04:17:27 +00:00 (Migrated from gitlab.com)

marked as related to #666

marked as related to #666
PlasticDigits commented 2026-08-26 04:18:46 +00:00 (Migrated from gitlab.com)

mentioned in issue #667

mentioned in issue #667
PlasticDigits commented 2026-08-26 04:18:49 +00:00 (Migrated from gitlab.com)

marked as related to #667

marked as related to #667
PlasticDigits commented 2026-08-26 04:19:23 +00:00 (Migrated from gitlab.com)

mentioned in issue #668

mentioned in issue #668
PlasticDigits commented 2026-08-26 04:19:24 +00:00 (Migrated from gitlab.com)

mentioned in issue #669

mentioned in issue #669
PlasticDigits commented 2026-08-26 04:19:26 +00:00 (Migrated from gitlab.com)

marked as related to #669

marked as related to #669
PlasticDigits commented 2026-08-26 04:20:46 +00:00 (Migrated from gitlab.com)

mentioned in issue #670

mentioned in issue #670
PlasticDigits commented 2026-08-26 04:22:42 +00:00 (Migrated from gitlab.com)

mentioned in issue #671

mentioned in issue #671
PlasticDigits commented 2026-08-27 00:17:42 +00:00 (Migrated from gitlab.com)

mentioned in issue #677

mentioned in issue #677
PlasticDigits commented 2026-08-27 00:20:54 +00:00 (Migrated from gitlab.com)

mentioned in issue #680

mentioned in issue #680
PlasticDigits commented 2026-08-27 09:00:10 +00:00 (Migrated from gitlab.com)

mentioned in issue #689

mentioned in issue #689
PlasticDigits commented 2026-08-28 05:22:09 +00:00 (Migrated from gitlab.com)

mentioned in issue #692

mentioned in issue #692
PlasticDigits commented 2026-08-28 05:28:47 +00:00 (Migrated from gitlab.com)

mentioned in issue #693

mentioned in issue #693
PlasticDigits commented 2026-08-29 08:04:47 +00:00 (Migrated from gitlab.com)

mentioned in issue #703

mentioned in issue #703
PlasticDigits commented 2026-08-31 05:36:04 +00:00 (Migrated from gitlab.com)

mentioned in issue #713

mentioned in issue #713
PlasticDigits commented 2026-08-31 16:08:49 +00:00 (Migrated from gitlab.com)

mentioned in issue #715

mentioned in issue #715
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
code/cl8y-dex-terraclassic#653
No description provided.