chore: audit all components (#2)

Reviewed-on: #2
This commit was merged in pull request #2.
This commit is contained in:
2026-11-08 06:27:12 +00:00
parent 0ad5c3fe90
commit 11b29dc91a
51 changed files with 2096 additions and 958 deletions
+95 -2
View File
@@ -11,6 +11,9 @@ is the first downstream consumer; its screens drive the order.
## Queue — to follow
Platform metric adoption continues one component at a time; each stop goes
through the review gate and a gallery pass.
Gaps surfaced by the signed comparison; ordered by signed's usage.
- [ ] **Virtual list** — generic virtualized variable-height rows with a
@@ -47,6 +50,14 @@ Gaps surfaced by the signed comparison; ordered by signed's usage.
- [x] Platform sources — macOS (NSColor), Windows 11 (UISettings), GNOME
(portal), KDE (kdeglobals), Omarchy (colors.toml), neutral fallback;
live watchers for each
- [x] Platform metric fidelity — stated control/input/menu-row/switch
metrics and the full radius ladder per platform, Linux root fonts
(GNOME gsettings `font-name`, KDE `kdeglobals font=`), per-source
border + focus chrome (`Theme::borders`), and a per-platform spacing
unit (`Theme::spacing`); overlay borders engage in dark mode, where
floating layers separate by border instead of shadow — dark elevation
shadows are dropped entirely, since they only muddied the dark scrim.
Components adopt the tokens one by one (see Next and Queue)
### icons (`crates/icons`)
@@ -55,12 +66,93 @@ Gaps surfaced by the signed comparison; ordered by signed's usage.
### core (`crates/core`)
- [x] Button platform chrome — every variant always paints the hairline
border, sized outside the stated control height (`BORDER_WIDTH`); where
the platform paints no border (`Theme::borders.buttons`, ghost) the
border takes the fill's color and disappears, so sizes match across
platforms; icon-bearing buttons pad with `dense_padding_x` instead of
`padding_x`
- [x] Button loading state — `.loading(true)` shows the spinner in place of
the icon and suppresses activation; Spinner gained a `.color` override
for accent-filled surfaces
- [x] Input platform chrome — the field always paints the hairline border,
sized outside the stated field height; where the platform paints no
border (`Theme::borders.fields`) it takes the field's fill; focus
recolors the border on Windows / KDE and paints the accent ring on
macOS / GNOME via `Theme::borders.focus_ring`; the shared `focus_ring`
band paints at half ink (every focusable control picks it up)
- [x] Input prefix / suffix — elements docked inside the field's edges,
typically small ghost buttons; a docked click activates the control
without reaching the field's caret handler, and the text region shrinks
to make room
- [x] Select platform chrome — the trigger takes the input treatment: the
hairline border always painted, sized outside the stated field height
and taking the fill's color where the platform paints none; open
recolors the border on Windows / KDE and paints the accent ring on
macOS / GNOME, so the trigger matches a focused field; the menu
popup's border sits behind `Theme::borders.overlays`, disappearing
into the surface where the platform paints none
- [x] Menu platform chrome — the popup border behind `Theme::borders.overlays`
(and dark mode); the panel padding and separator margins come from
`Theme::spacing`, and every action row renders at the stated
`menu_item_height` with content centered, so the stated metric is the
whole row; rows carry debug selectors for headless geometry tests
- [x] Popover platform chrome — the panel border behind
`Theme::borders.overlays` (and dark mode); the anchor gap is the
spacing unit and rides `anchored().offset`, not a margin, so the
window-edge clamp stays intact; the panel carries a debug selector
- [x] Dialog platform chrome — the panel border behind
`Theme::borders.overlays` (and dark mode), taking the surface color
where the platform paints none
- [x] Toast platform chrome — the pill border behind
`Theme::borders.overlays` (and dark mode), taking the surface color
where the platform paints none; the pill rides the popover elevation,
so dark mode's no-shadow rule applies to it too
- [x] Tooltip platform chrome — the panel border behind
`Theme::borders.overlays` (and dark mode), taking the surface color
where the platform paints none, and riding the popover elevation for
the light-mode shadow; anchored tooltips hang below the
hovered parent (`Tooltip::anchored(text, id)`) so they never cover it —
the element records its painted bounds with `record_anchor_bounds`
(`Button` does), the panel hangs below that with the spacing gap, and
it flips above the parent when it would overflow the window bottom
(the panel records its own height after the first frame); unanchored
tooltips fall back to the cursor-offset wrapper
- [x] Alert platform chrome — the banner border behind
`Theme::borders.overlays` (and dark mode), taking the surface color
where the platform paints none; it rides the popover elevation, so
dark mode's no-shadow rule applies to it too
- [x] Combobox platform chrome — the popup border behind
`Theme::borders.overlays` (and dark mode), taking the surface color
where the platform paints none, and riding the popover elevation for
the light-mode shadow; the trigger is a plain `Input`, so it
already carries the full field treatment, and the chevron recenters on
the field's full height, border included; the popup mounts on
`deferred(anchored().offset(...))` like the Popover — out of the
wrapper's layout, one spacing gap below, window-clamped — and always
matches the combobox's width; the combobox itself is no longer full
width: it takes a compact default and style refinements on the builder
(`.w(...)`) set the width; the empty field keeps its placeholder while
focused (`Input::placeholder_when_focused`) and clicking into it opens
the options right away, with no keystroke needed
- [x] Command palette platform chrome — the panel border behind
`Theme::borders.overlays` (and dark mode), taking the surface color
where the platform paints none; it rides the dialog elevation, so dark
mode's no-shadow rule applies to it too
- [x] Switch platform chrome — the track and knob take the stated
`switch_height` / `switch_width` / `switch_knob` (the knob's inset
derived to center it in the track, its travel from the remaining
width); the knob is borderless, and the track carries a debug selector
for headless geometry tests
- [x] Button, Checkbox, Switch, Radio + RadioGroup, Toggle, Link, Slider,
Progress, Avatar (image + seeded pixel-art fallback)
- [x] Spinner — painted ring + rotating-icon variant, indeterminate and
determinate; replaces `Tab::busy`'s placeholder
- [x] Input — single-line, password with reveal, multiline, undo/redo, actions
+ key context, caret blink
+ key context, caret blink (time-math driven: the focused field mounts a
repeating blink animation whose frames redraw the caret, the caret is
solid for one interval after each edit, and an idle unfocused page
schedules no frames)
- [x] ScrollArea, Popover, Menu, Tooltip, Dialog / AlertDialog, Toast,
Alert + alerts stack
- [x] Select, Segmented, ContextMenu, EmptyState, Badge
@@ -70,7 +162,8 @@ Gaps surfaced by the signed comparison; ordered by signed's usage.
screen-reader label
- [x] Combobox — type-to-filter picker with a caller-owned matcher, create /
keep / revert blur modes
- [x] Command palette — filtered actions; the matcher stays caller-owned
- [x] Command palette — filtered actions; the matcher stays caller-owned,
and commands may carry a leading icon
- [x] Scrollbar — overlay thumbs for gpui's `list` and `uniform_list`,
platform autohide with a `visibility` override
- [x] Clipboard button — copies a value, confirms with a brief check mark