Add standardized HTMX conventions, interaction patterns, and migration guide for ThrillWiki UX

This commit is contained in:
pacnpal
2025-12-22 16:56:27 -05:00
parent 2e35f8c5d9
commit ae31e889d7
144 changed files with 25792 additions and 4440 deletions

View File

@@ -0,0 +1,405 @@
# 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
<link href="{% static 'css/design-tokens.css' %}" rel="stylesheet">
<link href="{% static 'css/tailwind.css' %}" rel="stylesheet">
<link href="{% static 'css/components.css' %}" rel="stylesheet">
```
### JavaScript Loading Order
```html
<!-- Alpine.js stores (loaded before Alpine) -->
<script src="{% static 'js/stores/index.js' %}"></script>
<!-- Alpine.js plugins -->
<script defer src="https://unpkg.com/@alpinejs/intersect@3.x.x/dist/cdn.min.js"></script>
<script defer src="https://unpkg.com/@alpinejs/persist@3.x.x/dist/cdn.min.js"></script>
<!-- Alpine.js core -->
<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
<!-- Alpine.js components (after Alpine loads) -->
<script src="{% static 'js/alpine-components.js' %}"></script>
```
## 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 <a> #}
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="<p>Card content here</p>"
footer_content="<button>Action</button>"
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="<p>Dialog content</p>"
footer="<button>Action</button>"
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
<button @click="$store.theme.toggle()">
Toggle Theme
</button>
```
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
<button>
<svg>...</svg>
<span class="sr-only">Close menu</span>
</button>
```
### Touch Targets
Ensure interactive elements meet minimum touch target size (44x44px):
```html
<button class="touch-target">...</button>
```
## 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.