Knowledge
Search knowledge... ⌘K
Knowledge · Guidelines · sveltekit
Ui Async State Pattern
UI components that depend on async resources (images, deferred data from MD/SI) MUST implement explicit state machines rather than binary show/hide logic. Each component defines its own loading, ready, and error states. Each state controls the component's visible properties and animations. SSR hydration reserves space for the resource so layout does not shift when the resource arrives. Rule: The view is always in exactly one state. State transitions drive property changes, not imperative DOM manipulation.
Metadata
sveltekit sveltekit
Procedures
Showing 3 of 6
- ASP-001 All async resources in UI components MUST use an explicit state machine: loading | ready | error
Each state is a discrete value — never a combination of booleans. Transitions: loading → ready (resource loaded successfully) loading → error (resource failed — timeout, 404, network) error → loading (retry, if supported) Define state in Svelte 5 with $state(): type ImgState = 'loading' | 'ready' | 'error'; let imgState = $state<ImgState>('loading');code-review
- ASP-002 SSR renders the full component skeleton with reserved dimensions — no hydration shift
The server-rendered HTML MUST include placeholder elements with fixed dimensions so the browser layout is stable before the async resource arrives. For icon images: set width + height on <img> via CSS (or inline) in initial render. The space is reserved regardless of whether the img has loaded. BAD: <img src={url} /> — layout shift when image loads GOOD: <img src={url} width="20" height="20" class="icon icon--{imgState}" /> Skeleton placeholder technique (for heavier async slots): {#if resourceState === 'loading'} <span class="skeleton skeleton--icon" aria-hidden="true"></span> {:else if resourceState === 'ready'} <actual-content /> {/if}code-review
- ASP-003 Each state controls a distinct set of CSS properties — transitions animate state changes
Define CSS for each state class. Use CSS transitions (not JS) for smooth handoff. Example for icon img: .icon { transition: opacity 0.2s ease; } .icon--loading { opacity: 0; } .icon--ready { opacity: 1; } .icon--error { display: none; } /* or opacity: 0; width: 0; */ Animation is optional but MUST be defined in the guideline if used: loading → ready: fade-in (opacity 0 → 1, 150–200ms ease) loading → error: no animation (instant hide) Never animate layout-affecting properties (width, height, margin) — causes reflow. Animate only: opacity, transform, filter.code-review