Files
bookhoard/tailwind.config.ts
john-okeefe f3f908eb7e feat(ui): design system foundation
Add semantic design tokens and base primitives to replace the verbose
inline var() styling that made the UI feel dated.

- Rename colliding Tailwind color tokens (bg-primary/bg-secondary) to
  semantic names (surface/surface-raised/content/content-muted/brand/line)
- Derive hover, overlay, border-strong, accent-muted and elevation tokens
  once on <body> so they adapt to every theme automatically
- Make :root mirror Tokyo Night to kill the first-paint theme flash
- Add component primitives in @layer components: .card (surface + soft
  shadow, no hard border), .btn variants, .input, .chip, .badge, .icon-btn
- Add theme-aware status/priority badges and global focus-visible styling
- Add an inline-SVG Icon() component (consistent stroke language) to
  replace the mixed emoji/SVG iconography
- Data-drive theme/wood options and add an active-nav helper
- Add skeleton shimmer + x-cloak support
2026-08-05 16:03:07 -04:00

122 lines
3.2 KiB
TypeScript

import type { Config } from "tailwindcss";
const config: Config = {
content: [
"./templates/**/*.{templ,html}",
"./web/static/**/*.{html,js}",
"./web/src/**/*.ts",
],
safelist: [
"theme-tokyo-night",
"theme-dracula",
"theme-nord",
"theme-solarized-dark",
"theme-monokai",
"theme-one-dark-pro",
"theme-material-dark",
"theme-catppuccin-mocha",
"theme-catppuccin-macchiato",
"theme-catppuccin-frappe",
"theme-catppuccin-latte",
],
theme: {
extend: {
screens: {
nav: "970px",
},
fontFamily: {
sans: [
"ui-sans-serif",
"system-ui",
"sans-serif",
'"Noto Sans SC"',
'"Noto Sans TC"',
'"Noto Sans JP"',
'"Noto Sans KR"',
'"PingFang SC"',
'"Microsoft YaHei"',
'"Hiragino Sans"',
'"Apple SD Gothic Neo"',
"Apple Color Emoji",
"Segoe UI Emoji",
"Segoe UI Symbol",
"Noto Color Emoji",
],
},
colors: {
// Semantic surface tokens (page bg, cards, raised layers)
surface: {
DEFAULT: "var(--bg-primary)",
raised: "var(--bg-secondary)",
hover: "var(--surface-hover)",
overlay: "var(--surface-overlay)",
},
// Text tokens
content: {
DEFAULT: "var(--text-primary)",
muted: "var(--text-secondary)",
},
// Accent / brand
brand: {
DEFAULT: "var(--accent)",
muted: "var(--accent-muted)",
},
// Borders / hairlines
line: {
DEFAULT: "var(--border)",
strong: "var(--border-strong)",
},
// Status colors (theme-aware via vars, fall back to fixed)
success: "var(--status-success)",
warning: "var(--status-warning)",
danger: "var(--status-danger)",
info: "var(--status-info)",
},
borderRadius: {
xl: "0.875rem",
"2xl": "1.25rem",
},
boxShadow: {
card: "var(--shadow-card)",
"card-hover": "var(--shadow-card-hover)",
pop: "var(--shadow-pop)",
bar: "var(--shadow-bar)",
},
backgroundImage: {
"wood-light": "url('/static/textures/wood-light.png')",
"wood-dark": "url('/static/textures/wood-dark.png')",
"wood-mahogany": "url('/static/textures/wood-mahogany.png')",
},
typography: ({ theme }) => ({
invert: {
css: {
"--tw-prose-pre-bg": "var(--bg-secondary)",
code: {
backgroundColor: "var(--bg-primary)",
color: "var(--text-primary)",
fontWeight: "400",
},
"code::before": {
content: '""',
},
"code::after": {
content: '""',
},
"pre code": {
backgroundColor: "transparent",
color: "inherit",
},
pre: {
backgroundColor: "var(--bg-secondary)",
color: "var(--text-primary)",
},
},
},
}),
},
},
plugins: [require("@tailwindcss/forms"), require("@tailwindcss/typography")],
};
export default config;