@ryanhelsing/ry-ui
Version:
Framework-agnostic, Light DOM web components. CSS is the source of truth.
285 lines (240 loc) • 14.6 kB
CSS
/**
* ry-ui Design Tokens
*
* CORE KNOBS → DERIVED TOKENS → COMPONENTS
*
* Themes only need to set the ~18 core knobs at the top.
* Everything else derives automatically via color-mix() and calc().
* Override any derived token for fine-tuning.
*/
/* ═══════════════════════════════════════════════════════════════
@property — typed custom properties for animation & type safety
Note: color tokens are NOT registered here because @property
prevents light-dark() from re-resolving on dynamic color-scheme
changes in Firefox. Colors use unregistered custom properties.
═══════════════════════════════════════════════════════════════ */
@property --ry-duration-fast { syntax: "<time>"; inherits: true; initial-value: 100ms; }
@property --ry-duration-normal { syntax: "<time>"; inherits: true; initial-value: 200ms; }
@property --ry-duration-slow { syntax: "<time>"; inherits: true; initial-value: 300ms; }
@property --ry-space-1 { syntax: "<length>"; inherits: true; initial-value: 0.25rem; }
@property --ry-space-2 { syntax: "<length>"; inherits: true; initial-value: 0.5rem; }
@property --ry-space-3 { syntax: "<length>"; inherits: true; initial-value: 0.75rem; }
@property --ry-space-4 { syntax: "<length>"; inherits: true; initial-value: 1rem; }
@property --ry-space-6 { syntax: "<length>"; inherits: true; initial-value: 1.5rem; }
@property --ry-space-8 { syntax: "<length>"; inherits: true; initial-value: 2rem; }
@layer ry-tokens, ry-structure, ry-theme;
@layer ry-tokens {
:root {
color-scheme: light dark;
/* ═══════════════════════════════════════════════════════════════
CORE KNOBS — set these to define a theme
═══════════════════════════════════════════════════════════════ */
/* Palette: 3 roles */
--ry-color-primary: light-dark(oklch(0.623 0.188 259.8), oklch(0.714 0.143 254.6));
--ry-color-secondary: light-dark(oklch(0.554 0.041 257.4), oklch(0.711 0.035 256.8));
--ry-color-accent: light-dark(oklch(0.627 0.213 303.9), oklch(0.714 0.183 303.9));
/* Surface */
--ry-color-bg: light-dark(oklch(1 0 0), oklch(0.208 0.04 265.8));
--ry-color-text: light-dark(oklch(0.279 0.037 260), oklch(0.968 0.007 248.1));
/* Semantic (overrideable, but defaults are universal) */
--ry-color-success: oklch(0.723 0.192 149.6);
--ry-color-warning: oklch(0.769 0.165 70.1);
--ry-color-danger: oklch(0.637 0.208 25.3);
--ry-color-info: oklch(0.715 0.126 215.2);
/* Type: 2 fonts */
--ry-font-primary: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
--ry-font-secondary: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
/* Shape */
--ry-radius-base: 0.375rem;
--ry-border-width: 1px;
--ry-outline-width: 0px;
/* Depth */
--ry-shadow-color: light-dark(oklch(0 0 0 / 0.1), oklch(0 0 0 / 0.4));
--ry-shadow-strength: 1;
--ry-shadow-spread: 1;
/* Surface treatment */
--ry-panel-opacity: 1;
--ry-panel-blur: 0px;
/* Motion */
--ry-animation-style: smooth; /* none | smooth | bouncy */
--ry-duration-scale: 1;
/* Density */
--ry-space-scale: 1;
/* ═══════════════════════════════════════════════════════════════
DERIVED: COLORS — auto-generated from core palette
═══════════════════════════════════════════════════════════════ */
/* Hover/active states via color-mix */
--ry-color-primary-hover: color-mix(in oklch, var(--ry-color-primary) 80%, var(--ry-color-text));
--ry-color-primary-active: color-mix(in oklch, var(--ry-color-primary) 65%, var(--ry-color-text));
--ry-color-secondary-hover: color-mix(in oklch, var(--ry-color-secondary) 80%, var(--ry-color-text));
--ry-color-secondary-active: color-mix(in oklch, var(--ry-color-secondary) 65%, var(--ry-color-text));
--ry-color-accent-hover: color-mix(in oklch, var(--ry-color-accent) 80%, var(--ry-color-text));
--ry-color-accent-active: color-mix(in oklch, var(--ry-color-accent) 65%, var(--ry-color-text));
--ry-color-danger-hover: color-mix(in oklch, var(--ry-color-danger) 80%, var(--ry-color-text));
/* Text variants */
--ry-color-text-muted: color-mix(in oklch, var(--ry-color-text) 55%, var(--ry-color-bg));
--ry-color-text-inverse: var(--ry-color-bg);
/* Background variants */
--ry-color-bg-subtle: color-mix(in oklch, var(--ry-color-bg) 96%, var(--ry-color-text));
--ry-color-bg-muted: color-mix(in oklch, var(--ry-color-bg) 92%, var(--ry-color-text));
/* Border variants */
--ry-color-border: color-mix(in oklch, var(--ry-color-bg) 82%, var(--ry-color-text));
--ry-color-border-strong: color-mix(in oklch, var(--ry-color-bg) 70%, var(--ry-color-text));
/* Overlay */
--ry-color-overlay: color-mix(in oklch, var(--ry-color-text) 50%, transparent);
--ry-color-hover-overlay: color-mix(in oklch, var(--ry-color-text) 4%, transparent);
/* Semantic backgrounds & text — derived from base semantic colors */
--ry-color-info-bg: color-mix(in srgb, var(--ry-color-info) 12%, var(--ry-color-bg));
--ry-color-info-text: color-mix(in oklch, var(--ry-color-info) 70%, var(--ry-color-text));
--ry-color-success-bg: color-mix(in srgb, var(--ry-color-success) 12%, var(--ry-color-bg));
--ry-color-success-text: color-mix(in oklch, var(--ry-color-success) 70%, var(--ry-color-text));
--ry-color-warning-bg: color-mix(in srgb, var(--ry-color-warning) 12%, var(--ry-color-bg));
--ry-color-warning-text: color-mix(in oklch, var(--ry-color-warning) 70%, var(--ry-color-text));
--ry-color-danger-bg: color-mix(in srgb, var(--ry-color-danger) 12%, var(--ry-color-bg));
--ry-color-danger-text: color-mix(in oklch, var(--ry-color-danger) 70%, var(--ry-color-text));
/* ═══════════════════════════════════════════════════════════════
DERIVED: CODE SYNTAX — from palette, auto-adapts to any theme
═══════════════════════════════════════════════════════════════ */
--ry-code-bg: var(--ry-color-bg-subtle);
--ry-code-header-bg: var(--ry-color-bg-muted);
--ry-code-text-color: var(--ry-color-text);
--ry-code-title-color: var(--ry-color-text-muted);
--ry-code-icon-color: var(--ry-color-text-muted);
--ry-code-icon-hover-bg: var(--ry-color-bg-muted);
--ry-code-icon-hover-color: var(--ry-color-text);
--ry-code-line-number-color: var(--ry-color-secondary);
--ry-code-line-border-color: var(--ry-color-border);
--ry-code-color-preview-border: var(--ry-color-border);
--ry-code-keyword: var(--ry-color-danger);
--ry-code-property: var(--ry-color-primary);
--ry-code-value: var(--ry-color-accent);
--ry-code-string: var(--ry-color-success);
--ry-code-number: var(--ry-color-warning);
--ry-code-comment: var(--ry-color-text-muted);
--ry-code-selector: var(--ry-color-info);
--ry-code-punctuation: var(--ry-color-text-muted);
--ry-code-tag: var(--ry-color-info);
--ry-code-attribute: var(--ry-color-primary);
/* ═══════════════════════════════════════════════════════════════
DERIVED: TYPOGRAPHY — from core font knobs
═══════════════════════════════════════════════════════════════ */
--ry-font-sans: var(--ry-font-primary);
--ry-font-mono: var(--ry-font-secondary);
/* Font sizes */
--ry-text-xs: 0.75rem;
--ry-text-sm: 0.875rem;
--ry-text-base: 1rem;
--ry-text-lg: 1.125rem;
--ry-text-xl: 1.25rem;
--ry-text-2xl: 1.5rem;
--ry-text-3xl: 1.875rem;
--ry-text-4xl: 2.25rem;
/* Font weights */
--ry-font-normal: 400;
--ry-font-medium: 500;
--ry-font-semibold: 600;
--ry-font-bold: 700;
/* Line heights */
--ry-leading-tight: 1.25;
--ry-leading-normal: 1.5;
--ry-leading-relaxed: 1.75;
/* ═══════════════════════════════════════════════════════════════
DERIVED: SPACING — scaled from base
═══════════════════════════════════════════════════════════════ */
--ry-space-0: 0;
--ry-space-1: calc(0.25rem * var(--ry-space-scale));
--ry-space-2: calc(0.5rem * var(--ry-space-scale));
--ry-space-3: calc(0.75rem * var(--ry-space-scale));
--ry-space-4: calc(1rem * var(--ry-space-scale));
--ry-space-5: calc(1.25rem * var(--ry-space-scale));
--ry-space-6: calc(1.5rem * var(--ry-space-scale));
--ry-space-8: calc(2rem * var(--ry-space-scale));
--ry-space-10: calc(2.5rem * var(--ry-space-scale));
--ry-space-12: calc(3rem * var(--ry-space-scale));
--ry-space-16: calc(4rem * var(--ry-space-scale));
--ry-space-20: calc(5rem * var(--ry-space-scale));
/* ═══════════════════════════════════════════════════════════════
DERIVED: BORDERS & RADIUS — scaled from base
═══════════════════════════════════════════════════════════════ */
--ry-radius-none: 0;
--ry-radius-sm: calc(var(--ry-radius-base) * 0.66);
--ry-radius-md: var(--ry-radius-base);
--ry-radius-lg: calc(var(--ry-radius-base) * 1.33);
--ry-radius-xl: calc(var(--ry-radius-base) * 2);
--ry-radius-2xl: calc(var(--ry-radius-base) * 2.66);
--ry-radius-full: 9999px;
/* ═══════════════════════════════════════════════════════════════
DERIVED: SHADOWS — scaled from strength + spread knobs
═══════════════════════════════════════════════════════════════ */
--ry-shadow-color-sm: color-mix(in oklch, var(--ry-shadow-color) calc(50% * var(--ry-shadow-strength)), transparent);
--ry-shadow-sm:
0
calc(1px * var(--ry-shadow-spread))
calc(2px * var(--ry-shadow-spread))
0
var(--ry-shadow-color-sm);
--ry-shadow-md:
0
calc(4px * var(--ry-shadow-spread))
calc(6px * var(--ry-shadow-spread))
calc(-1px * var(--ry-shadow-spread))
var(--ry-shadow-color),
0
calc(2px * var(--ry-shadow-spread))
calc(4px * var(--ry-shadow-spread))
calc(-2px * var(--ry-shadow-spread))
var(--ry-shadow-color);
--ry-shadow-lg:
0
calc(10px * var(--ry-shadow-spread))
calc(15px * var(--ry-shadow-spread))
calc(-3px * var(--ry-shadow-spread))
var(--ry-shadow-color),
0
calc(4px * var(--ry-shadow-spread))
calc(6px * var(--ry-shadow-spread))
calc(-4px * var(--ry-shadow-spread))
var(--ry-shadow-color);
--ry-shadow-xl:
0
calc(20px * var(--ry-shadow-spread))
calc(25px * var(--ry-shadow-spread))
calc(-5px * var(--ry-shadow-spread))
var(--ry-shadow-color),
0
calc(8px * var(--ry-shadow-spread))
calc(10px * var(--ry-shadow-spread))
calc(-6px * var(--ry-shadow-spread))
var(--ry-shadow-color);
/* ═══════════════════════════════════════════════════════════════
DERIVED: TRANSITIONS — scaled from duration-scale + animation style
═══════════════════════════════════════════════════════════════ */
--ry-duration-fast: calc(100ms * var(--ry-duration-scale));
--ry-duration-normal: calc(200ms * var(--ry-duration-scale));
--ry-duration-slow: calc(300ms * var(--ry-duration-scale));
--ry-ease: cubic-bezier(0.4, 0, 0.2, 1);
--ry-ease-in: cubic-bezier(0.4, 0, 1, 1);
--ry-ease-out: cubic-bezier(0, 0, 0.2, 1);
--ry-ease-out-back: cubic-bezier(0.34, 1.85, 0.64, 1);
--ry-ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1);
--ry-ease-in-out-expo: cubic-bezier(1, 0, 0, 1);
/* ═══════════════════════════════════════════════════════════════
Z-INDEX (not themeable — structural)
═══════════════════════════════════════════════════════════════ */
--ry-z-dropdown: 1000;
--ry-z-sticky: 1020;
--ry-z-fixed: 1030;
--ry-z-modal-backdrop: 1040;
--ry-z-modal: 1050;
--ry-z-popover: 1060;
--ry-z-tooltip: 1070;
--ry-z-toast: 1080;
/* ═══════════════════════════════════════════════════════════════
DERIVED: FOCUS — from primary
═══════════════════════════════════════════════════════════════ */
--ry-focus-ring: 0 0 0 3px color-mix(in oklch, var(--ry-color-primary) 50%, transparent);
}
/* Force light or dark mode */
[data-ry-theme="light"] { color-scheme: light; }
[data-ry-theme="dark"] { color-scheme: dark; }
} /* @layer ry-tokens */