Uh oh!
There was an error while loading. Please reload this page.
refactor(ui-css): settle cascade and important resets - #485
Merged
Conversation
Astro-Han added a commit
that referenced
this pull request
Jul 3, 2026
5 CSS files (daily-review, health-center, permission-center, settings/connection, tool-stream) took main's format (@layer removal, indentation) and re-applied foreground alias replacement (40/50→muted-foreground, 60/70/80→foreground-secondary).
Astro-Han added a commit
that referenced
this pull request
Jul 3, 2026
…d aliases to main's new CSS files
Address tenth-round review P3: readExpressionValue now treats a
depth-0 opening brace as a function/class body boundary and stops,
preventing the text-prop scanner from reading into function bodies
after a type annotation like fill: string) { ... }.
Also re-applies foreground alias replacement (40/50→muted-foreground,
60/70/80→foreground-secondary) to CSS files introduced by main's
#485 (module-pages/skills.css, module-pages/capability-audit.css,
module-pages/plan-reminders.css, module-pages/module-shell.css,
model-switcher.css).Astro-Han added a commit
that referenced
this pull request
Jul 3, 2026
* feat(design): establish foreground-secondary alias + delete unused -90/-95 Add --foreground-secondary (→ --foreground-80) as the canonical secondary text tier alongside the existing --muted-foreground (→ --foreground-50). Delete --foreground-90/-95 which had zero call sites. Update shadcn --color-muted-foreground mapping to target --foreground-secondary so the Tailwind utility aligns with maka's secondary tier. Update maka-tokens.css internal call sites to use the new aliases. Update docs/design-system.md §1.1 color table. Part of issue #430 PR4 (foreground tier converge). * refactor(design): replace 444 text call sites with semantic foreground aliases (re-applied on rebased main) * test(design): add foreground-tier contract test + mark roadmap complete New foreground-tier-contract.test.ts bans text props (color/fill/ stroke) from referencing raw --foreground-40/50/60/70/80 directly, enforcing the 3-tier semantic aliases. Verify --foreground-secondary targets -80, --muted-foreground targets -50, -90/-95 not defined. Update design-refinement-roadmap-2026-07.md §1.6 (4-tier → 3-tier) and §3 (mark foreground-tier-converge done). Part of issue #430 PR4 (foreground tier converge). * fix(design): tighten foreground-tier contract + resolve muted-foreground conflict Address code review feedback on PR #479: P1: contract test TSX scanner missed real-world Tailwind syntax. The regex only matched text-[color:var(--foreground-N)] (with color: prefix), missing text-[var(--foreground-N)] (no prefix), disabled:text-[var(--foreground-N)] (variant prefix), and text-foreground-N (utility class). Fixed regex to cover all forms; added 4 negative-case tests proving each is caught. P2: @theme still exported --color-foreground-40/50/60/70/80 as Tailwind utilities, creating an entry point the contract test had to plug. Removed the raw text-stop exports; only surface wash (2/3/5/8/10) and semantic aliases (foreground-secondary, muted-foreground) remain. Added contract assertion. P2: --color-muted-foreground had two conflicting definitions — maka-tokens.css pointed at --muted-foreground (-50, true muted) while styles.css pointed at --foreground-secondary (-80). Fixed: styles.css now aligns with tokens (--muted-foreground). Shadcn components that used text-muted-foreground for secondary text (button quiet, menu label, field description, etc.) switched to text-foreground-secondary. Placeholder, shortcut, and empty-icon usages remain text-muted-foreground (correct muted semantics). P3: contract test now scans packages/ui/stories alongside src and renderer. * fix(design): ban raw foreground stops + simplify contract to raw-token scan Address second-round review on PR #479: P1: TSX contract still missed real-world forms. The Tailwind-syntax regex approach kept growing but never covered all shapes (quoted className, cn() strings, template literals, Tailwind shorthand text-(--foreground-N)). Replaced with a raw-token scan: ban --foreground-40/50/60/70/80/90/95 from appearing in TS/TSX at all, plus a UTILITY_CLASS_RE for the --less form text-foreground-60. 11 negative-case tests cover every syntax variant the reviewer listed. P2: @theme raw-stop export assertion had a variable-name bug (--color- + --foreground-60 = --color---foreground-60, never matched). Fixed to --color-foreground-N. P3: deleted --foreground-40/50/60/70/80 entirely. --muted-foreground and --foreground-secondary are now direct color-mix() definitions, not aliases pointing at raw stops. No production code references the raw stops. * fix(design): ban surface wash as text color + cover 90/95 in all scanners Address third-round review on PR #479: P2: surface wash tokens (foreground-2/3/5/8/10) could still be used as text color via text-foreground-5, text-[color:var(--foreground- 5)], text-(--foreground-5). Added TEXT_UTILITY_RE (bans all N in text-foreground-N), TEXT_ARBITRARY_RE, TEXT_SHORTHAND_RE, and TEXT_INLINE_RE to catch surface wash in text context only; bg/ border context remains allowed. Fixed 2 real violations in chat.tsx (load-tool-count/footer used --foreground-2 as text color, now --muted-foreground). P2: CSS text scanner only banned 40/50/60/70/80, missing 90/95. Unified all scanners to use BANNED_TEXT_NUMS = 40..95; CSS, TSX raw scan, TSX utility scan, and @theme export scan all derive from the same set. P3: updated contract header comment — old description of raw mix stops staying in maka-tokens.css and aliases pointing at --foreground-50/80 was stale. * fix(design): unify surface-wash text scanner + cover var fallback Address fourth-round review on PR #479: P2: scattered regex approach still missed forms: arbitrary property [color:var(--foreground-5)], type-hint shorthand text-(color:--foreground-5), fill/stroke/caret/decoration utility classes, and var() with fallback (var(--foreground-5, currentColor)). Replaced 5 separate regexes with a unified TEXT_CONTEXT_RE that matches any text-like context prefix (text/fill/stroke/caret/decoration/ color:) followed by --foreground-N, regardless of Tailwind syntax or var() closure. Surface context (bg/border/ring/ from/to/via) remains allowed. 11 new negative cases. P3: maka-tokens.css solid mix scale comment still described stops as 'body text, captions, dividers' — updated to state they are surface-only; text uses the 3 semantic aliases. * fix(design): CSS text scanner catches var() fallback + property boundary fix Address fifth-round review on PR #479: P2: CSS text scanner still required var() to close — color: var(--foreground-5, currentColor) bypassed it. Changed FOREGROUND_TOKEN_RE from matching var(--foreground-N) to matching --foreground-N directly (no var() dependency). Found 1 real violation in onboarding.css (used --foreground-80 with oklch fallback as text color); fixed to --foreground-secondary. P3: TEXT_CONTEXT_RE inline-style alternative (D) matched any substring containing color:/fill:/stroke:,误杀ing [border-color:...] and [background-color:...]. Added declaration-boundary requirement (^, whitespace, ;, {, quote) so only bare color/fill/stroke properties are caught. Added alternative E for hyphenated text-like properties ([caret-color:...], [text-decoration-color:...]). * docs(design): remove deleted raw text stops from color table --foreground-40/50/60/70/80 were deleted in a prior commit but design-system.md still listed them as internal mix stops. Removed the stale row; only surface wash (2/3/5/8/10) and semantic aliases (foreground/foreground-secondary/muted-foreground) remain. * fix(design): strengthen contract scanner for complex syntax + clean dead code Address sixth-round review on PR #479: P2-a: Added global raw-stop ban for renderer CSS and maka-tokens.css (strip comments, then assert no --foreground-40..95 in any context). Previously CSS scanner only checked text props; raw stops could linger in bg/border and fail at runtime. P2-b: TSX scanner replaced the single mega-regex (TEXT_CONTEXT_RE, 5 alternatives) with a token-based approach: split source into class-like tokens, classify by prefix (text/fill/stroke/caret/ decoration vs bg/border/ring), then search for --foreground-N anywhere inside text-like tokens. Catches complex arbitrary values like text-[color:color-mix(...,var(--foreground-5),...)] that the old regex missed (token no longer needs to be right after prefix). CSS declaration value regex changed from [^;}\n] to [^;}] so multi-line values (color-mix with line breaks) are scanned. P3-a: [color:] arbitrary property is now classified by utility prefix — bg-[color:...], border-[color:...], ring-[color:...] pass (surface context), bare [color:...] still fails (text context). P3-b: Deleted unused ALL_BANNED_NUMS constant and its stale comment (claimed TSX can't distinguish context — the new scanner does). * fix(design): contract scanner covers all Tailwind variants + quoted inline style Address seventh-round review on PR #479: P2-a: stripVariant now scans right-to-left tracking bracket/paren depth and cuts at the last ':' outside any nesting. Uniformly handles data-[state=open]:, group-hover/item:, [&.is-dragging]: without per-variant regexes. P2-b: INLINE_STYLE_RE now accepts optional quote (", ', `) between the property name and var(, so style={{ color: "var(--fg-5)" }} and template-literal values are caught. Surface wash stops can no longer hide behind quoted inline-style values. * fix(design): contract scanner covers theme mirror, @apply, and complex inline values Address eighth-round review on PR #479: P2-a: Token regexes unified to --(?:color-)?foreground-N so the @theme mirror form (--color-foreground-N) cannot bypass the text- context scanner. RAW_STOP_THEME_RE now bans --color-foreground-40..95 globally alongside --foreground-40..95. @theme surface wash exports (--color-foreground-2/3/5/8/10) remain allowed in non-text context. P2-b: New findCssApplyOffenders reuses the TSX token classifier on each @apply utility list, banning text-foreground-N / fill-foreground-N / text-[color:var(--foreground-N)] while allowing bg/border/ring. Added production scan for renderer CSS @apply directives. P2-c: scanTextPropValue replaces INLINE_STYLE_RE. Locates text-like property names (color/fill/stroke/caretColor/textDecorationColor/ columnRuleColor in kebab-case and camelCase), extracts the full value (quoted or bare, including commas inside quotes), and scans for foreground tokens. Catches complex values (color-mix(...)), camelCase props (caretColor), and JSX SVG attributes (fill="...", stroke={...}). * fix(design): contract scanner covers bare [fill:]/[stroke:], unquoted expressions, dedupe property list Address ninth-round review on PR #479: P2-a: BARE_TEXT_PROP_RE now includes fill and stroke — Tailwind arbitrary properties [fill:var(--foreground-5)] and [stroke:...] (SVG color props) are caught as text-like context. Surface bare properties ([background:...], [border-color:...]) still pass. P2-b: scanTextPropValue unquoted branch now tracks bracket/paren depth and scans to the matching }, so commas inside function calls (e.g. pick(base, "var(--foreground-5)")) are included instead of truncating at the first comma. P3-a: Deleted unused TEXT_PROP_NAMES_RE; scanTextPropValue now generates its regex from the shared TEXT_PROP_NAMES array, so there is a single property-name list. * fix(design): readExpressionValue uses balanced depth scanning for inline style values Address tenth-round review on PR #479: P2: scanTextPropValue's unquoted branch now uses readExpressionValue, a helper that tracks quote, (), [], and {} depth. Stops at the real end of the current property/attribute (depth-0 comma, semicolon, or closing brace), not at the first newline. Opening { at the start of a JSX expression is treated as part of the value, so fill={pick(...)} is fully scanned. Multi-line expressions like colorMix(\n base,\n "var(--foreground-5)"\n) are caught. Surface properties after a text property (color: semantic, background: "var(--foreground-5)") are no longer误报ed because the comma at depth 0 terminates the text property's value before the surface property begins. * fix(design): readExpressionValue stops at depth-0 { + apply foreground aliases to main's new CSS files Address tenth-round review P3: readExpressionValue now treats a depth-0 opening brace as a function/class body boundary and stops, preventing the text-prop scanner from reading into function bodies after a type annotation like fill: string) { ... }. Also re-applies foreground alias replacement (40/50→muted-foreground, 60/70/80→foreground-secondary) to CSS files introduced by main's #485 (module-pages/skills.css, module-pages/capability-audit.css, module-pages/plan-reminders.css, module-pages/module-shell.css, model-switcher.css).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
@layerwrappers from renderer feature stylesheets and add a contract that keepsapps/desktop/src/renderer/styles/**unlayered.Input/Textareafields through an explicit chrome-less path instead of resetting primitive focus rings with page-level!importantCSS.Input/Textareabare reset in@maka/ui, so call sites keep only business sizing/layout classes.unstyledfrom field chrome opt-out;InputGroupadapters now opt out explicitly because their wrapper owns chrome.!importantaudit around the retired skill search, onboarding quickchat, and composer textarea ring-reset sites, and add render-level bare-field contracts.Why
Refs #476.
PR1 made renderer CSS parseable. This PR settles the next CSS hygiene layer: feature stylesheets now use one cascade model, and embedded fields no longer need local
!importantring-shadow resets to avoid double chrome.Scope
Changed:
apps/desktop/src/main/__tests__/renderer-style-layer-cascade-contract.test.tsnow rejects@layerinside renderer feature stylesheets.apps/desktop/src/renderer/styles/**has local@layerwrappers mechanically removed while preserving rule order.packages/ui/src/ui.tsxgives legacyInput/Textareaanunstyledpath that owns the bare field reset anddata-maka-field-chrome="none".packages/ui/src/primitives/input.tsxandpackages/ui/src/primitives/textarea.tsxno longer treat primitiveunstyledas field chrome opt-out.packages/ui/src/primitives/input-group.tsxmarks its innerInput/Textareawithdata-maka-field-chrome="none"at the adapter layer.packages/ui/src/__tests__/field-chrome.test.tspins the primitive-vs-InputGroupunstyledcontract.unstyledand no longer carry repeatedborder-0/shadow-none/focus-visible:ring-*reset classes.apps/desktop/src/main/__tests__/renderer-important-audit-contract.test.tsguards the retired ring-reset patterns and parses the field focus selector semantically.apps/desktop/src/main/__tests__/bare-field-chrome-contract.test.tsrenders@maka/uifields and verifies the actual legacyunstyledDOM contract.Not included:
module-pages.cssdomain split.!importantcleanup outside the three ring-reset sites.Verification
renderer-style-layer-cascade-contract.test.jsfailed on existing@layerfeature stylesheets before unwrapping.renderer-important-audit-contract.test.jsfailed on.maka-skill-search inputbefore the bare-field route and ring-reset cleanup.bare-field-chrome-contract.test.jsfailed beforeunstyledowned the shared bare reset.field-chrome.test.jsfailed before primitiveunstyledstopped emittingdata-maka-field-chrome="none".npm run buildnpm run -w @maka/ui buildnpm run -w @maka/ui build && node --test packages/ui/dist/__tests__/field-chrome.test.jsnpm run -w @maka/desktop build:mainnode --test apps/desktop/dist/main/__tests__/bare-field-chrome-contract.test.js apps/desktop/dist/main/__tests__/renderer-important-audit-contract.test.jsnode --test apps/desktop/dist/main/__tests__/renderer-css-parse-contract.test.js apps/desktop/dist/main/__tests__/renderer-tailwind-compile-contract.test.js apps/desktop/dist/main/__tests__/renderer-important-audit-contract.test.js apps/desktop/dist/main/__tests__/bare-field-chrome-contract.test.jsnode --test apps/desktop/dist/main/__tests__/renderer-style-layer-cascade-contract.test.jsnpm run -w @maka/desktop build:renderer(passes; existing Vite chunk-size warning remains)node ../../scripts/capture-screenshots.mjs --scenario module-skills --variant light-1280-motionnode ../../scripts/capture-screenshots.mjs --scenario first-run --variant light-1280-motionnode ../../scripts/capture-screenshots.mjs --scenario provider-workspace --variant light-1280-motionnode ../../scripts/capture-screenshots.mjs --scenario module-daily-review --variant light-1280-motionnode ../../scripts/capture-screenshots.mjs --scenario command-palette-open --variant light-1280-motionnode ../../scripts/capture-screenshots.mjs --scenario sidebar-search-modal-open --variant light-1280-motionnode --test apps/desktop/dist/main/__tests__/rive-workflow-tool.test.js(rerun after one unrelated transient full-suite timeout)npm run -w @maka/desktop test(1716 tests pass)Known existing failure:
npm run -w @maka/ui teststill fails onchat-primitives.testfooter-action / lineage-badge merge assertions. The same command fails the same way on currentmain, so this PR does not introduce that failure.User-facing impact
No visual redesign intended. This PR does touch focus chrome plumbing and cascade boundaries, so the latest screenshots plus the computed-style focus smoke above cover the affected surfaces.
Reviewer notes
The commits are intentionally split by rollback reason:
refactor(ui-css): unlayer renderer feature stylesonly settles feature stylesheet cascade.fix(ui-css): route bare fields around focus chromeintroduces the explicit bare-field route and removes the original important resets.fix(ui-css): centralize bare field focus chromeaddresses review feedback: lower-specificity focus opt-out, behavior-level bare-field contract, and UI-owned bare reset.fix(ui-css): decouple primitive unstyled chromeaddresses review feedback: primitiveunstyledno longer means bare field chrome opt-out;InputGroupopts out explicitly at its adapter boundary.