UNPKG

@ryanhelsing/ry-ui

Version:

Framework-agnostic, Light DOM web components. CSS is the source of truth.

183 lines (149 loc) 5.68 kB
# ry-ui Theming Guide ## Built-in Themes Set on `<html>`: ```html <html data-ry-theme="light"> <!-- light | dark | ocean --> ``` Toggle at runtime: ```html <ry-theme-toggle themes="light,dark"></ry-theme-toggle> ``` Or programmatically: ```js document.documentElement.setAttribute('data-ry-theme', 'dark'); ``` ## Dark Mode Dark mode is built into the base bundle via `light-dark()` + `color-scheme`. No extra files needed. ```html <!-- This is all you need — dark mode works automatically --> <link rel="stylesheet" href="https://unpkg.com/@ryanhelsing/ry-ui/css/ry-ui.css"> ``` Without a `data-ry-theme` attribute, the OS preference is respected automatically. Setting `data-ry-theme="dark"` forces dark mode. ## Token Override (Quickest Customization) Use the full bundle, override specific tokens: ```css :root { --ry-color-primary: oklch(0.541 0.218 293); --ry-color-primary-hover: oklch(0.491 0.234 292); --ry-radius-md: 0; --ry-radius-lg: 0; } ``` > **Note:** Tokens use `oklch()` color values. Hex still works for overrides but won't participate in `light-dark()` automatic switching. For dark-aware overrides, use `light-dark()`: > ```css > :root { > --ry-color-primary: light-dark(oklch(0.541 0.218 293), oklch(0.65 0.2 293)); > } > ``` ## Custom Theme (Full Control) Load structure only, bring your own visuals: ```html <link rel="stylesheet" href="https://unpkg.com/@ryanhelsing/ry-ui/css/ry-structure.css"> <link rel="stylesheet" href="/your-tokens.css"> <link rel="stylesheet" href="/your-theme.css"> ``` Structure CSS has layout only — no colors, shadows, borders. Your theme provides all visuals. ## Token Reference ### Colors All color tokens use `oklch()` and `light-dark()` for automatic dark mode: ```css --ry-color-primary: light-dark(oklch(0.623 0.188 259.8), oklch(0.714 0.143 254.6)); --ry-color-primary-hover: light-dark(oklch(0.546 0.215 262.9), oklch(0.623 0.188 259.8)); --ry-color-primary-active: light-dark(oklch(0.488 0.217 264.4), oklch(0.546 0.215 262.9)); --ry-color-secondary: light-dark(oklch(0.554 0.041 257.4), oklch(0.714 0.035 253.3)); --ry-color-success: light-dark(oklch(0.723 0.192 149.6), oklch(0.723 0.192 149.6)); --ry-color-warning: light-dark(oklch(0.769 0.165 70.1), oklch(0.769 0.165 70.1)); --ry-color-danger: light-dark(oklch(0.637 0.208 25.3), oklch(0.637 0.208 25.3)); --ry-color-info: light-dark(oklch(0.715 0.126 215.2), oklch(0.715 0.126 215.2)); --ry-color-text: light-dark(oklch(0.279 0.037 260), oklch(0.95 0.008 255)); --ry-color-text-muted: light-dark(oklch(0.554 0.041 257.4), oklch(0.714 0.035 253.3)); --ry-color-text-inverse: light-dark(oklch(1 0 0), oklch(0.279 0.037 260)); --ry-color-bg: light-dark(oklch(1 0 0), oklch(0.205 0.027 261)); --ry-color-bg-subtle: light-dark(oklch(0.984 0.003 248.2), oklch(0.249 0.03 261)); --ry-color-bg-muted: light-dark(oklch(0.968 0.007 248.1), oklch(0.279 0.033 261)); --ry-color-border: light-dark(oklch(0.929 0.013 255.6), oklch(0.372 0.039 257.3)); --ry-color-overlay: light-dark(oklch(0 0 0 / 0.5), oklch(0 0 0 / 0.7)); ``` ### Typography ```css --ry-font-sans: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; --ry-font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace; /* 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; /* Weights */ --ry-font-normal: 400; --ry-font-medium: 500; --ry-font-semibold: 600; --ry-font-bold: 700; ``` ### Spacing ```css --ry-space-0: 0; --ry-space-1: 0.25rem; --ry-space-2: 0.5rem; --ry-space-3: 0.75rem; --ry-space-4: 1rem; --ry-space-5: 1.25rem; --ry-space-6: 1.5rem; --ry-space-8: 2rem; --ry-space-10: 2.5rem; --ry-space-12: 3rem; --ry-space-16: 4rem; --ry-space-20: 5rem; ``` ### Border Radius ```css --ry-radius-none: 0; --ry-radius-sm: 0.25rem; --ry-radius-md: 0.375rem; --ry-radius-lg: 0.5rem; --ry-radius-xl: 0.75rem; --ry-radius-2xl: 1rem; --ry-radius-full: 9999px; ``` ### Shadows Shadows use sub-tokens for dark-mode-aware intensity: ```css --ry-shadow-color: light-dark(oklch(0 0 0 / 0.1), oklch(0 0 0 / 0.4)); --ry-shadow-sm: 0 1px 2px 0 var(--ry-shadow-color-sm); --ry-shadow-md: 0 4px 6px -1px var(--ry-shadow-color), 0 2px 4px -2px var(--ry-shadow-color); --ry-shadow-lg: 0 10px 15px -3px var(--ry-shadow-color), 0 4px 6px -4px var(--ry-shadow-color); --ry-shadow-xl: 0 20px 25px -5px var(--ry-shadow-color), 0 8px 10px -6px var(--ry-shadow-color); ``` ### Transitions ```css --ry-duration-fast: 100ms; --ry-duration-normal: 200ms; --ry-duration-slow: 300ms; --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); ``` ### Z-Index Layers ```css --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; ``` ### Focus ```css --ry-focus-ring: 0 0 0 3px light-dark(oklch(0.623 0.188 259.8 / 0.5), oklch(0.714 0.143 254.6 / 0.5)); ``` ## Best Practices - Always use `--ry-*` tokens instead of hardcoding values - Use `var(--ry-color-text)` and `var(--ry-color-bg)` on your own elements to stay theme-consistent - Semantic colors (`success`, `warning`, `danger`, `info`) are available as both `--ry-color-*` tokens and component `variant`/`type`/`color` attributes - For inline styles, reference tokens: `style="color: var(--ry-color-text-muted); padding: var(--ry-space-4);"` - Set `background: var(--ry-color-bg); color: var(--ry-color-text);` on `<body>` for full-page theme support