feat(ui): F0 — Tailwind + design tokens + theme infrastructure

Install Tailwind v3, Radix primitives, cva/tailwind-merge/clsx, lucide-react.
Add HSL design tokens (light + dark) with the Indigo #5b5bf0 accent isolated
to a single --primary token (swappable for a future accent picker), darkMode
'class', anti-flash inline script, useTheme hook, and cn() helper. styles.css
still loads for not-yet-migrated pages. Build green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
cesnimda
2026-06-30 23:11:51 +02:00
parent 6af03ea807
commit 1bd8143a87
9 changed files with 2279 additions and 2 deletions
+64
View File
@@ -0,0 +1,64 @@
/** @type {import('tailwindcss').Config} */
export default {
darkMode: 'class',
content: ['./index.html', './src/**/*.{js,jsx}'],
theme: {
extend: {
colors: {
// All colors reference CSS variables (defined in src/index.css) so the
// whole palette — including the accent — is swappable in one place and
// flips automatically between light and `.dark`.
background: 'hsl(var(--background) / <alpha-value>)',
foreground: 'hsl(var(--foreground) / <alpha-value>)',
card: {
DEFAULT: 'hsl(var(--card) / <alpha-value>)',
foreground: 'hsl(var(--foreground) / <alpha-value>)',
},
muted: {
DEFAULT: 'hsl(var(--muted) / <alpha-value>)',
foreground: 'hsl(var(--muted-foreground) / <alpha-value>)',
},
border: 'hsl(var(--border) / <alpha-value>)',
input: 'hsl(var(--input) / <alpha-value>)',
ring: 'hsl(var(--ring) / <alpha-value>)',
primary: {
DEFAULT: 'hsl(var(--primary) / <alpha-value>)',
foreground: 'hsl(var(--primary-foreground) / <alpha-value>)',
},
success: 'hsl(var(--success) / <alpha-value>)',
warning: 'hsl(var(--warning) / <alpha-value>)',
danger: {
DEFAULT: 'hsl(var(--danger) / <alpha-value>)',
foreground: 'hsl(var(--danger-foreground) / <alpha-value>)',
},
},
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)',
},
boxShadow: {
sm: '0 1px 2px 0 hsl(var(--foreground) / 0.05)',
DEFAULT: '0 1px 3px 0 hsl(var(--foreground) / 0.08), 0 1px 2px -1px hsl(var(--foreground) / 0.06)',
md: '0 4px 12px -2px hsl(var(--foreground) / 0.10)',
},
keyframes: {
'fade-in': { from: { opacity: 0 }, to: { opacity: 1 } },
'slide-up': {
from: { opacity: 0, transform: 'translateY(6px)' },
to: { opacity: 1, transform: 'translateY(0)' },
},
'slide-in-right': {
from: { transform: 'translateX(100%)' },
to: { transform: 'translateX(0)' },
},
},
animation: {
'fade-in': 'fade-in 150ms ease-out',
'slide-up': 'slide-up 180ms ease-out',
'slide-in-right': 'slide-in-right 220ms ease-out',
},
},
},
plugins: [],
};