jedmund-svelte/src/lib/components/admin/EmptyState.svelte
Justin Edmund 45e3556663 feat(admin): complete Task 7 Phase 1 - styling & theming foundation
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>
2025-10-08 21:28:28 -07:00

59 lines
939 B
Svelte

<script lang="ts">
import type { Snippet } from 'svelte'
interface Props {
title: string
message: string
icon?: Snippet
action?: Snippet
}
let { title, message, icon, action }: Props = $props()
</script>
<div class="empty-state">
{#if icon}
<div class="empty-icon">
{@render icon()}
</div>
{/if}
<h3>{title}</h3>
<p>{message}</p>
{#if action}
<div class="empty-action">
{@render action()}
</div>
{/if}
</div>
<style lang="scss">
@import '$styles/variables.scss';
.empty-state {
text-align: center;
padding: $unit-8x $unit-4x;
color: $empty-state-text;
.empty-icon {
font-size: calc($unit * 6); // 48px
margin-bottom: $unit-3x;
opacity: 0.5;
}
h3 {
font-size: calc($unit * 2.5); // 20px
font-weight: 600;
margin: 0 0 $unit-2x;
color: $empty-state-heading;
}
p {
margin: 0;
line-height: 1.5;
}
.empty-action {
margin-top: $unit-3x;
}
}
</style>