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.
108 lines
4.3 KiB
Go
108 lines
4.3 KiB
Go
package templates
|
|
|
|
// ThemeMode classifies a theme for the Appearance panel's Dark/Light filter.
|
|
type ThemeMode string
|
|
|
|
const (
|
|
ModeDark ThemeMode = "dark"
|
|
ModeLight ThemeMode = "light"
|
|
)
|
|
|
|
// ThemeOption describes a selectable color theme shown in the header picker.
|
|
type ThemeOption struct {
|
|
Name string // CSS theme suffix applied as class theme-<name>
|
|
Label string // Human-readable label
|
|
Color string // Hex swatch colour
|
|
Mode ThemeMode // dark or light — drives the panel's mode filter
|
|
}
|
|
|
|
// ThemeOptions is the full set of selectable colour themes, in display order.
|
|
//
|
|
// Dark themes come first, light themes after. Each mode's list keeps the
|
|
// same shape: the default first, then the long-standing classics, then the
|
|
// newer theme blocks sorted by background luminance (darkest → lightest),
|
|
// the treatment the Catppuccin run introduced. The light list mirrors the
|
|
// dark one: counterparts of the classics in the slots their dark siblings
|
|
// occupy, Catppuccin Latte after them, the Omarchy light block last.
|
|
var ThemeOptions = []ThemeOption{
|
|
// Dark: the original set, order preserved.
|
|
{"tokyo-night", "Tokyo Night", "#7aa2f7", ModeDark},
|
|
{"dracula", "Dracula", "#bd93f9", ModeDark},
|
|
{"nord", "Nord", "#88c0d0", ModeDark},
|
|
{"solarized-dark", "Solarized Dark", "#2aa198", ModeDark},
|
|
{"monokai", "Monokai", "#a6e22e", ModeDark},
|
|
{"one-dark-pro", "One Dark Pro", "#61dafb", ModeDark},
|
|
{"material-dark", "Material Dark", "#80cbc4", ModeDark},
|
|
{"catppuccin-mocha", "Catppuccin Mocha", "#f38ba8", ModeDark},
|
|
{"catppuccin-macchiato", "Catppuccin Macchiato", "#c6a0f6", ModeDark},
|
|
{"catppuccin-frappe", "Catppuccin Frappé", "#ca9ee6", ModeDark},
|
|
// Dark: Omarchy defaults, sorted by background luminance. Palettes come
|
|
// from each theme's colors.toml (github.com/basecamp/omarchy).
|
|
{"vantablack", "Vantablack", "#8d8d8d", ModeDark},
|
|
{"last-horizon", "Last Horizon", "#b59790", ModeDark},
|
|
{"ethereal", "Ethereal", "#7d82d9", ModeDark},
|
|
{"hackerman", "Hackerman", "#82fb9c", ModeDark},
|
|
{"matte-black", "Matte Black", "#e68e0d", ModeDark},
|
|
{"solitude", "Solitude", "#798186", ModeDark},
|
|
{"retro-82", "Retro 82", "#faa968", ModeDark},
|
|
{"osaka-jade", "Osaka Jade", "#509475", ModeDark},
|
|
{"kanagawa", "Kanagawa", "#7e9cd8", ModeDark},
|
|
{"miasma", "Miasma", "#78824b", ModeDark},
|
|
{"lumon", "Lumon", "#8bc9eb", ModeDark},
|
|
{"ristretto", "Ristretto", "#f38d70", ModeDark},
|
|
{"gruvbox", "Gruvbox", "#7daea3", ModeDark},
|
|
{"everforest", "Everforest", "#7fbbb3", ModeDark},
|
|
// Light themes. Lupine leads as the default light theme (the app's
|
|
// real default remains tokyo-night); then counterparts of the classics.
|
|
{"lupine", "Lupine", "#3264eb", ModeLight},
|
|
{"tokyo-night-day", "Tokyo Night Day", "#2e7de9", ModeLight},
|
|
{"solarized-light", "Solarized Light", "#268bd2", ModeLight},
|
|
{"one-light", "One Light", "#4078f2", ModeLight},
|
|
{"ayu-light", "Ayu Light", "#ff9933", ModeLight},
|
|
{"github-light", "GitHub Light", "#0969da", ModeLight},
|
|
{"gruvbox-light", "Gruvbox Light", "#076678", ModeLight},
|
|
{"everforest-light", "Everforest Light", "#3a94c5", ModeLight},
|
|
{"kanagawa-lotus", "Kanagawa Lotus", "#4d699b", ModeLight},
|
|
{"catppuccin-latte", "Catppuccin Latte", "#d20f39", ModeLight},
|
|
// Light: Omarchy defaults, sorted by background luminance.
|
|
{"rose-pine", "Rosé Pine", "#56949f", ModeLight},
|
|
{"flexoki-light", "Flexoki Light", "#205ea6", ModeLight},
|
|
{"white", "White", "#6e6e6e", ModeLight},
|
|
}
|
|
|
|
// ThemeOptionsFor returns the ordered subset of themes for one mode.
|
|
func ThemeOptionsFor(mode ThemeMode) []ThemeOption {
|
|
var out []ThemeOption
|
|
for _, opt := range ThemeOptions {
|
|
if opt.Mode == mode {
|
|
out = append(out, opt)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
// ThemeModeOf returns the mode of a theme name. Unknown or empty ids fall
|
|
// back to dark — the catalog's origin and home of the default theme.
|
|
func ThemeModeOf(name string) ThemeMode {
|
|
for _, opt := range ThemeOptions {
|
|
if opt.Name == name {
|
|
return opt.Mode
|
|
}
|
|
}
|
|
return ModeDark
|
|
}
|
|
|
|
// WoodOption describes a selectable bookshelf background texture.
|
|
type WoodOption struct {
|
|
Name string // value stored as data-wood and CSS bg-<name>
|
|
Label string
|
|
}
|
|
|
|
// WoodOptions is the full set of bookshelf background options.
|
|
var WoodOptions = []WoodOption{
|
|
{"none", "None"},
|
|
{"wood-light", "Wood Light"},
|
|
{"wood-dark", "Wood Dark"},
|
|
{"wood-mahogany", "Wood Mahogany"},
|
|
}
|