Skip to content

refactor(desktop): stop app CSS restyling the shared components' insides - #3674

Merged
charleslpan merged 7 commits into
mainfrom
refactor/desktop-luke-internals-css
Oct 18, 2026
Merged

charleslpan merged 7 commits into
mainfrom
refactor/desktop-luke-internals-css

Conversation

@charleslpan

@charleslpan charleslpan commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Phase 3, P8: the desktop's own CSS stops reaching into @luke/ui's parts. I re-scanned rg '\.luke-' apps/desktop/src/renderer/styles apps/web/src: the web has no hits. Every desktop rule that restyled a shared component's inside is now a component option, points at the app's own element, or is deleted.

Into the components (approved by the orchestrator):

  • SplitButton answers a new --luke-fold: bare value: its main part's glyph alone, at the control's corner, with no chevron. The plan toolbar at ≤320px sets it instead of hiding .luke-split-button > .luke-button:last-child and re-rounding the main part. folded still folds the words.
  • SearchField answers --luke-fold: folded: its tally is read out to screen readers but not drawn. The find bar at ≤300px sets it instead of hiding .luke-search-field-tally.
  • InlineEdit's existing input look now fills the label's line and overhangs it (−3px above and below, minus its inset and border at the start). Before, Settings set those negative margins on .luke-inline-edit. No new API.
  • packages/ui/README.md documents the --luke-fold values. The catalog shows SplitButton bare and SearchField folded.

Pointed at the app's own element instead of a shared part:

  • To-dos dock: the rise animation now targets the dock's own body class (.todos-dock-body) instead of .luke-disclosure-body. fold.tsx is untouched (it's P4's).
  • Hover cards: .card-code, .actor-words:has(> .card-when), and a card-corner-mark class on the pull request mark replace the .luke-hover-card-note/-corner descendant selectors.
  • Chords: the chord in the tooltip and the chord on a filled button (dialog Send/Create issue, home New task) take a class on the app's Shortcut (tooltip-chord, button-chord). Before, they were selected through .luke-tooltip, .luke-dialog-actions .luke-button and .home .luke-button.
  • Capture runs: the tooltip, the menu and palette, and the toast stack each had a "hold motion still" rule. They are now one body-level line in base.css's capture rule.

Deleted:

  • .sidebar-task > .luke-inline-edit and .luke-hover-card .integration-tool-list were dead: no element matches them anymore.
  • The menu's chevron and check were restated at menu size only because the app's global glyph rules (.settings-chevron, .credential-check) beat the shared layer. Those global rules now leave .luke-menu-item-end alone, as they already left chips and button faces, so the menu draws its own.
  • .luke-combobox-option-end .credential-check, added by a sibling PR to undo the same leak in a picker's option. The global .credential-check rule now leaves .luke-combobox-option-end alone too, so the combobox draws its own check (16px, text colour when chosen). It is pixel-identical to the sibling's fix; screenshots below.
  • The negative margins on the Issues column head's + button.
  • overflow: visible on the automations empty state.

Why exclusions rather than scoping the glyph rules: .settings-chevron, .credential-check and .link-icon are @luke/ui glyph classes that the app styles globally. Scoping them to the app's own containers, or moving them into the base layer, would also resize the chevrons in several buttons, nav items and list rows that rely on the app size today. So the rules keep their :where(:not(…)) list of the shared slots that draw their own glyph, which has zero specificity and restyles nothing of those slots.

Kept, as placement or app content (not internals): flex, width or grid placement on a component's root (.luke-text, .luke-badge, .luke-empty-state, .luke-search-field, .luke-text-field, .luke-hover-card-head, .tab-button > .luke-inline-edit width). Also kept:

  • the drag-region opt-outs and menu layers;
  • :has() conditions on the app's own containers;
  • the app's own content in a slot (a repository picture in a menu glyph, and --state-glyph-size on hover-card slots, which sizes the app's own StateGlyph and nothing of the card's);
  • base.css's .luke-face rules and the face-size rules. These are the motion wiring that packages/brand's generator writes into the renderer (--face-motion, --voice-*), so they stay with the generated face-motion.css.

