# ThrillWiki Design System A unified design system for the ThrillWiki application, providing consistent styling, components, and utilities across the entire frontend. ## Quick Start ### Directory Structure ``` backend/ ├── static/ │ ├── css/ │ │ └── design-tokens.css # Primary design tokens (colors, typography, spacing) │ └── js/ │ ├── alpine-components.js # Alpine.js components │ └── stores/index.js # Alpine.js stores └── templates/ ├── base/ │ └── base.html # Base template (extend this) └── components/ └── ui/ ├── button.html # Button component ├── card.html # Card component ├── dialog.html # Modal/dialog component ├── icon.html # SVG icon component └── input.html # Form input component ``` ### CSS Loading Order CSS files must be loaded in this specific order: ```html ``` ### JavaScript Loading Order ```html ``` ## Design Tokens Design tokens are CSS custom properties that define the visual language of the application. ### Color System #### Color Scales Each color has a scale from 50-950: ```css --color-primary-50 /* Lightest */ --color-primary-100 --color-primary-200 --color-primary-300 --color-primary-400 --color-primary-500 /* Base */ --color-primary-600 --color-primary-700 --color-primary-800 --color-primary-900 --color-primary-950 /* Darkest */ ``` Available color scales: - `primary` - Blue (brand color) - `secondary` - Slate (neutral) - `accent` - Red (highlights) - `success` - Green - `warning` - Amber - `error` - Red - `info` - Sky blue #### Semantic Colors These adapt automatically for dark mode: ```css --color-background /* Page background */ --color-foreground /* Primary text */ --color-muted /* Muted backgrounds */ --color-muted-foreground /* Secondary text */ --color-border /* Border color */ --color-card /* Card background */ --color-card-foreground /* Card text */ --color-primary /* Primary action color */ --color-primary-foreground /* Text on primary */ --color-destructive /* Destructive actions */ ``` ### Typography ```css /* Font Families */ --font-family-sans /* Inter - body text */ --font-family-serif /* Playfair Display - headings */ --font-family-mono /* JetBrains Mono - code */ /* Font Sizes */ --font-size-xs /* 12px */ --font-size-sm /* 14px */ --font-size-base /* 16px */ --font-size-lg /* 18px */ --font-size-xl /* 20px */ --font-size-2xl /* 24px */ --font-size-3xl /* 30px */ --font-size-4xl /* 36px */ ``` ### Spacing Scale ```css --spacing-1 /* 4px */ --spacing-2 /* 8px */ --spacing-3 /* 12px */ --spacing-4 /* 16px */ --spacing-6 /* 24px */ --spacing-8 /* 32px */ --spacing-12 /* 48px */ --spacing-16 /* 64px */ ``` ### Shadows ```css --shadow-sm /* Subtle shadow */ --shadow-base /* Default shadow */ --shadow-md /* Medium shadow */ --shadow-lg /* Large shadow */ --shadow-xl /* Extra large shadow */ --shadow-2xl /* Maximum shadow */ ``` ### Border Radius ```css --radius-sm /* 2px */ --radius-base /* 4px */ --radius-md /* 6px */ --radius-lg /* 8px */ --radius-xl /* 12px */ --radius-full /* 9999px (pill) */ ``` ### Breakpoints ```css --breakpoint-sm /* 640px - Mobile landscape */ --breakpoint-md /* 768px - Tablets */ --breakpoint-lg /* 1024px - Desktops */ --breakpoint-xl /* 1280px - Large screens */ --breakpoint-2xl /* 1536px - Extra large */ ``` ## Components ### Button Component ```django {% include "components/ui/button.html" with text="Button Text" variant="default" {# default|secondary|destructive|outline|ghost|link #} size="default" {# default|sm|lg|icon #} icon="search" {# Optional: icon name #} disabled=False type="button" {# button|submit|reset #} href="" {# If provided, renders as #} hx_get="/url" {# HTMX attributes #} hx_post="/url" hx_target="#element" hx_swap="innerHTML" x_on_click="handler" {# Alpine.js attributes #} %} ``` ### Card Component ```django {% include "components/ui/card.html" with title="Card Title" description="Optional description" body_content="

Card content here

" footer_content="" class="additional-classes" %} ``` ### Input Component ```django {% include "components/ui/input.html" with name="field_name" label="Field Label" type="text" {# text|email|password|number|textarea #} placeholder="Placeholder text" value="" required=False disabled=False error="Error message" hint="Helper text" %} ``` ### Dialog/Modal Component ```django {% include "components/ui/dialog.html" with id="modal-id" title="Dialog Title" description="Optional description" content="

