feat(design): animated design system foundation with animate-ui and motion

Install motion + animate-ui, overhaul design tokens with brand cyan accent,
and replace CSS keyframe animations in Dialog, Tabs, Switch, and Tooltip
with spring-physics and blur-fade transitions via animate-ui Radix primitives.
This commit is contained in:
SaelixCode
2026-03-20 22:25:29 -04:00
parent 4d1aef744b
commit 0cb5fae947
39 changed files with 5634 additions and 441 deletions
+169 -37
View File
@@ -4,6 +4,9 @@
@custom-variant dark (&:is(.dark *));
/* ─────────────────────────────────────────────────────────────
LIGHT THEME
───────────────────────────────────────────────────────────── */
:root {
--background: oklch(1 0 0);
--foreground: oklch(0 0 0);
@@ -23,12 +26,21 @@
--destructive-foreground: oklch(1 0 0);
--border: oklch(0.9200 0 0);
--input: oklch(0.9400 0 0);
--ring: oklch(0 0 0);
--ring: oklch(0.50 0.14 200);
/* Brand — technical cyan, the signature accent */
--brand: oklch(0.50 0.14 200);
--brand-foreground: oklch(1 0 0);
--brand-muted: oklch(0.50 0.14 200 / 0.12);
/* Charts */
--chart-1: oklch(0.8100 0.1700 75.3500);
--chart-2: oklch(0.5500 0.2200 264.5300);
--chart-3: oklch(0.7200 0 0);
--chart-4: oklch(0.9200 0 0);
--chart-5: oklch(0.5600 0 0);
/* Sidebar */
--sidebar: oklch(0.9900 0 0);
--sidebar-foreground: oklch(0 0 0);
--sidebar-primary: oklch(0 0 0);
@@ -36,11 +48,17 @@
--sidebar-accent: oklch(0.9400 0 0);
--sidebar-accent-foreground: oklch(0 0 0);
--sidebar-border: oklch(0.9400 0 0);
--sidebar-ring: oklch(0 0 0);
--font-sans: Geist, sans-serif;
--sidebar-ring: oklch(0.50 0.14 200);
/* Typography */
--font-sans: 'Geist', sans-serif;
--font-serif: Georgia, serif;
--font-mono: Geist Mono, monospace;
--font-mono: 'Geist Mono', monospace;
/* Shape */
--radius: 0.5rem;
/* Shadows */
--shadow-x: 0px;
--shadow-y: 1px;
--shadow-blur: 2px;
@@ -55,14 +73,26 @@
--shadow-lg: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 4px 6px -1px hsl(0 0% 0% / 0.18);
--shadow-xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 8px 10px -1px hsl(0 0% 0% / 0.18);
--shadow-2xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.45);
/* Motion timing */
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
--duration-fast: 150ms;
--duration-base: 220ms;
--duration-slow: 350ms;
--tracking-normal: 0em;
--spacing: 0.25rem;
}
/* ─────────────────────────────────────────────────────────────
DARK THEME
───────────────────────────────────────────────────────────── */
.dark {
--background: oklch(0.1400 0 0);
--foreground: oklch(1 0 0);
--card: oklch(0.1400 0 0);
--card: oklch(0.1600 0 0);
--card-foreground: oklch(1 0 0);
--popover: oklch(0.1800 0 0);
--popover-foreground: oklch(1 0 0);
@@ -78,12 +108,21 @@
--destructive-foreground: oklch(0 0 0);
--border: oklch(0.2600 0 0);
--input: oklch(0.3200 0 0);
--ring: oklch(0.7200 0 0);
--ring: oklch(0.72 0.14 200);
/* Brand — bright technical cyan on dark backgrounds */
--brand: oklch(0.72 0.14 200);
--brand-foreground: oklch(0.05 0 0);
--brand-muted: oklch(0.72 0.14 200 / 0.12);
/* Charts */
--chart-1: oklch(0.8100 0.1700 75.3500);
--chart-2: oklch(0.5800 0.2100 260.8400);
--chart-3: oklch(0.5600 0 0);
--chart-4: oklch(0.4400 0 0);
--chart-5: oklch(0.9200 0 0);
/* Sidebar */
--sidebar: oklch(0.1800 0 0);
--sidebar-foreground: oklch(1 0 0);
--sidebar-primary: oklch(1 0 0);
@@ -91,27 +130,36 @@
--sidebar-accent: oklch(0.3200 0 0);
--sidebar-accent-foreground: oklch(1 0 0);
--sidebar-border: oklch(0.3200 0 0);
--sidebar-ring: oklch(0.7200 0 0);
--font-sans: Geist, sans-serif;
--sidebar-ring: oklch(0.72 0.14 200);
/* Typography */
--font-sans: 'Geist', sans-serif;
--font-serif: Georgia, serif;
--font-mono: Geist Mono, monospace;
--font-mono: 'Geist Mono', monospace;
/* Shape */
--radius: 0.5rem;
/* Shadows — deeper on dark backgrounds */
--shadow-x: 0px;
--shadow-y: 1px;
--shadow-blur: 2px;
--shadow-spread: 0px;
--shadow-opacity: 0.18;
--shadow-opacity: 0.35;
--shadow-color: hsl(0 0% 0%);
--shadow-2xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09);
--shadow-xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.09);
--shadow-sm: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18);
--shadow: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 1px 2px -1px hsl(0 0% 0% / 0.18);
--shadow-md: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 2px 4px -1px hsl(0 0% 0% / 0.18);
--shadow-lg: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 4px 6px -1px hsl(0 0% 0% / 0.18);
--shadow-xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.18), 0px 8px 10px -1px hsl(0 0% 0% / 0.18);
--shadow-2xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.45);
--shadow-2xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.18);
--shadow-xs: 0px 1px 2px 0px hsl(0 0% 0% / 0.18);
--shadow-sm: 0px 1px 2px 0px hsl(0 0% 0% / 0.35), 0px 1px 2px -1px hsl(0 0% 0% / 0.35);
--shadow: 0px 1px 2px 0px hsl(0 0% 0% / 0.35), 0px 1px 2px -1px hsl(0 0% 0% / 0.35);
--shadow-md: 0px 1px 2px 0px hsl(0 0% 0% / 0.35), 0px 2px 4px -1px hsl(0 0% 0% / 0.35);
--shadow-lg: 0px 1px 2px 0px hsl(0 0% 0% / 0.35), 0px 4px 6px -1px hsl(0 0% 0% / 0.35);
--shadow-xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.35), 0px 8px 10px -1px hsl(0 0% 0% / 0.35);
--shadow-2xl: 0px 1px 2px 0px hsl(0 0% 0% / 0.65);
}
/* ─────────────────────────────────────────────────────────────
TAILWIND THEME MAPPING
───────────────────────────────────────────────────────────── */
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
@@ -132,6 +180,9 @@
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-brand: var(--brand);
--color-brand-foreground: var(--brand-foreground);
--color-brand-muted: var(--brand-muted);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
@@ -165,6 +216,9 @@
--shadow-2xl: var(--shadow-2xl);
}
/* ─────────────────────────────────────────────────────────────
BASE STYLES
───────────────────────────────────────────────────────────── */
@layer base {
:root {
color-scheme: dark;
@@ -179,22 +233,9 @@
}
}
/* Custom Dark Mode Scrollbar */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: hsl(var(--muted) / 0.8);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: hsl(var(--muted-foreground) / 0.5);
}
/* ─────────────────────────────────────────────────────────────
TYPOGRAPHY & RENDERING
───────────────────────────────────────────────────────────── */
html,
body,
#root {
@@ -204,7 +245,8 @@ body,
}
body {
font-family: var(--font-sans), system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-family: var(--font-sans), system-ui, -apple-system, BlinkMacSystemFont,
'Segoe UI', sans-serif;
line-height: 1.5;
font-weight: 400;
font-synthesis: none;
@@ -213,7 +255,97 @@ body {
-moz-osx-font-smoothing: grayscale;
}
/* xterm.js styles */
/* ─────────────────────────────────────────────────────────────
SCROLLBAR
───────────────────────────────────────────────────────────── */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: oklch(0.40 0 0 / 0.5);
border-radius: 4px;
transition: background var(--duration-fast) ease;
}
::-webkit-scrollbar-thumb:hover {
background: oklch(0.55 0 0 / 0.7);
}
.dark ::-webkit-scrollbar-thumb {
background: oklch(0.35 0 0 / 0.6);
}
.dark ::-webkit-scrollbar-thumb:hover {
background: oklch(0.50 0 0 / 0.8);
}
/* ─────────────────────────────────────────────────────────────
ANIMATION KEYFRAMES
───────────────────────────────────────────────────────────── */
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes fade-up {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes fade-down {
from { opacity: 0; transform: translateY(-8px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes slide-in-left {
from { opacity: 0; transform: translateX(-12px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes scale-in {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
/* ─────────────────────────────────────────────────────────────
ANIMATION UTILITIES
───────────────────────────────────────────────────────────── */
.animate-fade-in {
animation: fade-in var(--duration-base) var(--ease-out-expo) both;
}
.animate-fade-up {
animation: fade-up var(--duration-base) var(--ease-out-expo) both;
}
.animate-fade-down {
animation: fade-down var(--duration-base) var(--ease-out-expo) both;
}
.animate-slide-in-left {
animation: slide-in-left var(--duration-base) var(--ease-out-expo) both;
}
.animate-scale-in {
animation: scale-in var(--duration-fast) var(--ease-spring) both;
}
/* Stagger delay helpers */
.animate-delay-50 { animation-delay: 50ms; }
.animate-delay-100 { animation-delay: 100ms; }
.animate-delay-150 { animation-delay: 150ms; }
.animate-delay-200 { animation-delay: 200ms; }
.animate-delay-300 { animation-delay: 300ms; }
/* ─────────────────────────────────────────────────────────────
PREFERS REDUCED MOTION — zero-cost accessibility
───────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* ─────────────────────────────────────────────────────────────
XTERM.JS
───────────────────────────────────────────────────────────── */
.xterm {
padding: 0;
}
}