feat: add dropdown menu component

This commit is contained in:
2026-11-08 17:03:38 +07:00
parent 11b29dc91a
commit d8663593b6
10 changed files with 1244 additions and 197 deletions
+13 -3
View File
@@ -22,8 +22,6 @@ Gaps surfaced by the signed comparison; ordered by signed's usage.
- [ ] **Editable code field** — syntax-highlighted editable multiline field,
the code view's highlighter over the input's editing model; signed's
repo file browser.
- [ ] **Dropdown menu** — trigger button + popover + menu composite, three
signed call sites; must stay a real component, not a wrapper.
- [ ] **Motion easing helpers** — cubic ease-out and lerp beside
`theme::Motion`; low priority, gpui's animation primitives cover most
cases.
@@ -96,7 +94,13 @@ Gaps surfaced by the signed comparison; ordered by signed's usage.
(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
whole row; rows sit a half-step apart (`gap_0p5`) so the rounded
highlight reads as its own chip, and the unselected pointer wash is the
preset's `muted_hover`, not a foreground token; pointer opens arm no
row — a keyboard open (arrow or Enter on the trigger) arms the first
selectable row, and Select arms its current value — so Enter cannot
fire an option nobody chose; 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
@@ -139,6 +143,12 @@ Gaps surfaced by the signed comparison; ordered by signed's usage.
`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] Dropdown menu — trigger button + menu composite reusing the menu's
anchored panel; the trigger takes the full button variant vocabulary;
the split form keeps the main zone a working button (`on_click` fires
anywhere outside the chevron) while the chevron zone opens the menu,
the menu-only form opens on activation, ArrowDown opens from focus, and
focus returns to the trigger on every close
- [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