Dialog content

" footer="" size="default" {# sm|default|lg|xl|full #} closable=True open=True %} ``` ### Icon Component ```django {% include "components/ui/icon.html" with name="search" {# Icon name from library #} size="md" {# xs|sm|md|lg|xl #} class="text-primary" {# Additional classes #} %} ``` Available icons: search, menu, close, chevron-up, chevron-down, chevron-left, chevron-right, arrow-up, arrow-down, arrow-left, arrow-right, user, users, settings, cog, heart, heart-filled, star, star-filled, home, edit, trash, copy, external-link, download, upload, check, check-circle, x-circle, info, warning, error, plus, minus, filter, sort, calendar, clock, map-pin, phone, mail, globe, link, image, camera, play, pause, volume, bell, bookmark, share, refresh, eye, eye-off, lock, unlock, sun, moon, loader ## Utility Classes ### Responsive Utilities ```css /* Visibility */ .hidden-mobile /* Hidden on mobile */ .hidden-sm /* Hidden on sm breakpoint */ .show-mobile /* Only visible on mobile */ .show-lg /* Only visible on lg breakpoint */ /* Grid */ .grid-responsive-2 /* 1 col mobile, 2 cols sm+ */ .grid-responsive-3 /* 1 col mobile, 2 cols sm+, 3 cols lg+ */ .grid-responsive-4 /* 1 col mobile, 2 cols sm+, 4 cols lg+ */ .grid-auto-fit /* Auto-fit grid with 300px min */ /* Flex */ .stack-to-row /* Column on mobile, row on sm+ */ .stack-to-row-lg /* Column on mobile/tablet, row on lg+ */ /* Spacing */ .py-responsive /* 16px mobile, 24px sm, 32px lg */ .px-responsive /* Same for horizontal */ .gap-responsive /* Responsive gap */ ``` ### Container Classes ```css .container /* max-width: 1280px */ .container-sm /* max-width: 640px */ .container-md /* max-width: 768px */ .container-lg /* max-width: 1024px */ .container-xl /* max-width: 1280px */ .container-2xl /* max-width: 1536px */ ``` ### Accessibility Utilities ```css .sr-only /* Visually hidden, screen reader accessible */ .sr-only-focusable /* sr-only that becomes visible on focus */ .focus-ring /* Focus ring on :focus-visible */ .touch-target /* Minimum 44x44px touch target */ .skip-link /* Skip to content link */ ``` ## Alpine.js Stores ### Theme Store ```javascript // Access Alpine.store('theme') // Properties $store.theme.isDark // Current theme state $store.theme.systemTheme // System preference // Methods $store.theme.toggle() // Toggle theme $store.theme.set('dark') // Set specific theme ``` ### Toast Store ```javascript // Show notifications Alpine.store('toast').show('Message', 'success') Alpine.store('toast').success('Success message') Alpine.store('toast').error('Error message') Alpine.store('toast').warning('Warning message') Alpine.store('toast').info('Info message') ``` ### Auth Store ```javascript // Access current user $store.auth.user // User object or null $store.auth.isLoggedIn // Boolean $store.auth.hasPermission('permission_name') ``` ### UI Store ```javascript // Modal management Alpine.store('ui').openModal('modal-id') Alpine.store('ui').closeModal('modal-id') Alpine.store('ui').isModalOpen('modal-id') // Sidebar Alpine.store('ui').toggleSidebar() $store.ui.isSidebarOpen ``` ## Dark Mode Dark mode is automatically supported through CSS custom properties. Toggle with: ```html ``` Or use the theme toggle component in the navbar. ## Accessibility ### Focus Management All interactive elements have visible focus indicators using `:focus-visible`. Custom focus rings can be added with `.focus-ring`. ### Reduced Motion Animations are automatically disabled for users who prefer reduced motion: ```css @media (prefers-reduced-motion: reduce) { * { animation-duration: 0.01ms !important; } } ``` ### Screen Reader Support Use `.sr-only` for screen reader text: ```html ``` ### Touch Targets Ensure interactive elements meet minimum touch target size (44x44px): ```html ``` ## Testing Visit `/design-system-test/` (development only) to see all components rendered with their various states and options. ## Migration from Legacy System If migrating from the legacy system: 1. Replace HSL color variables with design token references 2. Replace Font Awesome icons with `{% include "components/ui/icon.html" %}` 3. Update button classes from `.btn-primary` to the button component 4. Replace inline Alpine.js stores with centralized stores from `stores/index.js` 5. Update responsive classes to use new utility classes See `MIGRATION.md` for detailed migration steps.