Skip to content
Containment

Sheet

MD3 side and bottom sheets.

Walkthrough

1. Sides

Four edges. A bottom sheet is what a phone wants; the sides suit a desktop panel.

<script lang="ts">	import { Button, Sheet } from 'omaris';​	let side = $state<'start' | 'end' | 'top' | 'bottom'>('end');	let open = $state(false);​	function show(next: typeof side) {		side = next;		open = true;	}</script>​<Button variant="outlined" size="xs" onclick={() => show('start')}>start</Button><Button variant="outlined" size="xs" onclick={() => show('end')}>end</Button><Button variant="outlined" size="xs" onclick={() => show('top')}>top</Button><Button variant="outlined" size="xs" onclick={() => show('bottom')}>bottom</Button>​<Sheet bind:open {side} title="Filters" description="side = {side}">	<p class="text-body-md text-muted-foreground">Drag the handle to dismiss it, or press outside.</p></Sheet>

2. Snap points

snapPoints are fractions of the screen a bottom sheet settles at, so it can be a peek, a half sheet and a full one without three components.

<script lang="ts">	import { Button, Sheet } from 'omaris';​	let open = $state(false);	let snap = $state(0);</script>​<Button variant="tonal" onclick={() => (open = true)}>Open a snapping sheet</Button>​<Sheet	bind:open	bind:snap	side="bottom"	size="full"	snapPoints={[0.25, 0.6, 1]}	title="Nearby drivers"	description="Drag it up and down">	<div class="flex flex-col gap-3">		{#each { length: 10 }, i (i)}			<div class="h-12 rounded-shape-md bg-surface-container"></div>		{/each}	</div></Sheet>

4. Persistent

modal={false} is a panel, not an interruption: no backdrop, and the page behind stays live. With inline it sits inside its own container, so a map keeps its controls and a screen keeps its navigation bar. Bind snap and the page can move it — a focused search box lifts it, a trip drops it.

The page behind: still scrollable, tappable, and where the map would be.

<script lang="ts">	import { Button, Input, List, ListItem, Sheet, Text } from 'omaris';​	let snap = $state(0.4);	const PLACES = ['Citadel', 'Ankawa', '60m Street', 'Bakhtiari', 'Family Mall', 'Gulan Park'];</script>​<div class="relative h-96 w-full overflow-clip rounded-shape-lg bg-surface-container">	<div class="grid h-full place-items-start p-4">		<Text variant="body-sm" tone="muted">			The page behind: still scrollable, tappable, and where the map would be.		</Text>	</div>​	<Sheet		open		inline		modal={false}		dismissible={false}		side="bottom"		size="full"		snapPoints={[0.25, 0.55, 1]}		bind:snap		classes={{ root: 'border-t border-border' }}	>		<div class="flex flex-col gap-3">			<Input placeholder="Where to?" onfocus={() => (snap = 1)} />			<div class="flex gap-2">				<Button size="xs" variant="tonal" onclick={() => (snap = 0.25)}>Peek</Button>				<Button size="xs" variant="tonal" onclick={() => (snap = 0.55)}>Half</Button>				<Button size="xs" variant="tonal" onclick={() => (snap = 1)}>Full</Button>			</div>			<List>				{#each PLACES as place (place)}					<ListItem headline={place} supportingText="Tap to go" onclick={() => (snap = 0.25)} />				{/each}			</List>		</div>	</Sheet></div>