Files
OSIT-AE-App-Svelte/documentation/PROJECT__AE_Style_Review.md

17 KiB
Raw Blame History

PROJECT: Aether App — Comprehensive Style Review

Status: Phase 1 & 2 Complete — Phase 3 Deferred (post-April 2026 conference) Priority: Medium Created: 2026-03-13 Updated: 2026-03-16 Related: src/app.css, src/routes/+layout.svelte, documentation/AE__UI_Component_Patterns.md


1. Objective

Audit and unify the visual design system across all Aether modules. The goal is consistent:

  • Color token usage (Skeleton preset-* / surface-* / semantic tokens)
  • Button and interactive element styling
  • Dark mode handling
  • Typography hierarchy
  • Layout patterns (cards, lists, tables, modals, banners)
  • Icon system (Lucide only)

This review covers all modules and their distinct use cases. Changes must be sequenced to avoid breaking live-production systems (Events Launcher, IDAA).

Scope of Modules

Module Routes Primary Users Notes
Core / App Shell +layout.svelte, e_app_sys_bar.svelte All users Foundation — impacts everything
Core Admin /core/ OSIT staff / managers Manager-only section
Journals /journals/ Authenticated users Canonical/frontier model
Events — General /events/, /events/[id]/ Event staff, attendees Hub page
Events — Pres Mgmt /events/[id]/(pres_mgmt)/ Event coordinators Operations tool
Events — Launcher /events/[id]/(launcher)/ AV/tech staff (Electron kiosk) ⚠️ Live production — April 2026 conference
Events — Badges /events/[id]/(badges)/ Registration desk staff On-site kiosk use
Events — Leads /events/[id]/(leads)/ Exhibitor booth staff On-site kiosk use
IDAA /idaa/ IDAA members (iframe) ⚠️ Privacy-critical, iframe context

2. Current State: Dual-Generation Problem

The codebase has two parallel style generations that co-exist:

Era Pattern Where Used
Modern preset-tonal-*, preset-filled-*, Lucide icons, Svelte 5 runes sys_bar, Journals, IDAA dashboard
Legacy variant-soft-*, variant-filled-*, FontAwesome fas fa-* icons Events routes (most), some Core

The Journals module is the canonical reference for modern patterns — when in doubt, match it.


3. Color Token Architecture

Three overlapping systems are in use. The goal is to consolidate to two:

System 1: Skeleton Semantic Tokens (keep, expand usage)

Used for colored/semantic elements.

primary, secondary, tertiary, success, warning, error, surface

Usage: preset-tonal-primary, bg-primary-500/10, text-error-500, border-warning-500

System 2: Plain Tailwind Grayscale (keep for neutrals)

Used for neutral backgrounds, borders, and text. Predictable across all Skeleton themes.

gray-50/100/200/300/400/500/600/700/800/900

Usage: bg-gray-50 dark:bg-gray-900, border-gray-200 dark:border-gray-700

System 3: Hardcoded RGB/HSL (eliminate)

bg-orange-600/90  — root layout banner
hsla(0, 100%, 50%, .5)  — journal entry eye icon
rgb(243 244 246)  — form dark mode hacks in <style> blocks

These are brittle, not theme-aware, and create maintenance debt.

Decision Rule

Semantic color needed? → Use Skeleton token (preset-*, text-primary-*, etc.) Neutral background/border/text? → Use gray-* with dark: pair Hardcoded color? → Replace with token. No exceptions.


4. Dark Mode Architecture

Current Setup (already correct in app.css)

@custom-variant dark (&:where(.dark, .dark *));  /* Tailwind v4 class-based dark mode */
html.dark  { color-scheme: dark; }               /* Native controls follow app theme */
html.light { color-scheme: light; }

Gap: Skeleton Form Classes Lack Dark Mode

Skeleton's .input, .select, .textarea classes do not include dark mode styles. This causes white text on white backgrounds in dark mode. Currently patched with inline <style> blocks per-component (see e_app_sys_bar.svelte lines 693707).

Fix: Global utility in app.css (see Phase 1, Step 1). Once added, remove per-component patches.


5. Button System

Standard: preset-* (Skeleton v4 pattern)

<button class="btn preset-tonal-secondary">Secondary</button>
<button class="btn btn-sm preset-filled-primary">Primary</button>
<button class="btn preset-outlined-surface">Outlined</button>

Note: All legacy variant-* classes have been fully removed from the codebase. Use only preset-* classes for all buttons and interactive elements.

Custom ae_btn_* Classes (app.css)

These exist in app.css and wrap the preset-* system. They are valid but underused. Consider adopting where button groups need reuse.


6. Icon System

Standard: Lucide (@lucide/svelte) — SVG, tree-shakeable, consistent stroke weight Legacy: FontAwesome (fas fa-* / far fa-*) — CSS class-based, heavier

FontAwesome is still imported (likely via global CSS). Goal: complete removal from all new work; migrate existing usage to Lucide progressively.

FontAwesome → Lucide Reference Map (events module)

FontAwesome Lucide Component Notes
fa-cogs Settings Settings/config
fa-chart-line TrendingUp Reports/charts
fa-map-marked-alt MapPinned Location with map
fa-map-marker-alt MapPin Location marker
fa-tools Wrench Tools/maintenance
fa-search Search Search
fa-chalkboard-teacher PresentationIcon or GraduationCap Presenter
fa-plane Plane Travel/remote
fa-sync-alt fa-spin RefreshCw + CSS animation Spinner
fa-arrow-up ArrowUp Up arrow
fa-arrow-down ArrowDown Down arrow
fa-list-ol ListOrdered Ordered list
fa-file-csv FileSpreadsheet CSV file
fa-toggle-on ToggleRight Toggle
fa-calendar-alt CalendarDays Calendar
fa-exclamation-triangle TriangleAlert Warning
fa-lock Lock Locked
fa-unlock Unlock Unlocked
fa-eye Eye Visible
fa-eye-slash EyeOff Hidden
fa-trash Trash2 Delete
fa-edit / fa-pencil Pencil Edit
fa-plus Plus Add
fa-times / fa-close X Close/remove
fa-check Check Confirm
fa-ban Ban Denied/blocked
fa-user User Person
fa-users Users Group
fa-tag Tag Tag/label
fa-print Printer Print
fa-download Download Download
fa-upload Upload Upload
fa-copy Copy Copy
fa-qrcode QrCode QR code
fa-id-card IdCard Badge/ID
fa-file-alt FileText File
fa-compress-arrows-alt Minimize2 Collapse
fa-expand Maximize2 Expand
fa-angle-right ChevronRight Nav arrow
fa-angle-down ChevronDown Accordion
fa-clock Clock Time

Lucide Usage Pattern

<script>
    import { Settings, Search, MapPin } from '@lucide/svelte';
</script>

<!-- Decorative icon with adjacent label -->
<Settings size="1em" class="shrink-0" aria-hidden="true" />

<!-- Icon-only button — MUST have aria-label -->
<button aria-label="Settings" class="btn btn-sm preset-tonal-surface">
    <Settings size="1.1em" />
</button>

7. Typography

Standard Hierarchy

<!-- Page title -->
<h1 class="text-3xl sm:text-4xl font-black tracking-tight">Title</h1>

<!-- Section heading -->
<h2 class="text-xl font-bold">Section</h2>

<!-- Card/item heading -->
<h3 class="text-lg font-semibold">Item</h3>

<!-- Label / eyebrow -->
<span class="text-xs font-bold uppercase tracking-wide opacity-40">Label</span>

<!-- Muted secondary text -->
<span class="text-sm opacity-60">Secondary info</span>

<!-- Hint / placeholder text -->
<span class="text-xs opacity-40 italic">Hint</span>

Rule: Opacity Over Fixed Colors for Muted Text

<!-- ✅ Theme-aware muted text -->
<span class="text-sm opacity-60">Note</span>

<!-- ❌ Fixed muted text — breaks in dark mode -->
<span class="text-sm text-gray-500">Note</span>

Exception: text-gray-* is acceptable in components that intentionally use plain Tailwind grayscale for neutrality (e.g., Journals list cards), as long as dark:text-gray-* counterpart is always included.


8. Card & Layout Patterns

See documentation/AE__UI_Component_Patterns.md for the full pattern reference.

Key standard patterns:

  • List item card: border border-gray-200 dark:border-gray-700 border-l-4 border-l-primary-500/40 with hover intensification
  • Content card: rounded-lg border border-surface-200-800 bg-surface-50-900 px-4 py-3
  • Glow accent: absolute -inset-1 bg-linear-to-r from-primary-500 to-secondary-500 rounded-2xl blur opacity-25 dark:opacity-40 group-hover:opacity-60 transition duration-1000 group-hover:duration-200 pointer-events-none
  • Empty state: preset-tonal-warning p-6 rounded-xl centered, with icon + heading + description

9. Accessibility Rules

  • Never remove focus rings. focus:ring-0 on text inputs fails WCAG 2.1 AA. Use focus:ring-2 focus:ring-primary-500 instead.
  • Icon-only buttons must have aria-label. No exceptions.
  • Decorative icons must have aria-hidden="true". This applies to ALL FontAwesome <span class="fas ..."> elements too.
  • Color is not the only status indicator. Pair color with text or icon shape.
  • Form labels must be explicit. Use <label for="..."> or aria-label.

10. Module-by-Module Status

Core / App Shell

Item Status Notes
Root layout banners (offline, expired) Done bg-orange-600/90preset-tonal-warning (2026-03-16)
e_app_sys_bar.svelte Modern Best-practice reference component
e_app_theme.svelte 🟡 Legacy Redundant with sys_bar theme section; keep but no new work
core/+layout.svelte Done variant-*preset-* (2026-03-16)
core/+page.svelte Good Excellent card grid template
All /core/ files (21 files) Done variant-*preset-*, FA → Lucide (2026-03-16)

Journals

Item Status Notes
Overall Canonical reference Use as template for all new work
ae_comp__journal_obj_li.svelte Excellent Card pattern, icon sizing, hover states
ae_comp__journal_entry_obj_li.svelte Done bg-slate-*bg-gray-*; hardcoded HSL → Tailwind tokens (2026-03-16)
ae_comp__journal_entry_header.svelte Done focus:ring-0 restored to focus:ring-2 (2026-03-16)

Events — General

Item Status Notes
events/+page.svelte Done FA → Lucide; variant-ghost-surfacepreset-outlined-surface (2026-03-16)
events/+layout.svelte Done FA → Lucide (spinners, arrows) (2026-03-16)
events/ae_comp__events_menu_nav.svelte Done FA → Lucide (2026-03-16)
events/[id]/+page.svelte Done FA → Lucide; variant-*preset-* (2026-03-16)
events/ae_comp__event_file_obj_tbl.svelte Done FA → Lucide (2026-03-16)
events/ae_comp__event_presentation_obj_li.svelte Done FA → Lucide (2026-03-16)
Lucide inline flow Done Global svg.lucide { display: inline } rule in app.css (2026-03-16)

Events — Pres Mgmt

Item Status Notes
All 24 pres_mgmt files Done FA → Lucide; variant-*preset-* (2026-03-16)
Card styling for session/presenter lists 🔒 Phase 3 Deferred to post-April 2026

Events — Launcher ⚠️ Live Production

Item Status Notes
FA → Lucide Done All FA spans were already in HTML comments — launcher is clean (verified 2026-03-16)
variant-* Done The variant-soft-secondary at line 329 is inside a comment block — no live variants remain
Card styling / UX polish 🔒 Phase 3 Deferred to post-April 2026 conference

Events — Badges

Item Status Notes
FA → Lucide Done All badge files migrated (2026-03-16)
badge_upload_form.svelte Done variant-*preset-* (2026-03-16)
badge_template_form.svelte Done variant-*preset-* (2026-03-16)
code_to_html Refactored FA HTML string dict → code_to_icon Lucide component map (2026-03-16)

Events — Leads

Item Status Notes
FA → Lucide Done All leads files migrated (2026-03-16)
ae_comp__exhibit_signin.svelte Done variant-*preset-* (2026-03-16)
ae_comp__lead_qr_scanner.svelte Done variant-*preset-* (2026-03-16)
ae_tab__add.svelte Done variant-*preset-* (2026-03-16)

IDAA ⚠️ Privacy-Critical

Item Status Notes
(idaa)/+page.svelte Modern Semantic tokens, good access gate
FA CDN Scoped Moved from app.htmlidaa/+layout.svelte <svelte:head> (2026-03-16)
Archives, BB, Recovery Meetings 🔒 Deferred Full style review deferred to Phase 3
All IDAA FA → Lucide 🔒 Last priority Review only after non-IDAA modules are complete

11. Issues Ranked by Priority

# Severity Issue Location Phase
1 🔴 A11y focus:ring-0 removes focus indicator on journal name input ae_comp__journal_entry_header.svelte:108 1
2 🔴 Maintenance No global dark mode form fix — per-component patches scattered e_app_sys_bar.svelte lines 693707; others 1
3 🟡 Consistency FontAwesome icons throughout events module 61 event files 12
4 🟡 Consistency variant-* buttons used instead of preset-* Events, Badges, Leads routes 12
5 🟡 Theme Hardcoded bg-orange-600/90 on root layout offline banner +layout.svelte 2
6 🟡 Theme Hardcoded HSL colors on journal entry eye icon ae_comp__journal_entry_obj_li.svelte 2
7 🟢 Consistency bg-slate-* used in journal entry instead of bg-gray-* ae_comp__journal_entry_obj_li.svelte 2
8 🟢 Polish Pres Mgmt pages lack card styling (bare <ul> lists) pres_mgmt/+page.svelte and sub-pages 3
9 🟢 Polish Root layout banner uses direct font-semibold text-white instead of preset +layout.svelte 2

12. Implementation Plan

Phase 1: Quick Wins (current)

Step 1 — Global form dark mode utility Target: src/app.css

Add a global utility so Skeleton .input, .select, .textarea classes render correctly in dark mode. This eliminates all per-component <style> patches.

Step 2 — FontAwesome → Lucide in events nav/layout files

Scope: Non-Launcher, non-IDAA files only. Priority order:

  1. src/routes/events/ae_comp__events_menu_nav.svelte — top-level navigation
  2. src/routes/events/+layout.svelte — spinner and sort icons

Step 3 — Standardize variant-*preset-* in events

Scope: +page.svelte, settings/+page.svelte, sign_in_out.svelte Skip: Launcher files (frozen), IDAA files (deferred)


Phase 2: Consolidation

  • Replace hardcoded banner color in root layout (bg-orange-600/90preset-tonal-warning)
  • Fix journal entry eye icon hardcoded HSL colors
  • Fix bg-slate-* inconsistency in journal entry
  • Migrate variant-* in remaining events files: Pres Mgmt, Badges, Leads
  • Remove per-component <style> dark mode patches (now covered by global utility)
  • Add responsive typography to events hub and pres mgmt pages

Phase 3: Module Refactors (post-April 2026 conference)

  • Events Launcher: FontAwesome → Lucide, variant-*preset-*
  • Events Pres Mgmt: Card styling for session/presenter lists
  • IDAA: Full style review (Archives, BB, Recovery Meetings)
  • Create .prose-journal utility in app.css to centralize markdown prose overrides

13. Files to Modify (Phase 1)

File Change
src/app.css Add global .dark form element utility
src/routes/events/ae_comp__events_menu_nav.svelte Replace fas fa-* with Lucide imports
src/routes/events/+layout.svelte Replace fas fa-sync-alt fa-spin and arrow icons with Lucide
src/routes/events/+page.svelte Replace variant-ghost-surfacepreset-outlined-surface
src/routes/events/[event_id]/settings/+page.svelte Replace variant-filled-secondary/primarypreset-*
src/routes/events/[event_id]/sign_in_out.svelte Replace variant-soft-warningpreset-tonal-warning

14. Testing Notes

  • Run npx svelte-check after every file change
  • Test dark mode toggle after form utility added — confirm inputs render correctly in dark
  • Test light mode — confirm no regressions
  • Events nav: verify all Lucide icons render at correct size and with correct meaning
  • Launcher: do not touch — verify no unintended changes via git diff
  • IDAA: do not touch — verify no unintended changes via git diff

15. What We Are NOT Changing (Phase 1)

  • Events Launcher files — frozen until post-April 2026 conference
  • All IDAA files — deferred to last phase
  • Root layout banner hardcoded color — Phase 2
  • Journal entry HSL eye icon colors — Phase 2
  • Pres Mgmt card styling — Phase 3