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

11 KiB
Raw Blame History

Aether UI — Design System Style Guidelines

Version: 1.1 (2026-03-17) Author: One Sky IT / Scott Idem Scope: All Aether SvelteKit frontend components Related: AE__UI_Component_Patterns.md, ae-firefly.css, documentation/AE__Components.md


1. Design Philosophy

"Shiny serenity, like a firefly."

The Aether UI is calm, focused, and softly luminous. It must be immediately readable under conference-room lighting, at a glance, by presenters who are nervous and in a hurry. Staff in the Speaker Ready Room need scan-speed identity confirmation. Remote presenters uploading files from home need a clear, unambiguous interface that doesn't waste their time.

Core principles:

  • Identity first. The user's first question is always "Am I in the right place?" Answer it with the hero card — name, time, room — before anything else is shown.
  • Progressive disclosure. Admin fields (codes, IDs, passcodes) are hidden unless edit_mode is active.
  • Theme-aware always. Zero hardcoded colors. Every background, border, and text color must respond to light/dark mode and the active theme via CSS variables.
  • Transitions, not pops. Every interactive state change is smoothed with transition-colors duration-200.
  • Section 508 / WCAG 2.1 AA compliance is non-negotiable. Contrast ratios, focus indicators, ARIA labels, and screen-reader regions are required everywhere.

2. Technical Stack Mandates (2026 Standard)

To maintain codebase health and performance, all new development must adhere to the following stack:

🚀 Svelte 5 Runes

  • Mandatory: Use $state, $derived, and $effect.
  • Snippet pattern: Use {@render snippet()} for reusable UI blocks within components.
  • Avoid: Legacy export let (use $props()), onMount for reactive derived state (use $derived or $effect), and $$slots (use Snippets).

🎨 Tailwind 4 + Skeleton v4

  • Mandatory: Use preset-* classes for interactive elements (e.g., preset-tonal-primary).
  • Forbidden: Legacy Skeleton v3 variant-* classes.
  • Customization: Use Tailwind 4 @theme blocks for project-wide overrides.

🔣 Lucide Icons

  • Mandatory: Use @lucide/svelte components (e.g., <Calendar size="1em" />).
  • Migration: Replaced all FontAwesome fas fa-* icons in general modules.
  • 🚨 Exception: IDAA Module: The IDAA module must retain FontAwesome and Bootstrap classes. It integrates with Novi CMS which relies on these legacy standards. Do not migrate IDAA icons.

3. The AE_Firefly Theme

App default since 2026-03-06. Set in ae_stores.ts as theme_name = 'AE_Firefly'. File: src/ae-firefly.css | Activated by: data-theme="AE_Firefly"

Role Palette Name Hue Use Case
Primary Luminescent Teal ~184° Primary actions, date/time chips, focus rings, anchor links
Secondary Warm Amber-Gold ~90° Secondary actions, copy/email buttons, soft highlights
Tertiary Night-Sky Indigo ~277° Location/room chips, depth accents
Surface Moonlit Slate ~215233° All backgrounds — off-white (light) → midnight slate (dark)
Warning Amber semantic n/a Disabled/inactive records, "no results" states, code badges
Success Green semantic n/a Active/complete states, file count badges
Error Red semantic n/a Errors, disabled-presenter states

Contrast Guarantees

  • Body text (surface-950 on surface-50): > 15:1 in light mode ✓
  • Primary buttons: ≥ 3:1 for interactive component threshold ✓
  • Designed using OKLCH perceptual lightness — not HSL estimates

4. Color Token Rules

Always Use Theme Tokens

Backgrounds / surfaces:

bg-surface-50-900      ← card faces (light: near-white, dark: deep slate)
bg-surface-100-900     ← inner sections, code blocks, secondary panels
bg-surface-50-950      ← page-level containers
bg-surface-200-800     ← skeleton pulse placeholders, dividers

Borders:

border-surface-200-800  ← standard card/panel borders
border-primary-500      ← focus rings (via focus-visible:ring)
border-warning-500      ← warning/caution interactive zones
border-surface-500/20   ← subtle section dividers

Primary color accents (teal):

bg-primary-500/10       ← tinted chip background (time chips)
text-primary-700 dark:text-primary-300  ← chip text with auto dark mode
hover:text-primary-500  ← link hover color

Tertiary color accents (indigo):

bg-tertiary-500/10      ← tinted chip background (room/location chips)
text-tertiary-700 dark:text-tertiary-300

Skeleton presets:

preset-tonal-warning    ← "no results", disabled rows, code tag badges
preset-tonal-primary    ← primary action buttons
preset-tonal-surface    ← neutral/secondary actions, status badges
preset-tonal-success    ← success states, file count badges
preset-tonal-error      ← error/blocked states
preset-filled-*-500     ← solid-fill buttons (hover state for tonal)

Warning/error semantic backgrounds:

bg-warning-100 border border-warning-300  ← inline warning banners
bg-error-100 border border-error-300      ← inline error banners

Never Use These

Forbidden Reason Replace With
bg-gray-* Fixed color, breaks dark mode bg-surface-* tokens
bg-neutral-* Same — fixed hue bg-surface-* tokens
bg-white Light-mode only bg-surface-50-900
text-gray-* Breaks dark mode opacity-60 on inherited text
text-neutral-* Same opacity-*
border-gray-* Non-theme border border-surface-200-800
bg-yellow-*, text-yellow-* Bypasses warning semantic preset-tonal-warning
bg-red-*, text-red-* Bypasses error semantic bg-error-100 / preset-tonal-error
bg-white dark:bg-gray-800 Manual light/dark pair Let theme tokens handle it — remove entirely
text-gray-600 dark:text-gray-400 Manual light/dark pair opacity-60
rounded-container-token Skeleton v3 class rounded-xl
variant-* (v3) Skeleton v3 class preset-* (v4)
preset-filled-surface-300-700 v3 dual-shade notation bg-surface-200-800 or bg-surface-100-900
preset-filled-surface-400-600 v3 dual-shade notation bg-surface-100-900
overflow-x-scroll Forces scrollbar visible overflow-x-auto

5. Transitions & Animation

All interactive state changes must be smoothed — no hard pops.

Element Classes
Table row transition-colors duration-200 on <tr>
List item card transition-colors duration-200 on <li>
Link hover transition-colors duration-200 on <a>
Info chips transition-colors duration-200 on <span>
QR code toggle (size) transition-all duration-500 on <img>
Collapsible sections Use Skeleton Accordion or CSS transition-all — don't add custom unless needed
Buttons Handled automatically by Skeleton preset classes

6. Loading / Skeleton States

When liveQuery data is still resolving, show pulse placeholders instead of nothing:

<!-- Title placeholder -->
<div class="h-7 w-2/3 bg-surface-200-800 animate-pulse rounded"></div>

<!-- Chip/pill placeholder -->
<div class="h-5 w-1/2 bg-surface-200-800 animate-pulse rounded-full"></div>

<!-- Icon placeholder -->
<div class="h-5 w-5 bg-surface-200-800 animate-pulse rounded-full"></div>

Always wrap in {#if $lq__obj}{...}{:else}...skeleton...{/if}never show real content structure before data exists.


7. Dark Mode Rules

  • Never write dark: overrides for background or text colors. The Firefly theme handles both modes through CSS variables. Writing dark:bg-gray-800 or dark:text-gray-400 bypasses the theme and breaks if the user switches themes.
  • Exception allowed: dark:text-primary-300 and dark:text-tertiary-300 in info chips are intentional — they reference theme variables that gracefully degrade.
  • Exception allowed: dark:border-surface-700 in fine-grained border work when border-surface-200-800 isn't strong enough.

8. Accessibility (Section 508 / WCAG 2.1 AA)

Requirement Implementation
Decorative icons aria-hidden="true" on all icons
Icon-only buttons aria-label="..." or title="..." + visible context
Async content regions role="status" aria-live="polite" on loading/empty sections
Focus indicators focus-visible:ring-2 focus-visible:ring-primary-500 on custom interactive elements
Interactive dialogs aria-haspopup="dialog" on trigger buttons
Form inputs Visible <label> linked via for / id, or explicit aria-label
Color-only information Always pair color coding with icon or text — never color alone
Minimum touch target 44×44px effective hit area for all tap targets

9. Debug Code — Remove Before Committing

These patterns are breakpoint debuggers added during development. Never commit them:

<!-- Breakpoint border debugger — REMOVE before commit -->
sm:border-l-red-400 md:border-l-yellow-400 lg:border-l-gray-100
sm:dark:border-l-red-600 md:dark:border-l-yellow-600 lg:dark:border-l-gray-700

Also flag on code review:

  • console.log(...) that isn't behind a log_lvl guard
  • border-dashed border-y-transparent border-r-transparent left on production components
  • overflow-x-scroll (should be overflow-x-auto)

10. QR Code Pattern — Critical Bug Prevention

The async QR generation code uses a boolean true as a loading placeholder:

$events_sess.pres_mgmt.session_qr_url[$lq__obj.id] = true;   // ← loading
// ... async ...
$events_sess.pres_mgmt.session_qr_url[$lq__obj.id] = result; // ← URL string

Always gate display on typeof ... === 'string', not just truthy:

<!-- ✅ Correct -->
{#if typeof $events_sess.pres_mgmt.session_qr_url?.[$lq__obj.id] === 'string'}

<!-- ❌ Wrong — renders broken <img src="true"> during load -->
{#if $events_sess.pres_mgmt.session_qr_url[$lq__obj.id]}

11. Tailwind Utility Usage Notes

  • opacity-* for muted text: Use opacity-60 (secondary) or opacity-40 (tertiary/hint) instead of text-gray-*. This works in any theme and both modes.
  • / opacity modifier: bg-primary-500/10 is preferred over separate opacity-10 — it targets only the background.
  • text-sm leading-relaxed: Standard for body-level descriptive text in cards.
  • tracking-wide uppercase: Use for section label/eyebrow text with opacity-40.
  • whitespace-pre-wrap: Required for any <pre> or <p> displaying user-entered multi-line text (preserves breaks without horizontal overflow).