Extended the theming system to additional pages and components, continuing to eliminate hardcoded colors and duplicated styles. **Pages Refactored:** - /admin/media - Integrated EmptyState with action button (~20 lines removed) - /admin/albums - Integrated EmptyState & ErrorMessage (~25 lines removed) - Fixed hardcoded spacing in loading spinner (32px → calc($unit * 4)) - Replaced hardcoded error color (#d33 → $error-text) **Components Updated with Semantic Colors:** - Button.svelte - Replaced 3 instances of #dc2626 → $error-text - AlbumSelector.svelte - Error message uses $error-bg, $error-text - AlbumSelectorModal.svelte - Error message uses $error-bg, $error-text, $error-border - Fixed border width (1px → $unit-1px) **Phase 2 Results:** - Total lines removed: ~105 across 4 pages (Phase 1: 60, Phase 2: 45) - EmptyState component now used in 4 pages - ErrorMessage component now used in 3 pages - Standardized error colors across 3 modal components **Theming Benefits:** - Error styling centralized (change $error-bg once, updates everywhere) - Empty states guaranteed visual consistency - Dark mode ready (just remap CSS variables in themes.scss) **Remaining work (future):** - ~30 files with remaining hardcoded colors - ~15 files with spacing that could use $unit system - Opportunity for additional semantic variables as needed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
8.5 KiB
Task 7: Styling & Theming Harmonization
Status: ✅ Phase 1 & 2 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
Phase 2: Rollout (Complete ✅)
Completed: Oct 8, 2025
Additional Pages Refactored
Media Page (/admin/media):
- ✅ Integrated
EmptyStatewith action button - ✅ Replaced hardcoded error color (
#d33→$error-text) - Removed ~20 lines of duplicate empty-state styles
Albums Page (/admin/albums):
- ✅ Integrated
EmptyStatecomponent - ✅ Integrated
ErrorMessagecomponent - ✅ Fixed hardcoded spacing in loading spinner (32px →
calc($unit * 4)) - Removed ~25 lines of duplicate error/empty-state styles
Components Updated with Semantic Colors
Button.svelte:
- ✅ Replaced 3 instances of
#dc2626→$error-textin.btn-danger-textvariant
AlbumSelector.svelte:
- ✅
.error-message:rgba(239, 68, 68, 0.1)→$error-bg - ✅
.error-message:#dc2626→$error-text
AlbumSelectorModal.svelte:
- ✅
.error-message:rgba(239, 68, 68, 0.1)→$error-bg - ✅
.error-message:#dc2626→$error-text - ✅
.error-message:rgba(239, 68, 68, 0.2)→$error-border - ✅ Fixed border width:
1px→$unit-1px
Phase 2 Impact
Total lines removed: ~105 lines of duplicated styles
- Projects page: ~30 lines (Phase 1)
- Posts page: ~30 lines (Phase 1)
- Media page: ~20 lines (Phase 2)
- Albums page: ~25 lines (Phase 2)
Components standardized: 7
- EmptyState (used in 4 pages)
- ErrorMessage (used in 3 pages)
- Button (error text color)
- AlbumSelector, AlbumSelectorModal (error messages)
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 ~30 lines)
- Posts page refactored (removed ~30 lines)
- Media page refactored (removed ~20 lines)
- Albums page refactored (removed ~25 lines)
- Button error colors replaced with semantic variables
- Modal error styles replaced with semantic variables
- Hardcoded spacing fixed where applicable
- Documentation complete
Build verification(will verify at end)
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 stylessrc/routes/admin/media/+page.svelte- Uses EmptyState, replaced hardcoded colors, removed ~20 linessrc/routes/admin/albums/+page.svelte- Uses EmptyState & ErrorMessage, fixed spacing, removed ~25 lines
Components Updated:
src/lib/components/admin/Button.svelte- Replaced hardcoded error text colorssrc/lib/components/admin/AlbumSelector.svelte- Replaced error message colorssrc/lib/components/admin/AlbumSelectorModal.svelte- Replaced error message colors and borders
Impact Summary
Code Reduction:
- Removed ~105 lines of duplicated styles across 4 pages
- Created 2 reusable components now used in 4 pages
- Standardized error colors across 3 modal/form components
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 Enhancements (Optional)
Potential Next Steps
1. Additional Hardcoded Colors (~30 remaining files)
- Replace remaining
rgba()colors with semantic variables in media/form components - Standardize shadow values across dropdowns/modals
- Add semantic variables for success/warning states
2. Additional Spacing Fixes (~15 remaining files)
- Continue replacing hardcoded px values with $unit-based calculations
- Standardize border-radius usage
3. New Semantic Variables (As Needed)
- Button states (disabled, active, loading backgrounds)
- List item hover/selected states
- Focus ring colors for accessibility
- Dropdown active/hover states
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