Visible changes

  1. Issues column head 24 → 30px. The + is a full control again instead of being squeezed into a 24px head with negative margins. Every head, placeholder ones included, now stands the control's height, so nothing jumps when the board loads. The + glyph still ends on the cards' time edge.
Dark Light
Before
After
  1. The shared Menu's check, 12 → 16px. It is now the menu's own glyph size, as the web and the catalog already draw it, instead of the size the app's settings-row rule leaked in.
Dark Light
Before
After

Nothing else should change visibly. The Start split button at 600/400/300px, the find bar's tally at 420/280px, and the Settings rename field are pixel-identical between main and this branch:

Start: drawn, folded, bare
Find bar: tally drawn, then folded

  1. A picker's submenu chevron, 11 → 16px. The global .settings-chevron rule leaked into a combobox option's end slot as it did into the menu's. It now leaves .luke-combobox-option-end alone, so the chevron is the picker's own glyph size and matches the check beside it.
Dark Light
Before
After

The picker's check after this change (identical to main):

Dark Light

Evidence

  • pnpm check:affected: green (typecheck, lint, knip, discarded-effect, tests). One run hit a failure in list-row.test.ts's swipe test (from feat(ui): tune a row's swipe: a trackpad scroll never swipes, lifted fingers let go at once, a flick carries, and the row follows with no render #3653, already on main). It passes alone 3/3 and on rerun; this PR touches no list-row code.
  • Screenshots: Linux, headless Chrome, synthetic data. Markup from the real components, rendered in jsdom by a throwaway test that is not committed, drawn with the desktop renderer's built styles.css from main (before) and from this branch (after).
  • No new test: the PR changes only styling, and the rules forbid CSS/class assertions. The --luke-fold states are shown in the catalog instead.
  • Not verified on a Mac.

Invariants

  • ./scripts/check.sh green. (CI)
  • JSON Schema goldens unchanged.
  • Every behavior change has, in this PR, the test that fails without it; no change-detector test added. (styling only)
  • Gateway envelope goldens unchanged.
  • No new as type assertion.
  • No Effect.runPromise/runSync/runFork added.
  • No new setTimeout/setInterval/new Promise/AbortController/fs.watch.
  • No Effect, Stream, or Layer dropped.
  • Test count unchanged.
  • No hand-rolled file replaced.
  • No CLAUDE.md/AGENTS.md sentence names the changed part.
  • PRIVACY.md unchanged.
  • No dependency changes.
  • No barrel changes.

Notes

  • Blockers or follow-up verification: not verified on a Mac.

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
luke-web Ignored Ignored Preview Oct 18, 2026 8:28pm UTC

Request Review

charleslpan added a commit that referenced this pull request Oct 18, 2026
@charleslpan
charleslpan enabled auto-merge October 18, 2026 19:25
devin-ai-integration[bot]

This comment was marked as resolved.

…ther control

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@charleslpan
charleslpan added this pull request to the merge queue Oct 18, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 18, 2026
…-internals-css

# Conflicts:
#	apps/desktop/src/renderer/styles/desktop.css
#	apps/desktop/src/renderer/styles/tooltip.css
charleslpan and others added 2 commits October 18, 2026 20:14
…-internals-css

# Conflicts:
#	apps/catalog/src/examples/search-fields.tsx
#	apps/desktop/src/renderer/styles/desktop.css
…end slot rather than restating the picker's check

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…slot, so its submenu chevron is the picker's own size

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
charleslpan added a commit that referenced this pull request Oct 18, 2026
@charleslpan
charleslpan added this pull request to the merge queue Oct 18, 2026
Merged via the queue into main with commit 221d1b8 Oct 18, 2026
11 checks passed
@charleslpan
charleslpan deleted the refactor/desktop-luke-internals-css branch October 18, 2026 20:38
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.

1 participant