agent: add a settings menu with a theme override, defaulted to dark
Ports swarm-ui's `SettingsMenu` (mara: "agent terminal page should get
the settings panel from swarm ui as well") — same shape as `MetaNav`
already in this header: a `Badge` icon trigger ("⚙"), popover, close on
outside-click/Escape.
`theme-apply.ts` + `settings-storage.ts` are near-verbatim ports of
swarm-ui's own (duplicated rather than moved into `@hive/shared` for
this pass — lower risk than reworking swarm-ui's imports in the same
change). Defaults the stored override to 'dark', not 'system', for the
same reason as swarm-ui's own default flip: `prefers-color-scheme` has
no real "unset" value, so 'system' silently reads as light for anyone
who's never touched an OS dark-mode toggle.
Motion NOT ported — agent has no animation gated behind `data-motion`
yet, so that plumbing would have nothing to control.
Verified end-to-end: default dark on a fresh load, and an explicit
localStorage override to 'light' correctly re-themes the whole page via
the existing `colors.css` `:root[data-theme='light']` block (already
shipped, previously only reachable from swarm-ui).
This commit is contained in:
parent
51a9262202
commit
b28e8f1c4e
5 changed files with 233 additions and 0 deletions
|
|
@ -8,6 +8,7 @@ import { useEffect, useRef, useState } from 'preact/hooks';
|
|||
import type { BadgeTone } from '@hive/shared/badge.js';
|
||||
import { Header } from './components/Header.js';
|
||||
import { MetaNav } from './components/MetaNav.js';
|
||||
import { SettingsMenu } from './components/SettingsMenu.js';
|
||||
import { StatusChips } from './components/StatusChips.js';
|
||||
import { LiveStream, type LiveStreamHandle } from './components/LiveStream.js';
|
||||
import { HeaderPill } from './components/HeaderPill.js';
|
||||
|
|
@ -22,6 +23,7 @@ import { fmtAge, fmtTokens } from './lib/format.js';
|
|||
import { resolveDashboardBase } from './lib/dashboardBase.js';
|
||||
import { submitPauseResume } from './lib/pauseAction.js';
|
||||
import { postModel, postEffort } from './lib/modelEffort.js';
|
||||
import { useApplyThemeOverride } from './lib/theme-apply.js';
|
||||
import type { TokenUsage } from './types.js';
|
||||
|
||||
type OpenPanel = 'inbox' | 'todos' | null;
|
||||
|
|
@ -53,6 +55,7 @@ function tokenTotal(u: TokenUsage | null): number | null {
|
|||
}
|
||||
|
||||
export function Root() {
|
||||
useApplyThemeOverride();
|
||||
const { state, refresh } = useAgentState();
|
||||
const { todos, refresh: refreshTodos } = useTodos();
|
||||
const [openPanel, setOpenPanel] = useState<OpenPanel>(null);
|
||||
|
|
@ -100,6 +103,7 @@ export function Root() {
|
|||
dashboardBase={resolveDashboardBase(state.dashboard_port)}
|
||||
/>
|
||||
) : null}
|
||||
<SettingsMenu />
|
||||
</>
|
||||
);
|
||||
// Kept mounted regardless of `openPanel` (open/closed toggles just the
|
||||
|
|
|
|||
Loading…
Reference in a new issue