Skip to content

Retire --shadow-focus for the sanctioned focus outline (#261) - #1807

Merged
BigSimmo merged 4 commits into
mainfrom
claude/codex-m4c-retire-shadow-nliak3
Aug 11, 2026
Merged

Retire --shadow-focus for the sanctioned focus outline (#261)#1807
BigSimmo merged 4 commits into
mainfrom
claude/codex-m4c-retire-shadow-nliak3

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Summary

  • Retires --shadow-focus (DS Track A2, ledger #261). The token packed a 3px accent halo in front of --shadow-soft, so its one consumer — .chat-composer-shell-delta:focus-within — painted a companion focus ring on top of the accent border swap. That is the second focus affordance the shared :focus-visible treatment in globals.css is written to prevent (GATES Gate 3). The composer now uses the sanctioned outline: 2px solid var(--focus) at outline-offset: 2px, and both theme declarations of the token are deleted.
  • Focus no longer overrides box-shadow. The retired token carried --shadow-soft as its own second layer, so leaving the resting elevation alone keeps the pill seated at exactly the same height focused as at rest — the outline is the only thing that changes.
  • Adds a mutation-verified guard in tests/design-token-contract.test.ts rejecting both a --shadow-focus: declaration and a var(--shadow-focus) consumer, across globals.css and the v2 layer. Deliberately not the whole-file substring check used for --shadow-tight: the composer rule names the retired token in a comment on purpose, so the next author reaching for a focus halo finds the reason it is gone.
  • Tightens the design-system contract baseline: legacyShadowAliases 127 → 125 with the globals.css per-path pin 3 → 1. The deleted declarations' value ended in var(--shadow-soft), so they scored as two soft aliases — the indirection GATES already documents. Left un-ratcheted because it is pre-existing slack unrelated to this diff: rawPaddingLiterals 67 → 65, rawGapLiterals 34 → 32, layoutTransitionExceptions 12 → 11.
  • Corrects the premise this task inherited from HANDOVER-2026-08-07 Track A2, which called it "a visible focus-state change on the search composer". It is not a visible production change. chatComposerShell is imported only by calculators/search-detail.tsx and its mockup twin; production /calculators renders chatComposerShellBase + answer-footer-search-pill instead, and CalculatorSearchHome is reached only from two unrouted mockup exports. Probing all 37 static production routes in Chromium found zero renders of the class; the single live render is /mockups/calculators-search. The inherited note was right that a --include=*.tsx grep misses the consumer — it is in CSS — but wrong about its reach. The correction is recorded in that handover's own "Measured wrong so far" list, per the file's stated convention of not rewriting its body.
  • Marks the token done in TOKENS.md, SPEC.md, design-system.md and the Gate 3 evidence note, refreshes the now-stale alias breakdown in GATES.md to the measured 125 (soft 69, elevated 17, hover 17, card 12, lux 8, lift 2), and archives #261 in the outstanding-issues ledger.

Verification

  • npm run verify:pr-local

Every step passed except one pre-existing failure unrelated to this diff: tests/pr-handoff-stop.test.ts > emits handoff context only when the marker file exists. Baselined rather than assumed — with these changes stashed, the untouched base e8b61d8 fails the same single assertion (Tests 1 failed | 10 passed (11)). Because the runner stops there, build and check:rag:fixtures were re-run directly afterwards and both passed:

Test Files  1 failed | 555 passed (556)
     Tests  1 failed | 6048 passed | 4 skipped (6053)
completed: check:runtime, check:installed-lock-parity, format:changed, sitemap:check,
  docs:check-index, docs:check-inventory, docs:check-scripts, docs:check-links,
  check:branch-review-ledger, check:outstanding-issues, lint, typecheck
Client bundle secret surface check passed.            (npm run build)
Offline RAG fixture and manifest validation passed (36 golden cases, 23 suites).
  • npm run check:design-system-contract — the gate this ledger row names.
Design-system contract passed (709 production files; raw colors 2; literal shadows 0;
  legacy tap classes 0; edge conflicts 27; 1px shadow spreads 2).
Motion/z/palette ratchets: ... legacy shadow aliases 125; arbitrary tracking 0.
design-system adoption checked: 54 components, 59 roots
design-sync contract checked: 54 components and 7 guidelines
  • Chromium look at the changed focus state, both themes, on /mockups/calculators-search — the only route that renders the class:
light  focused: outline "solid 2px rgb(29, 111, 184)"  offset 2px   shadow unchanged by focus: true
dark   focused: outline "solid 2px rgb(116, 189, 240)" offset 2px   shadow unchanged by focus: true
  • Guard mutation-verified both ways: reinstating the declaration fails with redeclares --shadow-focus, reinstating the var() consumer fails with consumes --shadow-focus.

UI verification not run: npm run verify:ui and npm run verify:phone-chrome were not run. This container's Chromium is revision 1194 against the repo's pinned Playwright revision 1234 — the #255 drift, where docs/testing.md says to delegate browser proof to CI Production UI rather than force a mismatched binary. The Chromium evidence above is therefore reported as an inspection, not as gate evidence. No production phone chrome renders the changed class (zero of 37 production routes), so the phone-chrome risk this row anticipated does not arise.

Risk and rollout

  • Risk: Low. One CSS rule and two token declarations. The changed rule is reachable today only from /mockups/calculators-search, which 404s in production; the correctness benefit is that any future production use of chatComposerShell inherits the sanctioned focus treatment instead of a companion ring. Residual risk is a surface adopting the class between this PR and a Chromium CI run — covered by the Production UI job.
  • Rollback: git revert this commit. The token declarations and the box-shadow: var(--shadow-focus) consumer return together; the contract guard is in the same commit, so it reverts with them and cannot fail against a restored token.
  • Provider or production effects: None. No provider-backed gate, migration, or deployment behaviour was touched; the local dev server was stopped before npm run build and not left running.

Notes

  • Ledger #261 is archived with the measured outcome, including the reach correction and the three un-ratcheted slack metrics left for whoever picks up #262.
  • Gate 3 in GATES.md stays planned. This removes the one companion ring the rule knew about; nothing yet stops the next one.

Generated by Claude Code

Summary by CodeRabbit

  • New Features
    • Updated composer focus styling to use a clear 2px outline with offset.
  • Bug Fixes
    • Removed the retired focus-shadow styling while preserving accent borders and resting elevation.
  • Documentation
    • Updated design-system guidance, migration records, and issue status to reflect the completed focus-style transition.
  • Tests
    • Added validation to prevent reintroduction of the retired focus-shadow token or its usage.

DS Track A2. `--shadow-focus` packed a 3px accent halo in front of
`--shadow-soft`, so its one consumer — `.chat-composer-shell-delta:focus-within`
— painted a companion ring on top of the accent border swap. That is the second
focus affordance the shared `:focus-visible` treatment is written to prevent
(GATES Gate 3). The composer now uses `outline: 2px solid var(--focus)` at
`outline-offset: 2px`, and both theme declarations of the token are deleted.

Focus no longer overrides `box-shadow`. The retired token carried `--shadow-soft`
as its second layer, so leaving the resting elevation alone keeps the pill seated
at the same height focused as at rest. Measured in Chromium: light
`solid 2px rgb(29, 111, 184)`, dark `solid 2px rgb(116, 189, 240)`, box-shadow
byte-identical resting vs focused in both themes.

Corrects the premise inherited from HANDOVER-2026-08-07 A2: this is not a visible
production focus change. `chatComposerShell` is imported only by
`calculators/search-detail.tsx` and its mockup twin; production `/calculators`
renders `chatComposerShellBase` + `answer-footer-search-pill`, and
`CalculatorSearchHome` is reached only from two unrouted mockup exports. Probing
all 37 static production routes in Chromium found zero renders of the class; the
single live render is `/mockups/calculators-search`, where the look was taken.
The inherited note was right that a `--include=*.tsx` grep misses the consumer
(it is in CSS) but wrong about its reach. Corrections recorded in the handover's
own "Measured wrong so far" list, per that file's convention.

Guard: design-token-contract.test.ts rejects both a `--shadow-focus:` declaration
and a `var(--shadow-focus)` consumer, across globals.css and the v2 layer, and is
mutation-verified against both. Deliberately not the whole-file substring check
used for `--shadow-tight`, because the composer rule names the retired token in a
comment on purpose.

legacyShadowAliases 127 -> 125 (soft 71 -> 69), globals.css per-path pin
tightened 3 -> 1: the deleted declarations' VALUE ended in `var(--shadow-soft)`,
so they scored as two `soft` aliases — the indirection GATES documents. Left
un-ratcheted as pre-existing slack unrelated to this diff: rawPaddingLiterals
67 -> 65, rawGapLiterals 34 -> 32, layoutTransitionExceptions 12 -> 11.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012spLo9ry4zjoDyZi7j89kT
@supabase

supabase Bot commented Aug 11, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR removes --shadow-focus, changes composer focus styling to a 2px var(--focus) outline, adds contract tests, updates baseline metrics, and records the migration in design-system and issue documentation.

Changes

Shadow focus token retirement

Layer / File(s) Summary
Focus styling and token contract
src/app/globals.css, tests/design-token-contract.test.ts
The light and dark --shadow-focus declarations were removed. Composer focus styling now uses a 2px outline. Contract tests reject token declarations and consumers.
Design-system status and measurements
docs/design-system.md, docs/design-system/GATES.md, docs/design-system/TOKENS.md, docs/design-system/SPEC.md, scripts/design-system-contract-baseline.json
Design-system guidance and migration records were updated. The legacy shadow alias baseline changed from 127 to 125.
Reachability and issue records
docs/design-system/HANDOVER-2026-08-07.md, docs/outstanding-issues.md, docs/branch-review-ledger.md
The consumer was documented as mockup-only, issue #261 was archived, and the review-ledger record was added.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested labels: codex

Suggested reviewers: claude

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies retirement of --shadow-focus and its replacement with the sanctioned focus outline.
Description check ✅ Passed The description includes the required summary, verification evidence, risk, rollback, production effects, and explicit reasons for skipped UI gates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/codex-m4c-retire-shadow-nliak3

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: dependency version conflict. Check your lock file or package.json.


Comment @coderabbitai help to get the list of available commands.

Handoff record for PR #1807 (DS Track A2, --shadow-focus retirement).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012spLo9ry4zjoDyZi7j89kT

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 448a0d084c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/app/globals.css
@BigSimmo
BigSimmo enabled auto-merge August 11, 2026 06:26

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
docs/design-system/TOKENS.md (1)

112-115: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep exact focus values in the owner file.

Lines 3-5 state that token values live only in the owner file. The new row repeats outline: 2px solid var(--focus) and outline-offset: 2px. Keep this row at the role and behavior level, and link to docs/design-system.md or src/app/globals.css.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/design-system/TOKENS.md` around lines 112 - 115, Update the
--shadow-focus disposition in the design-system token table to describe the
focus behavior at the role level without repeating exact outline values. Link
readers to the owning documentation or stylesheet, such as docs/design-system.md
or the globals.css owner, while preserving the migration status and gate
details.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/globals.css`:
- Around line 1470-1480: Update the comment above
.chat-composer-shell-delta:focus-within so it acknowledges the focus-state
border-color change, stating that the outline is the only additional focus layer
or explicitly mentioning the border swap; leave the CSS rule unchanged.

In `@tests/design-token-contract.test.ts`:
- Around line 179-195: Update the retired-token assertions in the “keeps the
retired --shadow-focus token deleted in every scope” test to use
whitespace-aware matching for declarations and var() consumers, including
optional fallback arguments. Add mutation cases covering `--shadow-focus :`,
`var( --shadow-focus )`, and `var(--shadow-focus, fallback)` so each form is
rejected.

---

Nitpick comments:
In `@docs/design-system/TOKENS.md`:
- Around line 112-115: Update the --shadow-focus disposition in the
design-system token table to describe the focus behavior at the role level
without repeating exact outline values. Link readers to the owning documentation
or stylesheet, such as docs/design-system.md or the globals.css owner, while
preserving the migration status and gate details.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 58cb1908-ef17-44e2-a312-1b254f09f913

📥 Commits

Reviewing files that changed from the base of the PR and between cb23f86 and 342466c.

📒 Files selected for processing (10)
  • docs/branch-review-ledger.md
  • docs/design-system.md
  • docs/design-system/GATES.md
  • docs/design-system/HANDOVER-2026-08-07.md
  • docs/design-system/SPEC.md
  • docs/design-system/TOKENS.md
  • docs/outstanding-issues.md
  • scripts/design-system-contract-baseline.json
  • src/app/globals.css
  • tests/design-token-contract.test.ts

Comment thread src/app/globals.css
Comment thread tests/design-token-contract.test.ts
@BigSimmo

Copy link
Copy Markdown
Owner Author

Unblock snapshot (PR #1807)

  • Head: 342466c9008c034b0988e45ac0e76b7b62ab2834 (updated from 624e4ce0dd20514ef217ab9730d2a596aa6517b4)
  • Sync/merge: origin/main merged locally once as required (behind-by clean state => sync needed)
  • Merge-tree versus origin/main: clean (no conflicts)
  • Ahead/behind now: ahead=3 / behind=0
  • Mergeable: MERGEABLE, mergeStateStatus=BLOCKED
  • Required checks: Build, Unit coverage, Safety and config checks, Static PR checks, Production UI (1/2/3), and PR required are all green/passed on latest check run
  • Unresolved threads: one unresolved review thread remains in src/app/globals.css (CodeRabbit/P2 focus comment at line ~1479)

What I changed:

  • Per protocol for behind PR, performed one sync merge from origin/main on this PR branch and pushed commit 342466c9008c034b0988e45ac0e76b7b62ab2834.

Residual risk / what still blocks merge:

  • Merge remains blocked due GitHub merge-state (BLOCKED) despite required checks being green; this appears to be PR-review policy/review-thread state rather than a merge conflict or required-CI gate.
  • I did not make a content edit beyond the main sync because no concrete required merge/CI blocker remained from this branch after sync.

If you want, I can continue to the next PR now and return to #1807 after any reviewer action is posted.

@BigSimmo
BigSimmo merged commit 381d2c2 into main Aug 11, 2026
27 checks passed
@BigSimmo
BigSimmo deleted the claude/codex-m4c-retire-shadow-nliak3 branch August 11, 2026 10:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants