Implemented a three-layer theming architecture to standardize admin component styling and prepare for future dark mode support. **Architecture:** - Layer 1: Base colors ($gray-80, $red-60) in variables.scss - Layer 2: Semantic SCSS variables ($input-bg, $error-bg) in variables.scss - Layer 3: CSS custom properties (--input-bg, --error-bg) in themes.scss **New semantic variables (~30 added):** - Inputs & forms (bg, hover, focus, text, border states) - State messages (error, success, warning with bg/text/border) - Empty states (text, heading colors) - Cards, dropdowns, popovers, modals (bg, border, shadow) **New reusable components:** - EmptyState.svelte - Supports icon and action snippets - ErrorMessage.svelte - Supports dismissible errors **Pages refactored:** - /admin/projects - Uses EmptyState and ErrorMessage (~30 lines removed) - /admin/posts - Uses EmptyState and ErrorMessage with icon (~30 lines removed) **Benefits:** - 60+ lines of duplicate styles removed (just 2 pages) - Future dark mode = remap CSS variables in themes.scss only - Guaranteed visual consistency for errors and empty states - $unit-based spacing system enforced **Remaining work (Phase 2):** - Replace hardcoded colors in ~40 files - Fix hardcoded spacing in ~20 files - Expand EmptyState/ErrorMessage to remaining pages 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
6.4 KiB
Task 7: Styling & Theming Harmonization
Status: ✅ Phase 1 COMPLETED
Implementation Summary
Implemented a three-layer theming architecture to prepare the admin interface for future dark mode support while eliminating style duplication.
Architecture
Three-layer system:
- Base colors (
variables.scss): Core color scales like$gray-80,$red-60 - Semantic SCSS variables (
variables.scss): Component mappings like$input-bg: $gray-90 - CSS custom properties (
themes.scss): Theme-ready variables like--input-bg: #{$input-bg}
Benefits:
- Components use SCSS variables (
background: $input-bg) - Future dark mode = remap CSS variables in
themes.scssonly - No component code changes needed for theming
What Was Built
1. Semantic SCSS Variables (src/assets/styles/variables.scss)
Added ~30 new semantic variables organized by component type:
// Inputs & Forms
$input-bg: $gray-90;
$input-bg-hover: $gray-85;
$input-bg-focus: $white;
$input-text: $gray-20;
$input-border: $gray-80;
$input-border-focus: $blue-40;
// State Messages
$error-bg: rgba($red-60, 0.1);
$error-text: $red-error;
$error-border: rgba($red-60, 0.2);
$success-bg: rgba($green-40, 0.1);
$success-text: $green-30;
$success-border: rgba($green-40, 0.2);
// Empty States
$empty-state-text: $gray-40;
$empty-state-heading: $gray-20;
// Cards, Dropdowns, Modals...
2. CSS Custom Properties (src/assets/styles/themes.scss)
Mapped all semantic variables to CSS custom properties:
:root {
--input-bg: #{$input-bg};
--error-bg: #{$error-bg};
--empty-state-text: #{$empty-state-text};
// ... ~30 mappings
}
[data-theme='dark'] {
// Future: remap for dark mode
}
3. Reusable Components
Created two new standardized components using semantic variables:
EmptyState.svelte - Replaces 10+ duplicated empty state implementations
<EmptyState
title="No items found"
message="Create your first item to get started!"
>
{#snippet icon()}🎨{/snippet}
{#snippet action()}<Button>...</Button>{/snippet}
</EmptyState>
ErrorMessage.svelte - Replaces 4+ duplicated error displays
<ErrorMessage
message="Something went wrong"
dismissible
onDismiss={handleDismiss}
/>
Both components:
- Use semantic SCSS variables (
$error-bg,$empty-state-text) - Follow $unit-based spacing system
- Support Svelte 5 snippets for flexibility
- Include proper accessibility attributes
4. Integrated in Production Pages
Updated projects and posts list pages:
- ✅
/admin/projects- Uses<EmptyState>and<ErrorMessage> - ✅
/admin/posts- Uses<EmptyState>and<ErrorMessage>with icon snippet - Removed ~60 lines of duplicated styles from these two pages alone
Success Criteria
- ~30 semantic SCSS variables added to variables.scss
- ~30 CSS custom properties mapped in themes.scss
- EmptyState component created with $unit-based spacing
- ErrorMessage component created with semantic variables
- Projects page refactored (removed duplicate styles)
- Posts page refactored (removed duplicate styles)
All hardcoded colors replaced(Future: Phase 2)All hardcoded spacing fixed(Future: Phase 2)- Documentation complete
- Build verified (in progress)
Files Created
New Components:
src/lib/components/admin/EmptyState.svelte(66 lines)src/lib/components/admin/ErrorMessage.svelte(51 lines)
Documentation:
docs/task-7-styling-harmonization-plan.mddocs/task-7-styling-harmonization-completion.md(this file)
Files Modified
Style Configuration:
src/assets/styles/variables.scss- Added semantic variable systemsrc/assets/styles/themes.scss- Added CSS custom property mappings
Pages Refactored:
src/routes/admin/projects/+page.svelte- Uses new components, removed ~30 lines of stylessrc/routes/admin/posts/+page.svelte- Uses new components, removed ~30 lines of styles
Impact Summary
Code Reduction:
- Removed ~60 lines of duplicated styles (just from 2 pages)
- Created 2 reusable components that will eliminate ~200+ more lines across remaining pages
Maintainability:
- Error styling: Change once in
$error-bg, updates everywhere - Empty states: Guaranteed visual consistency
- Theme-ready: Dark mode implementation = remap CSS variables only
Developer Experience:
- Autocomplete for semantic variable names
- Clear variable naming conventions
- Future: Easy to add new semantic mappings
Future Work (Phase 2)
Remaining Tasks
1. Replace Hardcoded Colors (~40 files)
- Replace
rgba(239, 68, 68, 0.1)with$error-bg - Replace
#dc2626with$error-text - Replace hardcoded shadow values with semantic variables
2. Fix Hardcoded Spacing (~20 files)
- Replace
padding: 24pxwithpadding: $unit-3x - Replace
margin: 12px 16pxwithmargin: calc($unit * 1.5) $unit-2x - Use $corner-radius-* variables instead of hardcoded values
3. Expand Component Usage
- Integrate
EmptyStatein media, albums pages (~8 more usages) - Integrate
ErrorMessageacross forms and modals (~4 more usages)
4. Additional Semantic Variables
- Button states (disabled, active, loading)
- List item hover/selected states
- Focus ring colors
Variable Naming Convention
Pattern: ${component}-${property}-${modifier}
Examples:
// Component type - property
$input-bg
$card-shadow
$dropdown-border
// Component - property - modifier
$input-bg-hover
$input-bg-focus
$card-shadow-hover
Two-layer mapping:
// Layer 1: Base colors (immutable scale)
$gray-90: #f0f0f0;
// Layer 2: Semantic SCSS variables (component usage)
$input-bg: $gray-90;
// Layer 3: CSS custom properties (theme-ready)
--input-bg: #{$input-bg};
Testing
Manual QA Complete:
- Projects page: Empty state renders correctly
- Projects page: Error message displays properly
- Posts page: Empty state with icon renders
- Posts page: Error message displays
- Build verification (in progress)
Related Documents
Notes
- Semantic variables placed after
$red-errordefinition to avoid undefined variable errors - SCSS @import deprecation warnings expected (will address in future Dart Sass 3.0 migration)
- Dark mode placeholder already in themes.scss for future implementation