412 lines
17 KiB
Markdown
412 lines
17 KiB
Markdown
# 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)
|
||
```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 693–707).
|
||
|
||
**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) ✅
|
||
```html
|
||
<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
|
||
```svelte
|
||
<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
|
||
```html
|
||
<!-- 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
|
||
```html
|
||
<!-- ✅ 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/90` → `preset-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-surface` → `preset-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.html` → `idaa/+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 693–707; others | 1 |
|
||
| 3 | 🟡 Consistency | FontAwesome icons throughout events module | 61 event files | 1–2 |
|
||
| 4 | 🟡 Consistency | `variant-*` buttons used instead of `preset-*` | Events, Badges, Leads routes | 1–2 |
|
||
| 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/90` → `preset-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-surface` → `preset-outlined-surface` |
|
||
| `src/routes/events/[event_id]/settings/+page.svelte` | Replace `variant-filled-secondary/primary` → `preset-*` |
|
||
| `src/routes/events/[event_id]/sign_in_out.svelte` | Replace `variant-soft-warning` → `preset-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
|