feat(deps): Tailwind 3 → 4 + swap tailwindcss-animate for tw-animate-css
Ran the official @tailwindcss/upgrade tool: - tailwind.config.ts → @theme directive in globals.css - @tailwind base/components/utilities → @import 'tailwindcss' - postcss.config switched from tailwindcss + autoprefixer to @tailwindcss/postcss (autoprefixer baked in) - focus-visible:outline-none → focus-visible:outline-hidden (the v3 utility was a footgun — outline still showed in forced-colors mode) Reverted the migration tool's over-zealous variant="outline" → variant="outline-solid" rename on CVA prop values; that rename was meant for the Tailwind `outline:` utility, not our Button/Badge component variants. Swapped tailwindcss-animate (v3-style JS plugin) for tw-animate-css (v4-native @import). Same utility surface (animate-spin, animate-in, etc.), one fewer JS plugin in the bundle. Fixed the upgrade tool's malformed dark variant (@custom-variant dark (&:is(class *)) — `class` was being parsed as a tag) to canonical &:where(.dark, .dark *). Verified: tsc 0 errors, eslint 0 errors (16 pre-existing warnings), vitest 1315/1315, next build clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,183 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
@import 'tailwindcss';
|
||||
@import 'tw-animate-css';
|
||||
|
||||
@custom-variant dark (&:where(.dark, .dark *));
|
||||
|
||||
@theme {
|
||||
--color-border: hsl(var(--border));
|
||||
--color-input: hsl(var(--input));
|
||||
--color-ring: hsl(var(--ring));
|
||||
--color-background: hsl(var(--background));
|
||||
--color-foreground: hsl(var(--foreground));
|
||||
|
||||
--color-primary: hsl(var(--primary));
|
||||
--color-primary-foreground: hsl(var(--primary-foreground));
|
||||
|
||||
--color-secondary: hsl(var(--secondary));
|
||||
--color-secondary-foreground: hsl(var(--secondary-foreground));
|
||||
|
||||
--color-destructive: hsl(var(--destructive));
|
||||
--color-destructive-foreground: hsl(var(--destructive-foreground));
|
||||
|
||||
--color-muted: hsl(var(--muted));
|
||||
--color-muted-foreground: hsl(var(--muted-foreground));
|
||||
|
||||
--color-accent: hsl(var(--accent));
|
||||
--color-accent-foreground: hsl(var(--accent-foreground));
|
||||
|
||||
--color-popover: hsl(var(--popover));
|
||||
--color-popover-foreground: hsl(var(--popover-foreground));
|
||||
|
||||
--color-card: hsl(var(--card));
|
||||
--color-card-foreground: hsl(var(--card-foreground));
|
||||
|
||||
--color-brand-50: #d8e5f4;
|
||||
--color-brand-100: #b1cbe9;
|
||||
--color-brand-200: #89b0de;
|
||||
--color-brand-300: #6196d3;
|
||||
--color-brand-400: #3a7bc8;
|
||||
--color-brand-500: #2f6ab5;
|
||||
--color-brand-600: #255a9e;
|
||||
--color-brand-700: #1c4a87;
|
||||
--color-brand: #3a7bc8;
|
||||
--color-brand-dark: #1e2844;
|
||||
|
||||
--color-navy-50: #cdcfd6;
|
||||
--color-navy-100: #9ea1af;
|
||||
--color-navy-200: #71768a;
|
||||
--color-navy-300: #474e66;
|
||||
--color-navy-400: #1e2844;
|
||||
--color-navy-500: #171f35;
|
||||
--color-navy-600: #101625;
|
||||
--color-navy: #1e2844;
|
||||
|
||||
--color-sage: #dae3c1;
|
||||
--color-sage-light: #edf1e2;
|
||||
--color-sage-dark: #b8c49e;
|
||||
|
||||
--color-mint: #add5b3;
|
||||
--color-mint-light: #d6ead9;
|
||||
--color-mint-dark: #7dba85;
|
||||
|
||||
--color-teal: #83aab1;
|
||||
--color-teal-light: #b1cdd2;
|
||||
--color-teal-dark: #5a8a92;
|
||||
|
||||
--color-purple: #685aa3;
|
||||
--color-purple-light: #a49ac6;
|
||||
--color-purple-dark: #4d4280;
|
||||
|
||||
--color-success: #2d8a4e;
|
||||
--color-success-bg: #e8f5e9;
|
||||
--color-success-border: #a5d6a7;
|
||||
|
||||
--color-warning: #e6a817;
|
||||
--color-warning-bg: #fff8e1;
|
||||
--color-warning-border: #ffe082;
|
||||
|
||||
--color-error: #d32f2f;
|
||||
--color-error-bg: #ffebee;
|
||||
--color-error-border: #ef9a9a;
|
||||
|
||||
--color-sidebar: #1e2844;
|
||||
--color-sidebar-text: #cdcfd6;
|
||||
--color-sidebar-hover: #171f35;
|
||||
--color-sidebar-active: #3a7bc8;
|
||||
--color-sidebar-divider: #474e66;
|
||||
|
||||
--font-sans: Inter, system-ui, -apple-system, Arial, sans-serif;
|
||||
--font-mono: JetBrains Mono, ui-monospace, monospace;
|
||||
--font-serif: Georgia, Times New Roman, serif;
|
||||
|
||||
--shadow-xs: 0 1px 2px 0 rgb(15 23 42 / 0.04);
|
||||
--shadow-sm: 0 2px 4px -1px rgb(15 23 42 / 0.06);
|
||||
--shadow: 0 1px 3px rgba(30, 40, 68, 0.1), 0 1px 2px rgba(30, 40, 68, 0.06);
|
||||
--shadow-md: 0 4px 12px -2px rgb(15 23 42 / 0.08);
|
||||
--shadow-lg: 0 12px 32px -8px rgb(15 23 42 / 0.12);
|
||||
--shadow-xl: 0 20px 25px rgba(30, 40, 68, 0.1), 0 8px 10px rgba(30, 40, 68, 0.04);
|
||||
--shadow-glow: 0 0 0 4px rgb(58 123 200 / 0.12);
|
||||
|
||||
--radius-sm: 0.375rem;
|
||||
--radius: 0.375rem;
|
||||
--radius-md: 0.5rem;
|
||||
--radius-lg: 0.625rem;
|
||||
--radius-xl: 0.875rem;
|
||||
|
||||
--background-image-gradient-brand: linear-gradient(135deg, #3a7bc8 0%, #2f6ab5 100%);
|
||||
--background-image-gradient-brand-soft: linear-gradient(135deg, #d8e5f4 0%, #ffffff 100%);
|
||||
--background-image-gradient-success: linear-gradient(135deg, #e8f5e9 0%, #ffffff 100%);
|
||||
--background-image-gradient-warning: linear-gradient(135deg, #fef3c7 0%, #ffffff 100%);
|
||||
|
||||
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
--ease-smooth: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
--width-sidebar: 256px;
|
||||
--width-sidebar-collapsed: 64px;
|
||||
|
||||
--transition-duration-sidebar: 200ms;
|
||||
--transition-duration-fast: 150ms;
|
||||
--transition-duration-base: 200ms;
|
||||
--transition-duration-slow: 300ms;
|
||||
|
||||
--spacing-safe: env(safe-area-inset-bottom);
|
||||
--spacing-safe-top: env(safe-area-inset-top);
|
||||
--spacing-safe-bottom: env(safe-area-inset-bottom);
|
||||
--spacing-safe-left: env(safe-area-inset-left);
|
||||
--spacing-safe-right: env(safe-area-inset-right);
|
||||
|
||||
--animate-accordion-down: accordion-down 0.2s ease-out;
|
||||
--animate-accordion-up: accordion-up 0.2s ease-out;
|
||||
--animate-badge-pop: badge-pop 0.32s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
|
||||
@keyframes accordion-down {
|
||||
from {
|
||||
height: 0;
|
||||
}
|
||||
to {
|
||||
height: var(--radix-accordion-content-height);
|
||||
}
|
||||
}
|
||||
@keyframes accordion-up {
|
||||
from {
|
||||
height: var(--radix-accordion-content-height);
|
||||
}
|
||||
to {
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
@keyframes badge-pop {
|
||||
0% {
|
||||
transform: scale(0.5);
|
||||
opacity: 0;
|
||||
}
|
||||
60% {
|
||||
transform: scale(1.18);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
The default border color has changed to `currentcolor` in Tailwind CSS v4,
|
||||
so we've added these compatibility styles to make sure everything still
|
||||
looks the same as it did with Tailwind CSS v3.
|
||||
|
||||
If we ever want to remove these styles, we need to add an explicit border
|
||||
color utility to any element that depends on these defaults.
|
||||
*/
|
||||
@layer base {
|
||||
*,
|
||||
::after,
|
||||
::before,
|
||||
::backdrop,
|
||||
::file-selector-button {
|
||||
border-color: var(--color-gray-200, currentcolor);
|
||||
}
|
||||
}
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
|
||||
Reference in New Issue
Block a user