feat(ui): theme library, picker, and font-size control#58
Merged
Conversation
Mirror the desktop theming feature on Android. Add a library of named themes (the original SearchMob Light/Dark kept as defaults, plus GitHub, One Dark, Dracula, Tokyo Night, Catppuccin, Gruvbox, Nord, Rose Pine, and two WCAG-AAA accessibility themes) across the Compose app and the served page. A two-slot model layers on the existing light/dark/system control and Material You toggle: the picker chooses which theme fills the light slot and which fills the dark slot, and the quick toggle swaps between them. A font-size control steps the interface and result text by 2pt from a 12pt base, remembered between uses. A shared ui/theme/Themes.kt registry is the single source of palette truth: colorSchemeFor builds Material 3 ColorSchemes for Compose, and themeVars builds the served-page CSS custom properties, so a theme looks the same on both surfaces. The served page reuses the desktop pattern (one [data-theme] block per theme, two-slot localStorage init/toggle, root font size in pt with content in rem, the settings picker, and the nested home scope). Theme and font are local prefs (DataStore / localStorage), never transmitted. Reused palettes are credited in CREDITS.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Mirrors the desktop theming feature on Android: a real theme library with a picker and quality-of-life controls (font size, accessibility), across the Compose app and the served page. Part of the current RC feature pile (merge to
mainbehind green CI; no per-feature release).Themes
A slate of 13: the original SearchMob Light/Dark (kept as defaults, so existing users see no change until they pick a new theme) plus GitHub Light, One Dark, Dracula, Tokyo Night, Catppuccin Mocha/Latte, Gruvbox, Nord, Rose Pine Dawn, and two WCAG-AAA accessibility themes (Paper White, Obsidian Slate). Reused palettes are credited in
CREDITS.md(all MIT). Same ids/palettes as the desktop app for parity.Two-slot model
Layers on the existing light/dark/system control and the Material You toggle: the picker chooses which theme fills the light slot and which fills the dark slot; the quick toggle swaps between them. Material You stays an independent override (when on, it supersedes the named themes, with an in-UI hint).
Font size
A 12pt base with A−/A+ steps of 2pt (bounds 8–24) via a scaled
Typography, remembered between uses.How it's built
ui/theme/Themes.ktis the single source of palette truth:colorSchemeFor(theme)builds Material 3ColorSchemes for Compose;themeVars(theme)builds the served-page CSS custom properties, so a theme looks identical on both surfaces.SearchMobThemeresolves the active theme viaresolveActiveTheme(mode, lightId, darkId, systemDark).SearchServer.kt) mirrors desktop: one[data-theme="<id>"]block per theme, two-slot localStorage init/toggle, root font size inpt+ content inrem, the/settingsAppearance picker, and the nested home-page scope.lightThemeId,darkThemeId,fontPointSize(DataStore).Privacy
Theme and font are local prefs (DataStore /
localStorage), never transmitted, not search data. No new dependencies, no new network calls. Owner/LAN gating and the paging reveal are untouched. NosupportsRtl/i18n (that is a separate later feature).Tests + verification
ThemingTest(13): the slate + desktop-parity id set, the two-slot resolver truth table,colorSchemeFormapping, scaledTypography,clampFontPointSize, and contrast (all themes clear AA body; the two a11y themes hit AAA).ThemeMarkupTest(9): every theme id emits a[data-theme]block; the two-slot init/toggle JS; the/settingspicker;ptroot +remcontent.PreferencesRepositoryTest(+2): slot/font prefs default + round-trip + clamp.[data-theme]blocks.OpenSpec:
openspec/changes/add-theming/(validated--strict).🤖 Generated with Claude Code