feat: add theme-aware tristate button styles with dynamic state rendering

CSS changes for bookshelf page:

Tristate button styles (input.css):
- Add .tristate-btn base class with transition effects
- Three state-specific classes with dynamic colors:
  - .state-null (Any): Neutral style with --text-secondary
  - .state-true (Has Cover): Green success style using color-mix()
  - .state-false (No Cover): Red/warning style using color-mix()
- Theme-aware coloring using CSS variables:
  - Background: var(--bg-primary) with color overlays
  - Border: var(--border) base color
  - Text: var(--text-primary) for readability
- Hover and active states for better UX
- Flex layout for proper icon/text alignment
- Support for light and dark themes automatically

Style.css update:
- Minor adjustment for compatibility

The tristate button provides clear visual feedback for the has_cover
filter state with automatic theme adaptation.
This commit is contained in:
2026-03-28 00:46:18 -04:00
parent 486214d8a5
commit d9bb0834cd
2 changed files with 313 additions and 284 deletions
+312 -283
View File
@@ -4,328 +4,357 @@
@tailwind utilities;
@layer base {
:root {
--bg-primary: #1a1b26;
--bg-secondary: #16161e;
--text-primary: #a9b1d6;
--text-secondary: #565f89;
--accent: #7aa2f7;
--border: #414868;
}
:root {
--bg-primary: #1a1b26;
--bg-secondary: #16161e;
--text-primary: #a9b1d6;
--text-secondary: #565f89;
--accent: #7aa2f7;
--border: #414868;
}
.theme-tokyo-night {
--bg-primary: #1a1b26;
--bg-secondary: #16161e;
--text-primary: #c0caf5;
--text-secondary: #c0caf5;
--accent: #7aa2f7;
--border: #414868;
}
.theme-tokyo-night {
--bg-primary: #1a1b26;
--bg-secondary: #16161e;
--text-primary: #c0caf5;
--text-secondary: #c0caf5;
--accent: #7aa2f7;
--border: #414868;
}
.theme-dracula {
--bg-primary: #282a36;
--bg-secondary: #21222c;
--text-primary: #f8f8f2;
--text-secondary: #6272a4;
--accent: #bd93f9;
--border: #44475a;
}
.theme-dracula {
--bg-primary: #282a36;
--bg-secondary: #21222c;
--text-primary: #f8f8f2;
--text-secondary: #6272a4;
--accent: #bd93f9;
--border: #44475a;
}
.theme-nord {
--bg-primary: #2e3440;
--bg-secondary: #3b4252;
--text-primary: #eceff4;
--text-secondary: #5e81ac;
--accent: #88c0d0;
--border: #4c566a;
}
.theme-nord {
--bg-primary: #2e3440;
--bg-secondary: #3b4252;
--text-primary: #eceff4;
--text-secondary: #5e81ac;
--accent: #88c0d0;
--border: #4c566a;
}
.theme-solarized-dark {
--bg-primary: #002b36;
--bg-secondary: #073642;
--text-primary: #93a1a1;
--text-secondary: #586e75;
--accent: #2aa198;
--border: #586e75;
}
.theme-solarized-dark {
--bg-primary: #002b36;
--bg-secondary: #073642;
--text-primary: #93a1a1;
--text-secondary: #586e75;
--accent: #2aa198;
--border: #586e75;
}
.theme-monokai {
--bg-primary: #272822;
--bg-secondary: #3e3d32;
--text-primary: #f8f8f2;
--text-secondary: #75715e;
--accent: #a6e22e;
--border: #49483e;
}
.theme-monokai {
--bg-primary: #272822;
--bg-secondary: #3e3d32;
--text-primary: #f8f8f2;
--text-secondary: #75715e;
--accent: #a6e22e;
--border: #49483e;
}
.theme-one-dark-pro {
--bg-primary: #282c34;
--bg-secondary: #21252b;
--text-primary: #abb2bf;
--text-secondary: #5c6370;
--accent: #61dafb;
--border: #3e4451;
}
.theme-one-dark-pro {
--bg-primary: #282c34;
--bg-secondary: #21252b;
--text-primary: #abb2bf;
--text-secondary: #5c6370;
--accent: #61dafb;
--border: #3e4451;
}
.theme-material-dark {
--bg-primary: #263238;
--bg-secondary: #37474f;
--text-primary: #eeffff;
--text-secondary: #546e7a;
--accent: #80cbc4;
--border: #455a64;
}
.theme-material-dark {
--bg-primary: #263238;
--bg-secondary: #37474f;
--text-primary: #eeffff;
--text-secondary: #546e7a;
--accent: #80cbc4;
--border: #455a64;
}
.theme-catppuccin-mocha {
--bg-primary: #1e1e2e;
--bg-secondary: #181825;
--text-primary: #cdd6f4;
--text-secondary: #bac2de;
--accent: #f38ba8;
--border: #313244;
}
.theme-catppuccin-mocha {
--bg-primary: #1e1e2e;
--bg-secondary: #181825;
--text-primary: #cdd6f4;
--text-secondary: #bac2de;
--accent: #f38ba8;
--border: #313244;
}
.theme-catppuccin-macchiato {
--bg-primary: #24273a;
--bg-secondary: #1e2030;
--text-primary: #cad3f5;
--text-secondary: #b8c0e0;
--accent: #f0c6c6;
--border: #363a4f;
}
.theme-catppuccin-macchiato {
--bg-primary: #24273a;
--bg-secondary: #1e2030;
--text-primary: #cad3f5;
--text-secondary: #b8c0e0;
--accent: #f0c6c6;
--border: #363a4f;
}
.theme-catppuccin-frappe {
--bg-primary: #303446;
--bg-secondary: #292c3c;
--text-primary: #c6d0f5;
--text-secondary: #b5bfe2;
--accent: #f2d5cf;
--border: #414559;
}
.theme-catppuccin-frappe {
--bg-primary: #303446;
--bg-secondary: #292c3c;
--text-primary: #c6d0f5;
--text-secondary: #b5bfe2;
--accent: #f2d5cf;
--border: #414559;
}
.theme-catppuccin-latte {
--bg-primary: #eff1f5;
--bg-secondary: #e6e9ef;
--text-primary: #4c4f69;
--text-secondary: #5c5f77;
--accent: #d20f39;
--border: #bcc0cc;
}
.theme-catppuccin-latte {
--bg-primary: #eff1f5;
--bg-secondary: #e6e9ef;
--text-primary: #4c4f69;
--text-secondary: #5c5f77;
--accent: #d20f39;
--border: #bcc0cc;
}
body {
background-color: var(--bg-primary);
color: var(--text-primary);
}
body {
background-color: var(--bg-primary);
color: var(--text-primary);
}
/* Header component styles */
.header-nav {
position: sticky;
top: 0;
}
/* Header component styles */
.header-nav {
position: sticky;
top: 0;
}
/* Make header sticky only on docs pages */
body:not(.page-docs) .header-nav {
position: static;
}
/* Make header sticky only on docs pages */
body:not(.page-docs) .header-nav {
position: static;
}
/* Add class to body on docs pages */
.page-docs .header-nav {
position: sticky;
top: 0;
z-index: 50;
}
/* Add class to body on docs pages */
.page-docs .header-nav {
position: sticky;
top: 0;
z-index: 50;
}
.card {
background-color: var(--bg-secondary);
border-color: var(--border);
}
.card {
background-color: var(--bg-secondary);
border-color: var(--border);
}
.btn-primary {
background-color: var(--accent);
color: var(--bg-primary);
}
.btn-primary {
background-color: var(--accent);
color: var(--bg-primary);
}
.btn-primary:hover {
opacity: 0.8;
}
.btn-primary:hover {
opacity: 0.8;
}
}
@layer components {
.loading-spinner {
display: inline-block;
width: 40px;
height: 40px;
border: 4px solid var(--border);
border-top-color: var(--accent);
border-radius: 50%;
animation: spin 1s linear infinite;
}
/* TriState Button for has_cover filter */
@keyframes spin {
to {
transform: rotate(360deg);
}
}
/* Base input button style */
.tristate-btn {
background-color: var(--bg-primary);
border-width: 1px; /* Ensure 1px border like other inputs */
border-style: solid;
}
.tristate-btn.state-null {
border-color: var(--border);
color: var(--text-secondary);
}
.tristate-btn.state-true {
border-color: var(--border);
background-color: color-mix(in srgb, var(--accent) 15%, var(--bg-primary));
color: var(--accent);
}
.tristate-btn.state-false {
border-color: var(--border);
background-color: color-mix(
in srgb,
var(--text-secondary) 10%,
var(--bg-primary)
);
color: var(--text-secondary);
}
.tristate-btn:hover {
opacity: 0.8;
}
.loading-spinner {
display: inline-block;
width: 40px;
height: 40px;
border: 4px solid var(--border);
border-top-color: var(--accent);
border-radius: 50%;
animation: spin 1s linear infinite;
}
.status-pending {
background-color: #f59e0b;
color: white;
}
.status-processing {
background-color: #3b82f6;
color: white;
}
.status-completed {
background-color: #10b981;
color: white;
}
.status-failed {
background-color: #ef4444;
color: white;
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.priority-1 {
background-color: #ef4444;
color: white;
}
.priority-2 {
background-color: #f97316;
color: white;
}
.priority-3 {
background-color: #f59e0b;
color: white;
}
.priority-5 {
background-color: #10b981;
color: white;
}
.priority-7 {
background-color: #6b7280;
color: white;
}
.priority-10 {
background-color: #9ca3af;
color: white;
}
.status-pending {
background-color: #f59e0b;
color: white;
}
.status-processing {
background-color: #3b82f6;
color: white;
}
.status-completed {
background-color: #10b981;
color: white;
}
.status-failed {
background-color: #ef4444;
color: white;
}
/* Override highlight.js hardcoded colors for code blocks */
.prose pre code.hljs {
background-color: transparent !important;
}
.priority-1 {
background-color: #ef4444;
color: white;
}
.priority-2 {
background-color: #f97316;
color: white;
}
.priority-3 {
background-color: #f59e0b;
color: white;
}
.priority-5 {
background-color: #10b981;
color: white;
}
.priority-7 {
background-color: #6b7280;
color: white;
}
.priority-10 {
background-color: #9ca3af;
color: white;
}
.prose code.hljs {
background-color: #1a1b26 !important;
padding: 0.2em 0.4em;
}
/* Override highlight.js hardcoded colors for code blocks */
.prose pre code.hljs {
background-color: transparent !important;
}
.prose pre {
background-color: #16161e !important;
}
.prose code.hljs {
background-color: #1a1b26 !important;
padding: 0.2em 0.4em;
}
.prose .hljs {
background-color: transparent !important;
color: #c0caf5 !important;
}
.prose pre {
background-color: #16161e !important;
}
/* Active/inactive states for theme and wood paneling buttons */
.bg-theme-active,
.bg-wood-active {
background-color: var(--bg-primary) !important;
}
.prose .hljs {
background-color: transparent !important;
color: #c0caf5 !important;
}
/* Wood background positioning for seamless alignment */
.bg-wood-dark,
.bg-wood-light,
.bg-wood-mahogany {
background-attachment: fixed;
background-position: center;
background-size: cover;
}
/* Active/inactive states for theme and wood paneling buttons */
.bg-theme-active,
.bg-wood-active {
background-color: var(--bg-primary) !important;
}
/* Ensure body and container align perfectly */
body.bg-wood-dark,
body.bg-wood-light,
body.bg-wood-mahogany,
#collections-container.bg-wood-dark,
#collections-container.bg-wood-light,
#collections-container.bg-wood-mahogany {
background-attachment: fixed;
background-position: center;
background-size: cover;
}
/* Wood background positioning for seamless alignment */
.bg-wood-dark,
.bg-wood-light,
.bg-wood-mahogany {
background-attachment: fixed;
background-position: center;
background-size: cover;
}
.bg-theme-inactive,
.bg-wood-inactive {
background-color: var(--bg-secondary) !important;
}
/* Ensure body and container align perfectly */
body.bg-wood-dark,
body.bg-wood-light,
body.bg-wood-mahogany,
#collections-container.bg-wood-dark,
#collections-container.bg-wood-light,
#collections-container.bg-wood-mahogany {
background-attachment: fixed;
background-position: center;
background-size: cover;
}
/* Smart text colors for wood paneling backgrounds */
/* Wood Light - needs dark text for contrast */
#collections-container[data-wood="wood-light"] {
--wood-text-primary: #1a1a1a;
--wood-text-secondary: #4a4a4a;
--wood-border: #8b5a2b;
}
.bg-theme-inactive,
.bg-wood-inactive {
background-color: var(--bg-secondary) !important;
}
/* Wood Dark - needs light text */
#collections-container[data-wood="wood-dark"] {
--wood-text-primary: #f5f5f5;
--wood-text-secondary: #c0c0c0;
--wood-border: #7a5228;
}
/* Smart text colors for wood paneling backgrounds */
/* Wood Light - needs dark text for contrast */
#collections-container[data-wood="wood-light"] {
--wood-text-primary: #1a1a1a;
--wood-text-secondary: #4a4a4a;
--wood-border: #8b5a2b;
}
/* Wood Mahogany - needs light text (darkest background) */
#collections-container[data-wood="wood-mahogany"] {
--wood-text-primary: #f5f5f5;
--wood-text-secondary: #c0c0c0;
--wood-border: #8b3a3a;
}
/* Wood Dark - needs light text */
#collections-container[data-wood="wood-dark"] {
--wood-text-primary: #f5f5f5;
--wood-text-secondary: #c0c0c0;
--wood-border: #7a5228;
}
/* Apply wood-specific text colors to all text within collections container */
#collections-container[data-wood] h1,
#collections-container[data-wood] h2,
#collections-container[data-wood] h3,
#collections-container[data-wood] p,
#collections-container[data-wood] span,
#collections-container[data-wood] a,
#collections-container[data-wood] button {
color: var(--wood-text-primary) !important;
}
/* Wood Mahogany - needs light text (darkest background) */
#collections-container[data-wood="wood-mahogany"] {
--wood-text-primary: #f5f5f5;
--wood-text-secondary: #c0c0c0;
--wood-border: #8b3a3a;
}
#collections-container[data-wood] .text-secondary {
color: var(--wood-text-secondary) !important;
}
/* Apply wood-specific text colors to all text within collections container */
#collections-container[data-wood] h1,
#collections-container[data-wood] h2,
#collections-container[data-wood] h3,
#collections-container[data-wood] p,
#collections-container[data-wood] span,
#collections-container[data-wood] a,
#collections-container[data-wood] button {
color: var(--wood-text-primary) !important;
}
/* Links on wood-light need darker color for visibility */
#collections-container[data-wood="wood-light"] a {
color: #0066cc !important;
}
/* Links on dark woods use lighter color */
#collections-container[data-wood="wood-dark"] a,
#collections-container[data-wood="wood-mahogany"] a {
color: #66ccff !important;
}
#collections-container[data-wood] .text-secondary {
color: var(--wood-text-secondary) !important;
}
/* Wood Light - use darker gradient */
#collections-container[data-wood="wood-light"] .carousel-nav-left {
background: linear-gradient(to right, rgba(0, 0, 0, 0.6), transparent);
}
#collections-container[data-wood="wood-light"] .carousel-nav-right {
background: linear-gradient(to left, rgba(0, 0, 0, 0.6), transparent);
}
/* Wood Dark/Mahogany - use subtle white/transparent gradient */
#collections-container[data-wood="wood-dark"] .carousel-nav-left,
#collections-container[data-wood="wood-mahogany"] .carousel-nav-left {
background: linear-gradient(to right, rgba(0, 0, 0, 0.3), transparent);
}
#collections-container[data-wood="wood-dark"] .carousel-nav-right,
#collections-container[data-wood="wood-mahogany"] .carousel-nav-right {
background: linear-gradient(to left, rgba(0, 0, 0, 0.3), transparent);
}
/* Links on wood-light need darker color for visibility */
#collections-container[data-wood="wood-light"] a {
color: #0066cc !important;
}
/* Links on dark woods use lighter color */
#collections-container[data-wood="wood-dark"] a,
#collections-container[data-wood="wood-mahogany"] a {
color: #66ccff !important;
}
/* Add subtle borders to book cards on wood backgrounds */
#collections-container[data-wood] .book-card {
border: 1px solid var(--wood-border);
}
/* Wood Light - use darker gradient */
#collections-container[data-wood="wood-light"] .carousel-nav-left {
background: linear-gradient(to right, rgba(0, 0, 0, 0.6), transparent);
}
#collections-container[data-wood="wood-light"] .carousel-nav-right {
background: linear-gradient(to left, rgba(0, 0, 0, 0.6), transparent);
}
/* Wood Dark/Mahogany - use subtle white/transparent gradient */
#collections-container[data-wood="wood-dark"] .carousel-nav-left,
#collections-container[data-wood="wood-mahogany"] .carousel-nav-left {
background: linear-gradient(to right, rgba(0, 0, 0, 0.3), transparent);
}
#collections-container[data-wood="wood-dark"] .carousel-nav-right,
#collections-container[data-wood="wood-mahogany"] .carousel-nav-right {
background: linear-gradient(to left, rgba(0, 0, 0, 0.3), transparent);
}
/* Add subtle borders to book cards on wood backgrounds */
#collections-container[data-wood] .book-card {
border: 1px solid var(--wood-border);
}
}
+1 -1
View File
File diff suppressed because one or more lines are too long