mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 10:31:09 -05:00
- Implemented park card component with image, status badge, favorite button, and quick stats overlay. - Developed ride card component featuring thrill level badge, status badge, favorite button, and detailed stats. - Created advanced search page with filters for parks and rides, including location, type, status, and thrill level. - Added dynamic quick search functionality with results display. - Enhanced user experience with JavaScript for filter toggling, range slider updates, and view switching. - Included custom CSS for improved styling of checkboxes and search results layout.
459 lines
12 KiB
Markdown
459 lines
12 KiB
Markdown
# ThrillWiki Design System
|
|
Last Updated: 2025-01-15
|
|
|
|
## Overview
|
|
A comprehensive design system for ThrillWiki that combines modern aesthetics with exceptional user experience. Built on Tailwind CSS, HTMX, and AlpineJS to create a cohesive, accessible, and performant interface.
|
|
|
|
## Design Philosophy
|
|
|
|
### Core Principles
|
|
1. **Thrill-Focused**: Every design element should evoke excitement and adventure
|
|
2. **Data-Rich**: Present complex theme park information in digestible, beautiful ways
|
|
3. **Progressive Enhancement**: Works beautifully without JavaScript, enhanced with it
|
|
4. **Accessibility First**: WCAG 2.1 AA compliance throughout
|
|
5. **Performance Obsessed**: Sub-2s load times, smooth 60fps animations
|
|
|
|
### Visual Identity
|
|
- **Theme**: Modern theme park adventure with premium feel
|
|
- **Mood**: Exciting, trustworthy, sophisticated, fun
|
|
- **Target**: Theme park enthusiasts, families, travel planners
|
|
|
|
## Color System
|
|
|
|
### Primary Palette
|
|
```css
|
|
/* Thrill Colors - Excitement & Adventure */
|
|
--thrill-primary: #6366f1; /* Indigo 500 - Primary brand */
|
|
--thrill-primary-dark: #4f46e5; /* Indigo 600 - Hover states */
|
|
--thrill-primary-light: #818cf8; /* Indigo 400 - Light accents */
|
|
|
|
/* Adventure Colors - Energy & Fun */
|
|
--thrill-secondary: #f59e0b; /* Amber 500 - Secondary actions */
|
|
--thrill-secondary-dark: #d97706; /* Amber 600 - Hover states */
|
|
--thrill-secondary-light: #fbbf24; /* Amber 400 - Light accents */
|
|
|
|
/* Status Colors - Clear Communication */
|
|
--thrill-success: #10b981; /* Emerald 500 - Operating parks */
|
|
--thrill-warning: #f59e0b; /* Amber 500 - Construction */
|
|
--thrill-danger: #ef4444; /* Red 500 - Closed permanently */
|
|
--thrill-info: #3b82f6; /* Blue 500 - Information */
|
|
```
|
|
|
|
### Neutral Palette
|
|
```css
|
|
/* Light Mode */
|
|
--neutral-50: #f8fafc;
|
|
--neutral-100: #f1f5f9;
|
|
--neutral-200: #e2e8f0;
|
|
--neutral-300: #cbd5e1;
|
|
--neutral-400: #94a3b8;
|
|
--neutral-500: #64748b;
|
|
--neutral-600: #475569;
|
|
--neutral-700: #334155;
|
|
--neutral-800: #1e293b;
|
|
--neutral-900: #0f172a;
|
|
|
|
/* Dark Mode */
|
|
--dark-50: #0f172a;
|
|
--dark-100: #1e293b;
|
|
--dark-200: #334155;
|
|
--dark-300: #475569;
|
|
--dark-400: #64748b;
|
|
--dark-500: #94a3b8;
|
|
--dark-600: #cbd5e1;
|
|
--dark-700: #e2e8f0;
|
|
--dark-800: #f1f5f9;
|
|
--dark-900: #f8fafc;
|
|
```
|
|
|
|
### Gradient System
|
|
```css
|
|
/* Hero Gradients */
|
|
--gradient-hero: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #ec4899 100%);
|
|
--gradient-hero-dark: linear-gradient(135deg, #4338ca 0%, #7c3aed 50%, #db2777 100%);
|
|
|
|
/* Background Gradients */
|
|
--gradient-bg-light: linear-gradient(135deg, #f8fafc 0%, #e0e7ff 50%, #ede9fe 100%);
|
|
--gradient-bg-dark: linear-gradient(135deg, #0f172a 0%, #1e1b4b 50%, #581c87 100%);
|
|
|
|
/* Card Gradients */
|
|
--gradient-card: linear-gradient(145deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 100%);
|
|
--gradient-card-hover: linear-gradient(145deg, rgba(255,255,255,0.15) 0%, rgba(255,255,255,0.08) 100%);
|
|
```
|
|
|
|
## Typography
|
|
|
|
### Font Stack
|
|
```css
|
|
/* Primary Font - Poppins */
|
|
--font-primary: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
|
|
/* Weights */
|
|
--font-light: 300;
|
|
--font-regular: 400;
|
|
--font-medium: 500;
|
|
--font-semibold: 600;
|
|
--font-bold: 700;
|
|
--font-extrabold: 800;
|
|
```
|
|
|
|
### Type Scale
|
|
```css
|
|
/* Display - Hero sections */
|
|
--text-display-xl: 4.5rem; /* 72px */
|
|
--text-display-lg: 3.75rem; /* 60px */
|
|
--text-display-md: 3rem; /* 48px */
|
|
--text-display-sm: 2.25rem; /* 36px */
|
|
|
|
/* Headings */
|
|
--text-h1: 2rem; /* 32px */
|
|
--text-h2: 1.75rem; /* 28px */
|
|
--text-h3: 1.5rem; /* 24px */
|
|
--text-h4: 1.25rem; /* 20px */
|
|
--text-h5: 1.125rem; /* 18px */
|
|
--text-h6: 1rem; /* 16px */
|
|
|
|
/* Body */
|
|
--text-lg: 1.125rem; /* 18px */
|
|
--text-base: 1rem; /* 16px */
|
|
--text-sm: 0.875rem; /* 14px */
|
|
--text-xs: 0.75rem; /* 12px */
|
|
```
|
|
|
|
## Spacing System
|
|
|
|
### Base Scale (4px grid)
|
|
```css
|
|
--space-0: 0;
|
|
--space-1: 0.25rem; /* 4px */
|
|
--space-2: 0.5rem; /* 8px */
|
|
--space-3: 0.75rem; /* 12px */
|
|
--space-4: 1rem; /* 16px */
|
|
--space-5: 1.25rem; /* 20px */
|
|
--space-6: 1.5rem; /* 24px */
|
|
--space-8: 2rem; /* 32px */
|
|
--space-10: 2.5rem; /* 40px */
|
|
--space-12: 3rem; /* 48px */
|
|
--space-16: 4rem; /* 64px */
|
|
--space-20: 5rem; /* 80px */
|
|
--space-24: 6rem; /* 96px */
|
|
--space-32: 8rem; /* 128px */
|
|
```
|
|
|
|
## Component Library
|
|
|
|
### Buttons
|
|
|
|
#### Primary Button
|
|
```css
|
|
.btn-primary {
|
|
@apply px-6 py-3 bg-gradient-to-r from-thrill-primary to-thrill-primary-dark;
|
|
@apply text-white font-semibold rounded-xl shadow-lg;
|
|
@apply hover:shadow-xl hover:scale-105 active:scale-95;
|
|
@apply transition-all duration-200 ease-out;
|
|
@apply focus:outline-none focus:ring-4 focus:ring-thrill-primary/30;
|
|
}
|
|
```
|
|
|
|
#### Secondary Button
|
|
```css
|
|
.btn-secondary {
|
|
@apply px-6 py-3 bg-white dark:bg-neutral-800;
|
|
@apply text-thrill-primary dark:text-thrill-primary-light;
|
|
@apply font-semibold rounded-xl shadow-md border border-thrill-primary/20;
|
|
@apply hover:bg-thrill-primary/5 hover:shadow-lg hover:scale-105;
|
|
@apply active:scale-95 transition-all duration-200 ease-out;
|
|
@apply focus:outline-none focus:ring-4 focus:ring-thrill-primary/30;
|
|
}
|
|
```
|
|
|
|
#### Ghost Button
|
|
```css
|
|
.btn-ghost {
|
|
@apply px-4 py-2 text-neutral-600 dark:text-neutral-400;
|
|
@apply font-medium rounded-lg hover:bg-neutral-100 dark:hover:bg-neutral-800;
|
|
@apply hover:text-neutral-900 dark:hover:text-neutral-100;
|
|
@apply transition-all duration-150 ease-out;
|
|
@apply focus:outline-none focus:ring-2 focus:ring-neutral-300 dark:focus:ring-neutral-600;
|
|
}
|
|
```
|
|
|
|
### Cards
|
|
|
|
#### Base Card
|
|
```css
|
|
.card {
|
|
@apply bg-white/80 dark:bg-neutral-800/80 backdrop-blur-lg;
|
|
@apply border border-neutral-200/50 dark:border-neutral-700/50;
|
|
@apply rounded-2xl shadow-lg hover:shadow-xl;
|
|
@apply transition-all duration-300 ease-out;
|
|
@apply hover:scale-[1.02] hover:-translate-y-1;
|
|
}
|
|
```
|
|
|
|
#### Feature Card
|
|
```css
|
|
.card-feature {
|
|
@apply card p-8 relative overflow-hidden;
|
|
@apply before:absolute before:inset-0 before:bg-gradient-card;
|
|
@apply hover:before:bg-gradient-card-hover;
|
|
@apply before:transition-all before:duration-300;
|
|
}
|
|
```
|
|
|
|
#### Park Card
|
|
```css
|
|
.card-park {
|
|
@apply card group cursor-pointer;
|
|
@apply hover:ring-2 hover:ring-thrill-primary/30;
|
|
}
|
|
|
|
.card-park-image {
|
|
@apply aspect-video w-full object-cover rounded-t-2xl;
|
|
@apply group-hover:scale-105 transition-transform duration-500 ease-out;
|
|
}
|
|
|
|
.card-park-content {
|
|
@apply p-6 space-y-4;
|
|
}
|
|
```
|
|
|
|
### Forms
|
|
|
|
#### Input Fields
|
|
```css
|
|
.form-input {
|
|
@apply w-full px-4 py-3 bg-white dark:bg-neutral-800;
|
|
@apply border border-neutral-300 dark:border-neutral-600;
|
|
@apply rounded-xl shadow-sm focus:shadow-md;
|
|
@apply text-neutral-900 dark:text-neutral-100;
|
|
@apply placeholder-neutral-500 dark:placeholder-neutral-400;
|
|
@apply focus:outline-none focus:ring-2 focus:ring-thrill-primary/50;
|
|
@apply focus:border-thrill-primary dark:focus:border-thrill-primary-light;
|
|
@apply transition-all duration-200 ease-out;
|
|
}
|
|
```
|
|
|
|
#### Labels
|
|
```css
|
|
.form-label {
|
|
@apply block text-sm font-semibold text-neutral-700 dark:text-neutral-300;
|
|
@apply mb-2;
|
|
}
|
|
```
|
|
|
|
#### Error States
|
|
```css
|
|
.form-error {
|
|
@apply text-sm text-thrill-danger mt-1;
|
|
}
|
|
|
|
.form-input-error {
|
|
@apply border-thrill-danger focus:ring-thrill-danger/50;
|
|
@apply focus:border-thrill-danger;
|
|
}
|
|
```
|
|
|
|
### Status Badges
|
|
|
|
#### Operating
|
|
```css
|
|
.badge-operating {
|
|
@apply inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold;
|
|
@apply bg-thrill-success/10 text-thrill-success;
|
|
@apply border border-thrill-success/20;
|
|
}
|
|
```
|
|
|
|
#### Construction
|
|
```css
|
|
.badge-construction {
|
|
@apply inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold;
|
|
@apply bg-thrill-warning/10 text-thrill-warning;
|
|
@apply border border-thrill-warning/20;
|
|
}
|
|
```
|
|
|
|
#### Closed
|
|
```css
|
|
.badge-closed {
|
|
@apply inline-flex items-center px-3 py-1 rounded-full text-xs font-semibold;
|
|
@apply bg-thrill-danger/10 text-thrill-danger;
|
|
@apply border border-thrill-danger/20;
|
|
}
|
|
```
|
|
|
|
## Animation System
|
|
|
|
### Micro-Interactions
|
|
```css
|
|
/* Hover Lift */
|
|
.hover-lift {
|
|
@apply transition-all duration-300 ease-out;
|
|
@apply hover:scale-105 hover:-translate-y-1 hover:shadow-xl;
|
|
}
|
|
|
|
/* Pulse Animation */
|
|
.pulse-glow {
|
|
@apply animate-pulse;
|
|
animation: pulse-glow 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
}
|
|
|
|
@keyframes pulse-glow {
|
|
0%, 100% { box-shadow: 0 0 0 0 rgba(99, 102, 241, 0.4); }
|
|
50% { box-shadow: 0 0 0 10px rgba(99, 102, 241, 0); }
|
|
}
|
|
|
|
/* Slide In Animations */
|
|
.slide-in-up {
|
|
animation: slideInUp 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
|
}
|
|
|
|
@keyframes slideInUp {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(30px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
```
|
|
|
|
### HTMX Transitions
|
|
```css
|
|
/* View Transitions for HTMX */
|
|
.htmx-transition {
|
|
view-transition-name: main-content;
|
|
}
|
|
|
|
::view-transition-old(main-content) {
|
|
animation: 300ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
|
|
600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
|
|
}
|
|
|
|
::view-transition-new(main-content) {
|
|
animation: 400ms cubic-bezier(0, 0, 0.2, 1) 100ms both fade-in,
|
|
600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
|
|
}
|
|
|
|
@keyframes fade-in { from { opacity: 0; } }
|
|
@keyframes fade-out { to { opacity: 0; } }
|
|
@keyframes slide-from-right { from { transform: translateX(30px); } }
|
|
@keyframes slide-to-left { to { transform: translateX(-30px); } }
|
|
```
|
|
|
|
## Layout System
|
|
|
|
### Container Sizes
|
|
```css
|
|
.container-xs { max-width: 480px; }
|
|
.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; }
|
|
```
|
|
|
|
### Grid System
|
|
```css
|
|
/* Auto-fit grids for responsive cards */
|
|
.grid-auto-fit-xs { grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }
|
|
.grid-auto-fit-sm { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
|
|
.grid-auto-fit-md { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
|
|
.grid-auto-fit-lg { grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); }
|
|
```
|
|
|
|
## Responsive Design
|
|
|
|
### Breakpoints
|
|
```css
|
|
/* Mobile First Approach */
|
|
sm: 640px /* Small devices */
|
|
md: 768px /* Medium devices */
|
|
lg: 1024px /* Large devices */
|
|
xl: 1280px /* Extra large devices */
|
|
2xl: 1536px /* 2X Extra large devices */
|
|
```
|
|
|
|
### Container Queries
|
|
```css
|
|
/* Component-based responsive design */
|
|
@container (min-width: 320px) { /* Small container */ }
|
|
@container (min-width: 480px) { /* Medium container */ }
|
|
@container (min-width: 640px) { /* Large container */ }
|
|
```
|
|
|
|
## Accessibility
|
|
|
|
### Focus States
|
|
```css
|
|
.focus-visible {
|
|
@apply focus:outline-none focus-visible:ring-2 focus-visible:ring-thrill-primary;
|
|
@apply focus-visible:ring-offset-2 focus-visible:ring-offset-white;
|
|
@apply dark:focus-visible:ring-offset-neutral-900;
|
|
}
|
|
```
|
|
|
|
### Screen Reader Support
|
|
```css
|
|
.sr-only {
|
|
@apply absolute w-px h-px p-0 -m-px overflow-hidden;
|
|
@apply whitespace-nowrap border-0;
|
|
clip: rect(0, 0, 0, 0);
|
|
}
|
|
|
|
.sr-only-focusable:focus {
|
|
@apply static w-auto h-auto p-1 m-0 overflow-visible;
|
|
@apply whitespace-normal;
|
|
clip: auto;
|
|
}
|
|
```
|
|
|
|
## Performance Guidelines
|
|
|
|
### Critical CSS
|
|
- Inline critical styles for above-the-fold content
|
|
- Defer non-critical CSS loading
|
|
- Use CSS containment for performance isolation
|
|
|
|
### Animation Performance
|
|
- Prefer `transform` and `opacity` for animations
|
|
- Use `will-change` sparingly and remove after animation
|
|
- Implement `prefers-reduced-motion` support
|
|
|
|
### Loading States
|
|
```css
|
|
.loading-skeleton {
|
|
@apply bg-gradient-to-r from-neutral-200 via-neutral-100 to-neutral-200;
|
|
@apply dark:from-neutral-700 dark:via-neutral-600 dark:to-neutral-700;
|
|
@apply animate-pulse;
|
|
background-size: 200% 100%;
|
|
animation: shimmer 1.5s infinite;
|
|
}
|
|
|
|
@keyframes shimmer {
|
|
0% { background-position: -200% 0; }
|
|
100% { background-position: 200% 0; }
|
|
}
|
|
```
|
|
|
|
## Implementation Notes
|
|
|
|
### CSS Custom Properties
|
|
- Use CSS custom properties for theme values
|
|
- Implement proper fallbacks for older browsers
|
|
- Leverage cascade for theme switching
|
|
|
|
### Component Architecture
|
|
- Build components with composition in mind
|
|
- Use CSS classes for styling, not inline styles
|
|
- Implement proper component variants
|
|
|
|
### Testing Strategy
|
|
- Test across all supported browsers
|
|
- Validate accessibility with screen readers
|
|
- Performance test on low-end devices
|
|
- Verify responsive behavior at all breakpoints
|