A `WantedMenu` badge dropdown on the agents table clips against
`.ui-table-scroll`s overflow the moment its row is the last (or
near-last) one — the popover extends past the table content the
scroll container bounds itself to. `Table.tsx` already solved the
identical clip for its own column-filter popover with a
position:fixed + portal computed from the anchor rect; `Dropdown` now
takes an optional `portal` prop that opts a caller into that same
recipe instead of a second hand-rolled copy of it. Off by default —
every other current caller (StatusChips x2, the components-page demo)
keeps its existing non-portal behavior unchanged.
Pure `nix fmt` output from the commit before this one — no hand edits.
203 files: 52 md, 42 tsx, 32 js, 32 css, 21 ts, 13 html, 8 json, 3 mjs.
Reproduce with `nix develop -c nix fmt` on the parent commit; the result
should be byte-identical to this tree.
None of the 13 `.prettierignore` entries appears here — verified by
intersecting the changed-file list against the ignore file, with a
control proving the intersection finds a match when one exists.
mara, #3775: clicking a badge with its own dropdown open reopens it
instead of closing it. Root cause: the outside-click listener only
excludes the dropdown's own ref, not the sibling trigger that opened
it — a click on the trigger closes via that listener (pointerdown
fires first), then the trigger's own onClick toggle fires straight
after and reopens it, since its closure reads the pre-close state.
Dropdown now takes an optional anchorRef (the trigger's wrapper,
which callers already have for CSS positioning) and excludes it from
the outside-click check too — the same shape MetaNav's own hand-rolled
popover already uses correctly. Wired into StatusChips's Picker +
StatusMenu and swarm-ui's ComponentsPage demo (the only three Dropdown
consumers).
Verified two ways: reverted the fix, rebuilt, confirmed the bug
reproduces via a raw-CDP interaction test (two real clicks dispatched
through headless chromium, not just a static screenshot); restored
the fix, rebuilt, confirmed it passes.
mara, #3757: fold the separate alive badge into the turn-state badge,
with pause/resume + cancel-turn moved into its dropdown. Cancel-turn is
click-again-to-confirm, not a modal.
model/effort/ctx/cost stay as separate badges — not asked to fold
those in too.
New shared Preact primitives for the per-agent terminal redesign:
- Badge (@hive/shared/badge.js): a labelled status pill. Plain <span>
when static (e.g. "alive"), a real <button> with a disclosure caret
when given onClick (e.g. opens a Dropdown, or toggles itself in
place). Same component either way so a status row reads as one
consistent set of badges regardless of which are interactive.
- Dropdown (@hive/shared/dropdown.js): a small option list anchored
directly under whatever opened it (no portal, no native <dialog> —
see the file comment for why). Closes on outside click or Escape.
This is the fix for the design guide's own named anti-example: the
agent page's model/effort pickers live in the overflow menu while the
current model/effort only show as a disconnected chip. Badge+Dropdown
composed together is that control moved inline, next to what it shows.
Demoed on swarm-ui's /components page: all Badge tones, a label-prefixed
badge, an interactive badge that opens a Dropdown (model-picker shape),
and an interactive badge that toggles itself (pause/resume shape).
Both packages build + tsc --noEmit clean.