From 45e3556663f43bb04ebbd190ec772f99f814afb9 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Wed, 8 Oct 2025 21:28:28 -0700 Subject: [PATCH] feat(admin): complete Task 7 Phase 1 - styling & theming foundation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- docs/admin-modernization-plan.md | 84 +++-- ...task-7-styling-harmonization-completion.md | 226 ++++++++++++ docs/task-7-styling-harmonization-plan.md | 322 ++++++++++++++++++ src/assets/styles/themes.scss | 49 ++- src/assets/styles/variables.scss | 48 +++ src/lib/components/admin/EmptyState.svelte | 59 ++++ src/lib/components/admin/ErrorMessage.svelte | 54 +++ src/routes/admin/posts/+page.svelte | 59 +--- src/routes/admin/projects/+page.svelte | 49 +-- 9 files changed, 842 insertions(+), 108 deletions(-) create mode 100644 docs/task-7-styling-harmonization-completion.md create mode 100644 docs/task-7-styling-harmonization-plan.md create mode 100644 src/lib/components/admin/EmptyState.svelte create mode 100644 src/lib/components/admin/ErrorMessage.svelte diff --git a/docs/admin-modernization-plan.md b/docs/admin-modernization-plan.md index ac1f5ad..606d855 100644 --- a/docs/admin-modernization-plan.md +++ b/docs/admin-modernization-plan.md @@ -2,25 +2,26 @@ ## Progress Overview -**Current Status:** Phase 3 Complete βœ… (4 of 4 phases done) +**Current Status:** Phase 4 In Progress 🚧 (Task 7 Phase 1 Complete) - βœ… **Phase 0:** Runed integration (Task 0) - βœ… **Phase 1:** Auth & data foundation (Tasks 1, 2) - βœ… **Phase 2:** Form modernization (Tasks 3, 6) - βœ… **Phase 3:** List utilities & primitives (Tasks 4, 5) -- πŸ“‹ **Phase 4:** Styling harmonization (Task 7) - **NEXT** +- 🚧 **Phase 4:** Styling harmonization (Task 7) - **IN PROGRESS** **Recent Completions:** -- Task 3 - Project Form Modularization (Oct 7, 2025) - - Reduced ProjectForm from 720 β†’ 417 lines (42%) - - Created reusable composable stores and helpers -- Task 4 - Shared List Filtering Utilities (Oct 8, 2025) - - Removed ~100 lines of duplicated filter/sort code - - Integrated into projects and posts lists +- Task 7 Phase 1 - Styling & Theming Foundation (Oct 8, 2025) + - Created 3-layer theming architecture (SCSS β†’ CSS variables) + - Added ~30 semantic SCSS variables for components + - Built EmptyState and ErrorMessage reusable components + - Refactored projects and posts pages (~60 lines removed) - Task 5 - Dropdown & Click-Outside Primitives (Oct 8, 2025) - Documented existing implementation (~85% already done) - Cleaned up GenericMetadataPopover to use clickOutside action - - Justified remaining manual event listeners +- Task 4 - Shared List Filtering Utilities (Oct 8, 2025) + - Removed ~100 lines of duplicated filter/sort code + - Integrated into projects and posts lists --- @@ -269,22 +270,58 @@ Created `src/lib/admin/autoSave.svelte.ts` with: --- -## Task 7 – Styling & Theming Harmonization +## Task 7 – Styling & Theming Harmonization 🚧 -**Objective:** Reduce SCSS duplication and make layout adjustments easier. +**Status:** 🚧 **PHASE 1 COMPLETE** (Oct 8, 2025) -### Steps -1. Create `src/lib/styles/admin.css` exposing CSS variables for spacing, typography, and colors consumed by admin components. -2. Replace per-component `@import '$styles/variables.scss'` with `@use` in a single scoped stylesheet or with CSS variable access. -3. Introduce layout wrappers (e.g., `AdminLayoutShell.svelte`) that centralize container widths and card backgrounds, removing repeated SCSS from `AdminPage`, `AdminNavBar`, etc. -4. Audit component classes to ensure consistent BEM-ish naming and remove redundant selectors (e.g., duplicate `.loading` styles across pages). +**Objective:** Reduce SCSS duplication, standardize component styling, and prepare for future dark mode theming. + +### Phase 1: Foundation (Complete βœ…) + +**Completed:** +1. βœ… Created 3-layer theming architecture: + - Base colors (`$gray-80`, `$red-60`) in `variables.scss` + - Semantic SCSS variables (`$input-bg`, `$error-bg`) in `variables.scss` + - CSS custom properties (`--input-bg`, `--error-bg`) in `themes.scss` +2. βœ… Added ~30 semantic SCSS variables for: + - Inputs & forms (bg, hover, focus, text, border) + - State messages (error, success, warning) + - Empty states + - Cards & containers + - Dropdowns & popovers + - Modals +3. βœ… Created reusable components: + - `EmptyState.svelte` - Replaces 10+ duplicate implementations + - `ErrorMessage.svelte` - Replaces 4+ duplicate implementations +4. βœ… Refactored pages using new components: + - `/admin/projects` - Removed ~30 lines of duplicate styles + - `/admin/posts` - Removed ~30 lines of duplicate styles + +**Results:** +- 60+ lines of duplicated styles removed (2 pages) +- Theme-ready architecture for future dark mode +- Guaranteed visual consistency for errors and empty states + +### Phase 2: Rollout (Future) + +**Remaining work:** +1. ⏳ Replace hardcoded colors with semantic variables (~40 files) + - `rgba(239, 68, 68, 0.1)` β†’ `$error-bg` + - `#dc2626` β†’ `$error-text` +2. ⏳ Fix hardcoded spacing with $unit system (~20 files) + - `padding: 24px` β†’ `$unit-3x` + - `margin: 12px` β†’ `calc($unit * 1.5)` +3. ⏳ Expand EmptyState usage to media, albums pages (~8 more usages) +4. ⏳ Expand ErrorMessage usage across forms/modals (~4 more usages) ### Implementation Notes -- Consider PostCSS or Svelte’s ` +``` + +**B. `ErrorMessage.svelte`** (~4 usages) +```svelte + + +
+ {message} + {#if dismissible && onDismiss} + + {/if} +
+ + +``` + +### Step 6: Documentation + +Create `docs/task-7-styling-harmonization-completion.md` with: +- Architecture explanation (3-layer system) +- Semantic variable naming conventions +- How to add new semantic mappings +- Component usage patterns +- Future dark mode approach + +## Implementation Order + +1. **Add semantic SCSS variables** to `variables.scss` (~30 new variables) +2. **Map to CSS custom properties** in `themes.scss` (~30 new mappings) +3. **Fix spacing in high-impact files** (projects/posts pages, forms, modals) +4. **Replace hardcoded colors** with semantic SCSS variables +5. **Create EmptyState component** and replace ~10 usages +6. **Create ErrorMessage component** and replace ~4 usages +7. **Document approach** in task-7 completion doc +8. **Update admin modernization plan** to mark Task 7 complete + +## Success Criteria + +- [ ] ~30 semantic SCSS variables added to variables.scss +- [ ] ~30 CSS custom properties mapped in themes.scss +- [ ] All hardcoded spacing uses $unit system (20 files) +- [ ] All colors use semantic SCSS variables (40 files) +- [ ] EmptyState component created and integrated (10 usages) +- [ ] ErrorMessage component created and integrated (4 usages) +- [ ] No rgba() or hex in admin components (use SCSS variables) +- [ ] Documentation complete +- [ ] Build passes, manual QA complete + +## Benefits + +βœ… **Theme-ready**: Dark mode = remap CSS vars in themes.scss only +βœ… **Maintainability**: Change semantic variable once, updates everywhere +βœ… **Consistency**: All empty states/errors look identical +βœ… **DX**: Autocomplete for semantic variable names +βœ… **Reduced duplication**: ~200-300 lines of styles removed diff --git a/src/assets/styles/themes.scss b/src/assets/styles/themes.scss index 4400a8c..5fdf0eb 100644 --- a/src/assets/styles/themes.scss +++ b/src/assets/styles/themes.scss @@ -1,11 +1,58 @@ :root { + // Base page colors --bg-color: #{$gray-80}; --page-color: #{$gray-100}; --card-color: #{$gray-90}; --mention-bg-color: #{$gray-90}; - --text-color: #{$gray-20}; + + // Inputs & Forms + --input-bg: #{$input-bg}; + --input-bg-hover: #{$input-bg-hover}; + --input-bg-focus: #{$input-bg-focus}; + --input-text: #{$input-text}; + --input-text-hover: #{$input-text-hover}; + --input-border: #{$input-border}; + --input-border-focus: #{$input-border-focus}; + + // State Messages + --error-bg: #{$error-bg}; + --error-text: #{$error-text}; + --error-border: #{$error-border}; + + --success-bg: #{$success-bg}; + --success-text: #{$success-text}; + --success-border: #{$success-border}; + + --warning-bg: #{$warning-bg}; + --warning-text: #{$warning-text}; + --warning-border: #{$warning-border}; + + // Empty States + --empty-state-text: #{$empty-state-text}; + --empty-state-heading: #{$empty-state-heading}; + + // Cards & Containers + --card-bg: #{$card-bg}; + --card-border: #{$card-border}; + --card-shadow: #{$card-shadow}; + --card-shadow-hover: #{$card-shadow-hover}; + + // Dropdowns & Popovers + --dropdown-bg: #{$dropdown-bg}; + --dropdown-border: #{$dropdown-border}; + --dropdown-shadow: #{$dropdown-shadow}; + --dropdown-item-hover: #{$dropdown-item-hover}; + + // Modals + --modal-overlay: #{$modal-overlay}; + --modal-bg: #{$modal-bg}; + --modal-shadow: #{$modal-shadow}; } [data-theme='dark'] { + // Future: remap CSS custom properties for dark mode + // --input-bg: #{$dark-input-bg}; + // --card-bg: #{$dark-card-bg}; + // etc. } diff --git a/src/assets/styles/variables.scss b/src/assets/styles/variables.scss index f438a84..14a3a6a 100644 --- a/src/assets/styles/variables.scss +++ b/src/assets/styles/variables.scss @@ -318,3 +318,51 @@ $shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1); $shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1); $shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1); $shadow-xl: 0 20px 25px rgba(0, 0, 0, 0.15); + +/* Admin Component-Specific Semantic Colors + * Two-layer system: base colors ($gray-80) β†’ semantic mappings ($input-bg) + * These will be exposed as CSS custom properties in themes.scss for theming + * -------------------------------------------------------------------------- */ + +// Inputs & Forms (extended semantics) +$input-bg: $gray-90; +$input-bg-hover: $gray-85; +$input-bg-focus: $white; +$input-text: $gray-20; +$input-text-hover: $gray-10; +$input-border: $gray-80; +$input-border-focus: $blue-40; + +// State Messages (errors, success, warnings) +$error-bg: rgba($red-60, 0.1); +$error-text: $red-error; // Already defined as #dc2626 +$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); + +$warning-bg: rgba($yellow-50, 0.1); +$warning-text: $yellow-10; +$warning-border: rgba($yellow-50, 0.2); + +// Empty States +$empty-state-text: $gray-40; +$empty-state-heading: $gray-20; + +// Cards & Containers +$card-bg: $white; +$card-border: $gray-80; +$card-shadow: rgba($black, 0.08); +$card-shadow-hover: rgba($black, 0.12); + +// Dropdowns & Popovers +$dropdown-bg: $white; +$dropdown-border: $gray-80; +$dropdown-shadow: rgba($black, 0.12); +$dropdown-item-hover: $gray-95; + +// Modals +$modal-overlay: rgba($black, 0.5); +$modal-bg: $white; +$modal-shadow: rgba($black, 0.15); diff --git a/src/lib/components/admin/EmptyState.svelte b/src/lib/components/admin/EmptyState.svelte new file mode 100644 index 0000000..c163e4f --- /dev/null +++ b/src/lib/components/admin/EmptyState.svelte @@ -0,0 +1,59 @@ + + +
+ {#if icon} +
+ {@render icon()} +
+ {/if} +

{title}

+

{message}

+ {#if action} +
+ {@render action()} +
+ {/if} +
+ + diff --git a/src/lib/components/admin/ErrorMessage.svelte b/src/lib/components/admin/ErrorMessage.svelte new file mode 100644 index 0000000..c8d2146 --- /dev/null +++ b/src/lib/components/admin/ErrorMessage.svelte @@ -0,0 +1,54 @@ + + +
+ {message} + {#if dismissible && onDismiss} + + {/if} +
+ + diff --git a/src/routes/admin/posts/+page.svelte b/src/routes/admin/posts/+page.svelte index 7f53ee9..b2acd15 100644 --- a/src/routes/admin/posts/+page.svelte +++ b/src/routes/admin/posts/+page.svelte @@ -6,6 +6,8 @@ import PostListItem from '$lib/components/admin/PostListItem.svelte' import InlineComposerModal from '$lib/components/admin/InlineComposerModal.svelte' import DeleteConfirmationModal from '$lib/components/admin/DeleteConfirmationModal.svelte' + import EmptyState from '$lib/components/admin/EmptyState.svelte' + import ErrorMessage from '$lib/components/admin/ErrorMessage.svelte' import Button from '$lib/components/admin/Button.svelte' import Select from '$lib/components/admin/Select.svelte' import { createListFilters, commonSorts } from '$lib/admin/listFilters.svelte' @@ -165,22 +167,20 @@ const statusFilterOptions = [ {#if actionError} -
{actionError}
+ {/if} {#if filters.items.length === 0} -
-
πŸ“
-

No posts found

-

- {#if filters.values.type === 'all' && filters.values.status === 'all'} - Create your first post to get started! - {:else} - No posts found matching the current filters. Try adjusting your filters or create a new - post. - {/if} -

-
+ + {#snippet icon()} + πŸ“ + {/snippet} + {:else}
{#each filters.items as post (post.id)} @@ -217,44 +217,11 @@ const statusFilterOptions = [