mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-23 10:11:09 -05:00
8.1 KiB
8.1 KiB
Design System Migration Guide
This guide helps migrate from the legacy frontend system to the unified design system.
Overview
The ThrillWiki frontend was consolidated from two parallel systems:
- Legacy System (
/backend/templates/,/backend/static/css/) - HSL-based variables, Font Awesome icons - Modern System (
/templates/,/static/css/) - RGB hex-based design tokens, SVG icons
The unified system uses design-tokens.css as the single source of truth.
CSS Migration
Color Variables
Replace HSL-based variables with design tokens:
/* Before (legacy) */
background-color: hsl(var(--primary));
color: hsl(var(--primary-foreground));
/* After (design tokens) */
background-color: var(--color-primary);
color: var(--color-primary-foreground);
Common Replacements
| Legacy | Design Token |
|---|---|
hsl(var(--primary)) |
var(--color-primary) |
hsl(var(--secondary)) |
var(--color-secondary) |
hsl(var(--background)) |
var(--color-background) |
hsl(var(--foreground)) |
var(--color-foreground) |
hsl(var(--muted)) |
var(--color-muted) |
hsl(var(--accent)) |
var(--color-accent) |
hsl(var(--destructive)) |
var(--color-destructive) |
hsl(var(--border)) |
var(--color-border) |
hsl(var(--card)) |
var(--color-card) |
Font Variables
/* Before */
font-family: var(--font-sans);
/* After */
font-family: var(--font-family-sans);
Shadow Variables
/* Before */
box-shadow: var(--shadow);
/* After */
box-shadow: var(--shadow-base);
Icon Migration
Replace Font Awesome icons with the SVG icon component:
<!-- Before (Font Awesome) -->
<i class="fa fa-search"></i>
<i class="fas fa-user"></i>
<i class="far fa-heart"></i>
<!-- After (SVG Icon Component) -->
{% include "components/ui/icon.html" with name="search" %}
{% include "components/ui/icon.html" with name="user" %}
{% include "components/ui/icon.html" with name="heart" %}
Icon Name Mapping
| Font Awesome | SVG Icon |
|---|---|
fa-search |
search |
fa-user |
user |
fa-users |
users |
fa-cog |
settings |
fa-heart |
heart |
fa-star |
star |
fa-home |
home |
fa-edit |
edit |
fa-trash |
trash |
fa-copy |
copy |
fa-external-link |
external-link |
fa-chevron-down |
chevron-down |
fa-chevron-up |
chevron-up |
fa-chevron-left |
chevron-left |
fa-chevron-right |
chevron-right |
fa-check |
check |
fa-times |
close |
fa-plus |
plus |
fa-minus |
minus |
fa-bars |
menu |
Icon Sizes
<!-- Before -->
<i class="fa fa-search fa-sm"></i>
<i class="fa fa-search fa-lg"></i>
<i class="fa fa-search fa-2x"></i>
<!-- After -->
{% include "components/ui/icon.html" with name="search" size="sm" %}
{% include "components/ui/icon.html" with name="search" size="lg" %}
{% include "components/ui/icon.html" with name="search" size="xl" %}
Button Migration
Basic Buttons
<!-- Before -->
<button class="btn btn-primary">Click Me</button>
<button class="btn btn-secondary">Click Me</button>
<button class="btn btn-danger">Delete</button>
<button class="btn btn-outline">Outline</button>
<!-- After -->
{% include "components/ui/button.html" with text="Click Me" variant="default" %}
{% include "components/ui/button.html" with text="Click Me" variant="secondary" %}
{% include "components/ui/button.html" with text="Delete" variant="destructive" %}
{% include "components/ui/button.html" with text="Outline" variant="outline" %}
Buttons with Icons
<!-- Before -->
<button class="btn btn-primary">
<i class="fa fa-search mr-2"></i>
Search
</button>
<!-- After -->
{% include "components/ui/button.html" with text="Search" icon="search" %}
Link Buttons
<!-- Before -->
<a href="/url" class="btn btn-primary">Go</a>
<!-- After -->
{% include "components/ui/button.html" with text="Go" href="/url" %}
Form Input Migration
<!-- Before -->
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" class="form-control" placeholder="Enter email">
<small class="form-text text-muted">We'll never share your email.</small>
</div>
<!-- After -->
{% include "components/ui/input.html" with
name="email"
label="Email"
type="email"
placeholder="Enter email"
hint="We'll never share your email."
%}
Card Migration
<!-- Before -->
<div class="card">
<div class="card-header">
<h3 class="card-title">Title</h3>
</div>
<div class="card-body">
<p>Content here</p>
</div>
<div class="card-footer">
<button class="btn">Action</button>
</div>
</div>
<!-- After -->
{% include "components/ui/card.html" with
title="Title"
body_content="<p>Content here</p>"
footer_content="<button class='btn'>Action</button>"
%}
Modal Migration
<!-- Before -->
<div class="modal" id="myModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Title</h5>
<button class="close">×</button>
</div>
<div class="modal-body">Content</div>
<div class="modal-footer">
<button class="btn">Close</button>
</div>
</div>
</div>
</div>
<!-- After -->
{% include "components/ui/dialog.html" with
id="myModal"
title="Title"
content="Content"
footer="<button class='btn'>Close</button>"
%}
Alpine.js Migration
Store Definitions
Move inline store definitions to stores/index.js:
// Before (inline in template)
<script>
document.addEventListener('alpine:init', () => {
Alpine.store('theme', {
isDark: false,
toggle() { this.isDark = !this.isDark; }
});
});
</script>
// After (use centralized store)
// Store is already defined in stores/index.js
// Access via $store.theme.toggle()
Component Definitions
Move inline component definitions to alpine-components.js:
// Before (inline in template)
<div x-data="{ open: false }">
<button @click="open = !open">Toggle</button>
<div x-show="open">Content</div>
</div>
// After (use registered component)
<div x-data="dropdown()">
<button @click="toggle()">Toggle</button>
<div x-show="open">Content</div>
</div>
Alert/Toast Migration
<!-- Before -->
<div class="alert alert-success">
<strong>Success!</strong> Your action was completed.
</div>
<!-- After -->
<div class="alert alert-success" role="alert">
<div class="alert-title">Success!</div>
<div class="alert-description">Your action was completed.</div>
</div>
<!-- Or use toast store for dynamic notifications -->
<script>
Alpine.store('toast').success('Your action was completed.');
</script>
Responsive Classes Migration
<!-- Before -->
<div class="d-none d-md-block">Hidden on mobile</div>
<div class="d-md-none">Only on mobile</div>
<div class="row">
<div class="col-12 col-md-6">...</div>
</div>
<!-- After -->
<div class="hidden-mobile">Hidden on mobile</div>
<div class="show-mobile">Only on mobile</div>
<div class="grid-responsive-2">
<div>...</div>
<div>...</div>
</div>
Checklist
Use this checklist when migrating a template:
- Replace HSL color variables with design tokens
- Replace Font Awesome icons with SVG icon component
- Update button markup to use button component
- Update form inputs to use input component
- Update cards to use card component
- Update modals to use dialog component
- Remove inline Alpine.js store definitions
- Update responsive classes
- Test dark mode appearance
- Test focus states for accessibility
- Test on mobile viewport
Testing Migration
After migrating, visit /design-system-test/ to compare your migrated components against the reference implementation.
Getting Help
If you encounter issues during migration:
- Check the design system README for component documentation
- Review
design-tokens.cssfor available tokens - Inspect the design system test page for examples