settings: move the theme/motion panel into @hive/shared, add motion to agent

Review feedback on this PR (mara): "i think the component should be
shared. motion setting is missing." Both addressed:

- `settings-storage.ts` (generic localStorage hook), `theme-apply.ts`,
  `motion-apply.ts`, and `SettingsMenu.tsx`/`.css` all move from
  swarm-ui's `lib/`/`shell/` into `@hive/shared/src/settings/` —
  agent's previous local copies are deleted outright rather than kept
  as a second implementation. One component, `Badge` trigger
  everywhere (already used elsewhere in swarm-ui, so not a new visual
  language there either) — storage keys stay caller-owned (`themeKey`/
  `motionKey` props + matching `useApplyThemeOverride`/
  `useApplyMotionOverride` calls at each package's single mount point)
  so agent and swarm-ui keep fully independent, non-colliding
  persisted settings.
- Agent's settings menu now includes the motion row, matching
  swarm-ui's. No animation in the agent package is gated behind
  `data-motion` yet — same as when swarm-ui first built this plumbing
  ahead of having a consumer — so it's currently inert there, ready for
  whenever agent grows a motion-guarded animation.
- swarm-ui's own theme default flips to `'dark'` as part of this move
  (`theme-apply.ts`'s new default), superseding PR #3715 — that PR
  becomes redundant once this lands and will be closed rather than
  merged, to avoid the two colliding on the same file.

Verified end-to-end with real screenshots on both pages: shared
component renders identically (Badge trigger, theme+motion rows, dark
default) on agent's mock server and a static rebuild of swarm-ui's
dist.
This commit is contained in:
iris 2026-08-29 11:11:39 +02:00
commit 9720bdfad0
16 changed files with 230 additions and 487 deletions

View file

@ -1,44 +0,0 @@
/* <SettingsMenu> popover matches `MetaNav`'s popover values exactly
(`../components/MetaNav.css`), which in turn match `@hive/shared`'s
`Dropdown` (`.ui-dropdown`) same "reuse the values, not the
component" call, this popover holds a `<select>` row, not
`Dropdown`'s command-dispatch `<button>`s or `MetaNav`'s `<a>`s.
Right-anchored sits in the header's right-hand pills cluster next
to `MetaNav`, so a left anchor would push it off-screen. */
.settings-menu-anchor {
position: relative;
display: inline-block;
}
.settings-menu-popover {
position: absolute;
top: calc(100% + 0.25em);
right: 0;
left: auto;
z-index: 20;
display: flex;
flex-direction: column;
min-width: 10em;
padding: 0.5em;
background: var(--bg-elev);
border: 1px solid var(--border);
border-radius: 0.5em;
box-shadow: 0 0.4em 1em rgba(0, 0, 0, 0.35);
}
.settings-menu-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.75em;
min-height: 2.75em;
padding: 0 0.3em;
color: var(--fg);
}
.settings-menu-row select {
min-height: 2.75em;
padding: 0 0.4em;
border: 1px solid var(--border);
border-radius: 0.35em;
background: var(--bg);
color: var(--fg);
font: inherit;
}