Files
bookhoard/templates/theme_flash_guard.templ
John O'Keefe d5bb874651 feat(themes): Omarchy catalog, 12 light themes, Dark/Light Appearance picker
Expand the catalog from 11 themes (10 dark, 1 light) to 37 (24/13):
all 18 remaining Omarchy defaults (palettes from each theme's
colors.toml) plus 8 canonical light themes (Tokyo Night Day, Solarized
Light, One Light, Ayu Light, GitHub Light, Gruvbox Light, Everforest
Light, Kanagawa Lotus). Lupine leads the light list as the default
light theme; the app default stays tokyo-night.

Appearance panel: Dark/Light segmented filter (SSR-initialized from the
user's current theme), scrollable theme list, Bookshelf section pinned;
active row revealed on open. Light themes carry color-scheme: light and
the soft-shadow token set. Public-page theme selects get Dark/Light
optgroups. New moon/sun icons.

tailwind.config: safelist the new theme ids — Tailwind v3 purges custom
@layer base class selectors that appear in no scanned content file, so
an unsafelisted id silently ships without its CSS (found the hard way).

theme.ts: applyTheme now swaps only theme-* classes (changing theme
from the login select no longer wipes min-h-screen) and keeps the class
in sync on <html> for the new ThemeFlashGuard — a pre-paint inline
script on the four public pages that applies the saved theme before
first paint.

Kanagawa's UI accent uses crystalBlue (#7e9cd8) instead of Omarchy's
foreground-as-accent so links stay distinguishable from text.
2026-10-18 12:08:07 -04:00

21 lines
715 B
Templ

package templates
// ThemeFlashGuard applies the browser's saved theme to <html> before first
// paint. Public pages (landing, login, register, setup) render without a
// user, so they cannot SSR the theme class; without this guard they paint
// the :root default (Tokyo Night) and then flash when main.js applies the
// saved theme. The class lands on <html>, where the same --bg-*/--text-*
// variables cascade; body-level classes keep precedence for the subtree.
templ ThemeFlashGuard() {
<script>
(function () {
try {
var t = localStorage.getItem("theme");
if (t && /^[a-z0-9-]+$/.test(t)) {
document.documentElement.classList.add("theme-" + t);
}
} catch (e) {}
})();
</script>
}