feat(ui): rebuild shared chrome and core browse/read pages

- Header: sticky app-wide, active nav highlighting, data-driven theme
  picker with active swatch, unified SVG icons, deduped login fragment
  (was duplicated verbatim for desktop + mobile), removed stray console.log
- LibrarySwitcher: cleaner sticky bar, SVG action icons, theme-aware
- BookCard: the atomic unit now has a real surface (was floating text
  when wood-paneling was off due to an undefined --wood-border), with
  cohesive shadow + hover lift; reused across dashboard/bookshelf/series
- Dashboard: calmer section headers, snap carousels with SVG chevrons
- Bookshelf: recompose the filter wall into a search toolbar + collapsible
  Filters panel (all 9 filters + save/load/clear preserved), redesigned
  empty state and pagination
- Book detail, series, collections, browse: cohesive cards, SVG action
  icons, uppercase muted labels, theme-aware badges/links
This commit is contained in:
2026-08-05 16:01:09 -04:00
parent 6f271d624f
commit 28e40e302c
19 changed files with 3127 additions and 2593 deletions
+22 -23
View File
@@ -1,28 +1,27 @@
package templates
templ LibrarySwitcher(libData []LibraryData, currentLibraryID string, actions ...templ.Component) {
<div class="sticky top-0 z-40 bg-opacity-95 backdrop-blur border-b" style="background-color: var(--bg-primary);">
<div class="w-full px-4 py-3 flex items-center justify-between">
<div class="flex items-center gap-4">
<label class="text-sm font-medium" style="color: var(--text-secondary)">Library:</label>
<div class="sticky top-16 z-30 border-b border-line bg-surface/95 backdrop-blur">
<div class="w-full px-4 sm:px-6 lg:px-8 py-2.5 flex items-center justify-between gap-4">
<div class="flex items-center gap-3 min-w-0">
<label class="hidden sm:block text-xs font-semibold uppercase tracking-wide text-content-muted" for="library-select">Library</label>
<select
id="library-select"
name="library_id"
class="px-4 py-2 rounded-lg border focus:ring-2 focus:ring-blue-500"
style="background-color: var(--bg-secondary); color: var(--text-primary);"
class="input w-auto min-w-[12rem] py-1.5"
>
<option value="">All Libraries ({ TotalMediaCount(libData) })</option>
for _, lib := range libData {
if lib.ID == currentLibraryID {
<option value={ lib.ID } selected>{ lib.Name } ({ lib.MediaCount })</option>
} else {
<option value={ lib.ID }>{ lib.Name } ({ lib.MediaCount })</option>
<option value="">All Libraries ({ TotalMediaCount(libData) })</option>
for _, lib := range libData {
if lib.ID == currentLibraryID {
<option value={ lib.ID } selected>{ lib.Name } ({ lib.MediaCount })</option>
} else {
<option value={ lib.ID }>{ lib.Name } ({ lib.MediaCount })</option>
}
}
}
</select>
</div>
if len(actions) > 0 {
<div class="flex items-center gap-2">
<div class="flex items-center gap-1">
for _, action := range actions {
@action
}
@@ -31,10 +30,10 @@ templ LibrarySwitcher(libData []LibraryData, currentLibraryID string, actions ..
</div>
<div
id="loading-spinner"
class="hidden fixed inset-0 bg-opacity-50 flex items-center justify-center z-50"
style="background-color: var(--bg-primary);"
class="hidden fixed inset-0 z-50 flex items-center justify-center"
style="background-color: var(--surface-overlay);"
>
<div class="animate-spin rounded-full h-12 w-12 border-b-2" style="border-color: var(--accent);"></div>
<div class="loading-spinner"></div>
</div>
</div>
}
@@ -42,18 +41,18 @@ templ LibrarySwitcher(libData []LibraryData, currentLibraryID string, actions ..
templ DashboardActions() {
<button
data-action="open-dashboard-settings"
class="p-2 rounded-lg hover:bg-gray-700 transition-colors"
style="background-color: var(--bg-secondary);"
class="icon-btn"
title="Customize Dashboard"
aria-label="Customize Dashboard"
>
⚙️
@Icon("settings", "h-5 w-5")
</button>
<button
data-action="reload-page"
class="p-2 rounded-lg hover:bg-gray-700 transition-colors"
style="background-color: var(--bg-secondary);"
class="icon-btn"
title="Refresh"
aria-label="Refresh"
>
🔄
@Icon("refresh", "h-5 w-5")
</button>
}