Splash Screen
The screen an app shows before it has anything else to show — six looks, seven indicators, eight ways to leave, and no wiring for the common case.
Walkthrough
1. Basic
The whole of it: a splash over the app, and the app behind it once it goes. In a real layout you would leave open alone — the splash waits for the page to load and takes itself off. Here it is bound to a timer so you can watch it again.
Dashboard
The app behind the splash.
Acme
Getting your workspace ready.
Loading your workspace
<script lang="ts"> import { Button, SplashScreen, Text } from 'omaris'; let booting = $state(true); $effect(() => { if (!booting) return; const timer = setTimeout(() => (booting = false), 1800); return () => clearTimeout(timer); });</script><div class="relative h-full w-full overflow-hidden rounded-shape-lg border border-border"> <div class="flex h-full flex-col items-start gap-3 p-6"> <Text variant="headline-sm" as="h2">Dashboard</Text> <Text tone="muted">The app behind the splash.</Text> <Button size="xs" onclick={() => (booting = true)}>Boot again</Button> </div> <SplashScreen bind:open={booting} inline title="Acme" description="Getting your workspace ready." pattern="gradient" message="Loading your workspace" > {#snippet logo()} ... {/snippet} </SplashScreen></div> 2. Looks
Two decisions, taken separately: variant is the colour the screen is, pattern is the decorative layer over it. Six by seven, and every pairing is one word each.
grid
dots
aurora
spotlight
mesh
gradient
<script lang="ts"> import { SplashScreen, type SplashScreenPattern, type SplashScreenVariant } from 'omaris'; const looks: { variant: SplashScreenVariant; pattern: SplashScreenPattern }[] = [ { variant: 'background', pattern: 'grid' }, { variant: 'surface', pattern: 'dots' }, { variant: 'primary', pattern: 'aurora' }, { variant: 'inverse', pattern: 'spotlight' }, { variant: 'background', pattern: 'mesh' }, { variant: 'surface', pattern: 'gradient' } ];</script><div class="grid w-full gap-4 sm:grid-cols-2 lg:grid-cols-3"> {#each looks as look (look.variant + look.pattern)} <div class="relative h-48 overflow-hidden rounded-shape-lg border border-border"> <SplashScreen open inline size="sm" variant={look.variant} pattern={look.pattern} title={look.pattern} indicator="dots" /> </div> {/each}</div> 3. Indicators
Seven ways to say "working on it". bar is the only one that can also say how far along it is; the rest are honest about knowing nothing.
spinner
ring
dots
bar
wave
orbit
pulse
<script lang="ts"> import { SplashScreen, type SplashScreenIndicator } from 'omaris'; const indicators: SplashScreenIndicator[] = [ 'spinner', 'ring', 'dots', 'bar', 'wave', 'orbit', 'pulse' ];</script><div class="grid w-full gap-4 sm:grid-cols-2 lg:grid-cols-4"> {#each indicators as indicator (indicator)} <div class="relative h-40 overflow-hidden rounded-shape-lg border border-border"> <SplashScreen open inline size="sm" {indicator} message={indicator} /> </div> {/each}</div> 4. Exits
The part anyone remembers. Press one and watch it go: iris opens a hole in the middle and the app is behind it, rise takes the whole screen up like a curtain.
fade
scale
zoom
rise
fall
swipe
blur
iris
<script lang="ts"> import { Button, SplashScreen, Text, type SplashScreenExit } from 'omaris'; const exits: SplashScreenExit[] = [ 'fade', 'scale', 'zoom', 'rise', 'fall', 'swipe', 'blur', 'iris' ]; /** Which are currently up. Replaying one drops it and puts it back a frame later. */ let up = $state<Record<string, boolean>>(Object.fromEntries(exits.map((e) => [e, true]))); function replay(exit: string) { up[exit] = false; setTimeout(() => (up[exit] = true), 700); }</script><div class="grid w-full gap-4 sm:grid-cols-2 lg:grid-cols-4"> {#each exits as exit (exit)} <div class="flex flex-col gap-2"> <div class="relative h-40 overflow-hidden rounded-shape-lg border border-border"> <div class="grid h-full place-items-center"> <Text variant="label-sm" tone="muted">the app</Text> </div> <SplashScreen open={up[exit]} inline {exit} size="sm" pattern="gradient" title={exit} indicator="none" minDuration={0} duration={700} /> </div> <Button size="xs" variant="outlined" onclick={() => replay(exit)}>Play {exit}</Button> </div> {/each}</div> 5. Boot sequence
createSplash carries open, progress and message together, so the screen says what the app is actually doing. run walks the steps, weights the bar by how slow each one is, and takes the splash down at the end — including when a step throws.
Workspace
Loaded.
Acme
<script lang="ts"> import { Button, createSplash, SplashScreen, Text } from 'omaris'; // `open: false` because the app is already up here; a real one starts up. const splash = createSplash({ open: false }); const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); const boot = () => splash.run([ { label: 'Signing you in', run: () => wait(700) }, { label: 'Loading your workspace', weight: 2, run: () => wait(1200) }, { label: 'Almost there', run: () => wait(500) } ]);</script><div class="relative h-full w-full overflow-hidden rounded-shape-lg border border-border"> <div class="flex h-full flex-col items-start gap-3 p-6"> <Text variant="headline-sm" as="h2">Workspace</Text> <Text tone="muted">Loaded.</Text> <Button size="xs" onclick={boot}>Run the boot sequence</Button> </div> <SplashScreen {splash} inline title="Acme" pattern="aurora" indicator="bar" percent halo exit="iris" > {#snippet logo()} ... {/snippet} {#snippet footer()} <Text variant="label-sm">v2.4.0</Text> {/snippet} </SplashScreen></div> 6. Overridden
Every part is reachable. This one is left-aligned, bottom-anchored, has a display-sized title, a tertiary indicator and a footer of its own — none of which is a prop the component had to invent.
Ledger
Reconciling accounts
<script lang="ts"> import { Button, SplashScreen, Text } from 'omaris'; let open = $state(true);</script><div class="flex h-full w-full flex-col gap-3"> <div class="relative min-h-0 flex-1 overflow-hidden rounded-shape-lg border border-border"> <SplashScreen {open} inline variant="inverse" pattern="grid" align="bottom" enter="reveal" indicator="wave" exit="rise" title="Ledger" message="Reconciling accounts" classes={{ content: 'w-full max-w-none items-start px-10 text-start', title: 'text-display-sm', indicator: 'text-tertiary', message: 'opacity-60', footer: 'items-start px-10 text-start' }} > {#snippet footer()} <Text variant="label-sm">Built by Acme · v2.4.0</Text> {/snippet} </SplashScreen> </div> <Button size="xs" variant="outlined" class="self-start" onclick={() => (open = !open)}> {open ? 'Hide' : 'Show'} </Button></div>