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

412 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 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) ✅
```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 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/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