Watch
0
0
Fork
You've already forked hyperhive
0

swarm ui: a solid backgrounds setting turns the frosted surfaces opaque

A gear-menu toggle, off by default: the header bar, badges and terminal
panes lose their see-through fill and blur.
This commit is contained in:
iris 2026-11-01 13:35:42 +01:00 • committed by mara
commit 099118d31e
4 changed files with 71 additions and 0 deletions

View file

@ -55,6 +55,7 @@
"./hide-debug-setting.js": "./src/settings/HideDebugSetting.tsx",
"./expand-details-setting.js": "./src/settings/ExpandDetailsSetting.tsx",
"./settings-menu.css": "./src/settings/SettingsMenu.css",
"./solid-backgrounds.js": "./src/settings/solid-backgrounds.tsx",
"./user-menu.js": "./src/user-menu/UserMenu.tsx",
"./user-menu.css": "./src/user-menu/UserMenu.css",
"./links-menu.js": "./src/links-menu/LinksMenu.tsx",

View file

@ -0,0 +1,20 @@
/* The frosted surfaces, made opaque while `data-solid="true"` is on `<html>`
(`solid-backgrounds.tsx`). Each rule names the same surface as the rule that
makes it see-through, with `html:root` in front so it outranks that rule's
theme variants whatever order the stylesheets load in. The dialog scrim is
left alone: it dims the page on purpose. */
html:root[data-solid="true"] .shell-header {
background: var(--bg-elev);
-webkit-backdrop-filter: none;
backdrop-filter: none;
}
html:root[data-solid="true"] .ui-badge:not(.ui-badge-quiet) {
background: var(--purple-dim);
-webkit-backdrop-filter: none;
backdrop-filter: none;
}
html:root[data-solid="true"] .terminal-wrap {
background: var(--crust);
-webkit-backdrop-filter: none;
backdrop-filter: none;
}

View file

@ -0,0 +1,39 @@
// "Solid backgrounds" — a gear-menu toggle that turns the frosted, see-through
// surfaces opaque (mara: "add setting to disable transparency", e.g. the top
// bar and badge backgrounds). Off by default, so the look is unchanged until
// someone turns it on.
//
// The setting sets `data-solid="true"` on `<html>`, and `./solid-backgrounds.css`
// answers it. The caller owns the storage key, as with the theme and motion
// overrides, and mounts `useApplySolidBackgrounds` once so the choice applies
// before the menu is ever opened; `SolidBackgroundsSetting` is the menu's row.
import { useEffect } from "preact/hooks";
import { useLocalSetting } from "./settings-storage.js";
import "./solid-backgrounds.css";
export function useApplySolidBackgrounds(key: string): void {
const [solid] = useLocalSetting<boolean>(key, false);
useEffect(() => {
const root = document.documentElement;
if (solid) root.dataset.solid = "true";
else delete root.dataset.solid;
}, [solid]);
}
export function SolidBackgroundsSetting({
storageKey,
}: {
storageKey: string;
}) {
const [solid, setSolid] = useLocalSetting<boolean>(storageKey, false);
return (
<label class="settings-menu-row">
<span>solid backgrounds</span>
<input
type="checkbox"
checked={solid}
onChange={(e) => setSolid((e.target as HTMLInputElement).checked)}
/>
</label>
);
}

View file

@ -37,6 +37,10 @@ import { HideDebugSetting } from "@hive/shared/hide-debug-setting.js";
import { ExpandDetailsSetting } from "@hive/shared/expand-details-setting.js";
import { useApplyThemeOverride } from "@hive/shared/theme-apply.js";
import { useApplyMotionOverride } from "@hive/shared/motion-apply.js";
import {
SolidBackgroundsSetting,
useApplySolidBackgrounds,
} from "@hive/shared/solid-backgrounds.js";
import { isFullBleedRoute, visibleNavItems } from "./routes.js";
import { useDynamicTabs } from "./useDynamicTabs.js";
import { useSwarmName } from "./useSwarmName.js";
@ -49,6 +53,7 @@ import "./Shell.css";
// not `'system'` — see `@hive/shared/theme-apply.js`'s file comment.
const THEME_KEY = "swarm-ui:theme-override";
const MOTION_KEY = "swarm-ui:motion-override";
const SOLID_KEY = "swarm-ui:solid-backgrounds";
const NAV_ITEMS: { href: string; label: string; accent: string }[] = [
{ href: "/agents", label: "agents", accent: "var(--green)" },
@ -220,6 +225,7 @@ export function Shell({ children }: { children: ComponentChildren }) {
// needing a reference to the other.
useApplyThemeOverride(THEME_KEY);
useApplyMotionOverride(MOTION_KEY);
useApplySolidBackgrounds(SOLID_KEY);
// Measures nav item `index`'s rect relative to `.shell-nav`.
// `getBoundingClientRect()` on both elements at the same tick keeps
@ -424,6 +430,7 @@ export function Shell({ children }: { children: ComponentChildren }) {
<SettingsMenu themeKey={THEME_KEY} motionKey={MOTION_KEY}>
<HideDebugSetting />
<ExpandDetailsSetting />
<SolidBackgroundsSetting storageKey={SOLID_KEY} />
</SettingsMenu>
<LinksMenu />
<UserMenu />