ui: theme picker in Settings, and ship the component gallery

The gallery at /theme-sample is now a normal route rather than a development
one, and Settings links to it, so a user can see what a theme actually looks
like before committing to it. Every new component belongs in the gallery: it is
how the design gets reviewed, and how a component that only looks wrong in one
of the four themes gets caught.

Settings gains a Theme section with the new ThemePicker, which explains what
each theme is for - notably that night mode filters videos, documents and maps
to red as well, not just the interface.

Theme names and picker options move to themes/names.ts so the component library
can read them without importing components/Theme.tsx, which still pulls in
Semantic UI. Theme.tsx re-exports them, so existing call sites are unchanged.
The navigation bar's compact picker now reads the same list, so the two cannot
drift apart.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Roland 2026-07-29 19:38:04 -06:00
parent 1bf8ea3da8
commit ea50ee2f16
No known key found for this signature in database
GPG key ID: 1BA620CE6C9A4680
10 changed files with 290 additions and 52 deletions

View file

@ -53,6 +53,63 @@ html[data-theme="night"] .wrolpi-button-danger:hover:not(:disabled) {
/* The icon inside inherits currentColor, so it follows without another rule. */
/* ----------------------------------------------------------- Theme picker */
.wrolpi-theme-picker {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
gap: 10px;
}
.wrolpi-theme-option {
display: flex;
flex-direction: column;
gap: 4px;
align-items: flex-start;
text-align: left;
padding: 10px 12px;
background: var(--panel);
color: var(--text);
border: 1px solid var(--border);
font: inherit;
cursor: pointer;
}
.wrolpi-theme-option:hover {
background: var(--head);
}
/* The selected theme is marked by a heavier border as well as color, so the
selection survives in monochrome themes. */
.wrolpi-theme-option-active {
border: 2px solid var(--blue);
padding: 9px 11px;
}
html[data-theme="night"] .wrolpi-theme-option-active,
html[data-theme="amber"] .wrolpi-theme-option-active {
border-color: var(--text);
}
.wrolpi-theme-option:focus-visible {
outline: 2px solid var(--blue);
outline-offset: 1px;
}
.wrolpi-theme-option-name {
display: inline-flex;
align-items: center;
gap: 7px;
font-weight: 600;
font-size: 13px;
}
.wrolpi-theme-option-description {
font-size: 12px;
color: var(--muted);
line-height: 1.4;
}
/* --------------------------------------------------------------- Switches */
/*
* Mantine's unchecked track is a gray from its own palette, which would put a