fix(ui): align theme toggle with dashboard style

This commit is contained in:
vince 2026-06-20 01:33:27 +02:00
parent c84de9aaa9
commit 9c948bd746
7 changed files with 99 additions and 17 deletions

View file

@ -34,8 +34,11 @@ describe("React app dashboard state view", () => {
);
expect(html).toContain('data-ui-theme-toggle="true"');
expect(html).toContain('data-ui-theme-current="dark"');
expect(html).toContain('aria-label="Switch to light theme"');
expect(html).not.toContain("aria-pressed");
expect(html).toContain("Theme");
expect(html).toContain("Dark");
expect(html).toContain("Light");
});
});

View file

@ -15,15 +15,22 @@ export function ThemeToggle({ theme, onThemeChange }: ThemeToggleProps) {
<button
aria-label={label}
className="theme-toggle"
data-ui-theme-current={theme}
data-ui-theme-toggle="true"
onClick={() => onThemeChange(nextTheme)}
type="button"
>
<IconGlyph
name={theme === "dark" ? "mdi:weather-night" : "mdi:white-balance-sunny"}
size="sm"
/>
<span>{theme === "dark" ? "Dark" : "Light"}</span>
<span className="theme-toggle__label">Theme</span>
<span className="theme-toggle__switch" aria-hidden="true">
<span className="theme-toggle__cell" data-active={theme === "dark"}>
<IconGlyph name="mdi:weather-night" size="sm" />
<span>Dark</span>
</span>
<span className="theme-toggle__cell" data-active={theme === "light"}>
<IconGlyph name="mdi:white-balance-sunny" size="sm" />
<span>Light</span>
</span>
</span>
</button>
);
}

View file

@ -6,6 +6,7 @@ import { FooterCell } from "./FooterCell";
import { IconButton } from "./IconButton";
import { ServiceRow } from "./ServiceRow";
import { TelemetryCard } from "./TelemetryCard";
import { ThemeToggle } from "./ThemeToggle";
import { dashboardPreviewFixtures } from "../fixtures";
describe("dashboard UI components", () => {
@ -144,4 +145,20 @@ describe("dashboard UI components", () => {
expect(iconButton).toContain("class=\"icon-button custom-icon-action ");
expect(iconButton).toContain("aria-expanded=\"false\"");
});
test("renders the theme toggle as a segmented instrument control", () => {
const body = renderToString(
<ThemeToggle theme="light" onThemeChange={() => undefined} />,
);
expect(body).toContain('class="theme-toggle"');
expect(body).toContain('data-ui-theme-current="light"');
expect(body).toContain('aria-label="Switch to dark theme"');
expect(body).toContain('class="theme-toggle__label"');
expect(body).toContain('class="theme-toggle__switch"');
expect(body).toContain('data-active="true"');
expect(body).toContain("Theme");
expect(body).toContain("Dark");
expect(body).toContain("Light");
});
});

View file

@ -565,35 +565,90 @@
}
.theme-toggle {
display: inline-grid;
grid-auto-flow: column;
gap: var(--ui-space-2);
display: grid;
grid-template-columns: 2.72rem minmax(0, 1fr);
align-items: center;
justify-content: center;
min-width: 6.5rem;
min-height: 2.15rem;
border: var(--ui-border);
background: var(--ui-color-surface-raised);
width: 9.75rem;
min-width: 0;
min-height: 2.18rem;
border: var(--ui-border-strong);
background: var(--ui-color-surface-module);
color: var(--ui-color-text);
cursor: pointer;
font: inherit;
font-size: 0.62rem;
font-size: 0.55rem;
font-weight: 850;
letter-spacing: 0;
padding: 0 var(--ui-space-3);
padding: 0.13rem;
text-transform: uppercase;
box-shadow: var(--ui-shadow-hard);
}
.theme-toggle:hover {
border-color: var(--ui-color-accent);
color: var(--ui-color-accent);
}
.theme-toggle span {
.theme-toggle__label {
display: grid;
align-self: stretch;
place-items: center;
border-right: var(--ui-border);
color: var(--ui-color-muted);
font-size: 0.48rem;
font-weight: 800;
line-height: 1;
}
.theme-toggle__switch {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 0.1rem;
min-width: 0;
padding-left: 0.1rem;
}
.theme-toggle__cell {
display: grid;
grid-template-columns: auto auto;
gap: 0.2rem;
align-items: center;
justify-content: center;
min-height: 1.68rem;
border: 1px solid transparent;
color: var(--ui-color-muted);
line-height: 1;
padding: 0 0.22rem;
white-space: nowrap;
}
.theme-toggle__cell[data-active="true"] {
border-color: var(--ui-color-accent);
background: var(--ui-color-accent);
color: var(--ui-color-accent-contrast);
}
.theme-toggle__cell > span {
color: currentColor;
}
.theme-toggle:hover .theme-toggle__cell[data-active="false"] {
border-color: var(--ui-color-line);
color: var(--ui-color-text);
}
.theme-toggle .icon-glyph {
width: 0.82rem;
height: 0.82rem;
border: 0;
background: transparent;
color: currentColor;
}
.theme-toggle .icon-glyph svg {
width: 0.78rem;
height: 0.78rem;
}
.icon-glyph {
display: inline-grid;
width: 1.55rem;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 253 KiB

After

Width:  |  Height:  |  Size: 254 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 KiB

After

Width:  |  Height:  |  Size: 275 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 274 KiB

After

Width:  |  Height:  |  Size: 276 KiB

Before After
Before After