settings menu: replace showExpandDetails prop with a children slot

mara, reviewing PR#3780's showExpandDetails boolean prop: "you cannot
just add it like this - if we have more and more options there in
different places we will keep accumulating cruft in the shared
component." SettingsMenu now exposes a plain children slot instead;
the agent page owns its expand-tool-output row entirely (state,
storage, markup) in its own ExpandDetailsSetting component and passes
it in, so the shared component never learns that setting exists.
This commit is contained in:
iris 2026-08-30 15:55:23 +02:00 committed by mara
commit 33fafc8c19
3 changed files with 52 additions and 31 deletions

View file

@ -11,6 +11,7 @@ import { useApplyThemeOverride } from '@hive/shared/theme-apply.js';
import { useApplyMotionOverride } from '@hive/shared/motion-apply.js';
import { Header } from './components/Header.js';
import { MetaNav } from './components/MetaNav.js';
import { ExpandDetailsSetting } from './components/ExpandDetailsSetting.js';
import { StatusChips } from './components/StatusChips.js';
import { LiveStream, type LiveStreamHandle } from './components/LiveStream.js';
import { HeaderPill } from './components/HeaderPill.js';
@ -113,7 +114,9 @@ export function Root() {
dashboardBase={resolveDashboardBase(state.dashboard_port)}
/>
) : null}
<SettingsMenu themeKey={THEME_KEY} motionKey={MOTION_KEY} showExpandDetails />
<SettingsMenu themeKey={THEME_KEY} motionKey={MOTION_KEY}>
<ExpandDetailsSetting />
</SettingsMenu>
</>
);
// Kept mounted regardless of `openPanel` (open/closed toggles just the

View file

@ -0,0 +1,35 @@
// Agent-terminal-only settings-menu row: "expand tool output panels".
// Rendered as a `<SettingsMenu>` child (`@hive/shared/settings-menu.js`)
// rather than a prop on that shared component — `SettingsMenu` is also
// used by swarm-ui, which has no terminal to apply this to, and a prior
// attempt to gate it behind a boolean prop (`showExpandDetails`) on the
// shared component drew mara's review: "you cannot just add it like
// this - if we have more and more options there in different places we
// will keep accumulating cruft in the shared component." This file owns
// its own state/storage entirely; `SettingsMenu` just renders it as a
// child, no different from any other consumer's markup.
import { useState } from 'preact/hooks';
import { getExpandDetailsPref, setExpandDetailsPref } from '@hive/shared/prefs.js';
export function ExpandDetailsSetting() {
// Plain localStorage read, not a hook-managed override like
// theme/motion — `getExpandDetailsPref`/`setExpandDetailsPref`
// (`@hive/shared/prefs.js`) are the existing shared-storage-key pair
// the terminal itself already reads live (no round-trip needed here
// beyond re-rendering this row's own checkbox state on toggle).
const [expandDetails, setExpandDetailsState] = useState(() => getExpandDetailsPref());
return (
<label class="settings-menu-row">
<span>expand tool output</span>
<input
type="checkbox"
checked={expandDetails}
onChange={(e) => {
const v = (e.target as HTMLInputElement).checked;
setExpandDetailsPref(v);
setExpandDetailsState(v);
}}
/>
</label>
);
}