Skip to content
Containment

Share

The share sheet — a bottom sheet on a phone, a centred dialog on a desktop, built on Dialog so the focus trap, the drag-to-dismiss and the morphing height all come for free.

Walkthrough

1. Basic

Three fields and a binding. The preview, the copyable link, the QR code and seven working destinations are all derived from them.

Share

A bottom sheet on a phone, a dialog on a desktop, and nothing to wire.

omaris.dev/docs/components/share

Share via

<script lang="ts">	import { Button, Share } from 'omaris';​	let open = $state(false);</script>​<Button onclick={() => (open = true)}>Share this page</Button>​<Share	bind:open	url="https://omaris.dev/docs/components/share"	title="Share"	text="A bottom sheet on a phone, a dialog on a desktop, and nothing to wire."/>

2. People

people puts a row of faces above the apps, each badged with the channel it would send over. Someone with nothing to send to stays on the rail, unpressable, rather than disappearing from it.

Q3 revenue

Up 14% on Q2, with Erbil carrying most of it.

omaris.dev/reports/q3

Send to

Share via

<script lang="ts">	import { Button, Share, shareGlyphs, type ShareTarget } from 'omaris';​	let open = $state(false);	/** Who it went to. The row is the record, so nothing else announces it. */	let sentTo = $state<string | null>(null);​	const people: ShareTarget[] = [		{			id: 'rania',			label: 'Rania',			detail: 'WhatsApp',			tint: '#25d366',			glyph: shareGlyphs.bubble,			onselect: () => {				sentTo = 'Rania';			}		},		{			id: 'dilan',			label: 'Dilan',			detail: 'Telegram',			tint: '#2aabee',			glyph: shareGlyphs.plane,			onselect: () => {				sentTo = 'Dilan';			}		},		{			id: 'karwan',			label: 'Karwan',			detail: 'Email',			glyph: shareGlyphs.mail,			onselect: () => {				sentTo = 'Karwan';			}		},		{ id: 'hemin', label: 'Hemin', detail: 'Offline', disabled: true }	];</script>​<Button variant="tonal" onclick={() => (open = true)}>Send the report</Button>​{#if sentTo}	<p class="mt-3 text-body-sm text-muted-foreground">Sent to {sentTo}.</p>{/if}​<Share	bind:open	url="https://omaris.dev/reports/q3"	title="Q3 revenue"	text="Up 14% on Q2, with Erbil carrying most of it."	{people}	targets={['whatsapp', 'telegram', 'email']}/>

3. Your own targets

targets takes built-in names and your own objects in the same array, and actions are the rows underneath it. Revoking the link is the one press whose result would otherwise be invisible, so the row says it — and the link bar goes.

Invoice INV-2291

Due 30 September.

omaris.dev/invoices/INV-2291

Share via

<script lang="ts">	import { Button, Share, shareGlyphs, shareTargets, type ShareTarget } from 'omaris';​	let open = $state(false);	let revoked = $state(false);​	const intranet: ShareTarget = {		id: 'intranet',		label: 'Intranet',		tint: 'var(--primary)',		ink: 'var(--primary-foreground)',		glyph: shareGlyphs.globe,		href: (data) => `https://intranet.example.com/post?url=${encodeURIComponent(data.url ?? '')}`	};</script>​<Button variant="tonal" onclick={() => (open = true)}>Send invoice</Button>​<Share	bind:open	heading="Send invoice"	url="https://omaris.dev/invoices/INV-2291"	title="Invoice INV-2291"	text={revoked ? 'The link has been revoked.' : 'Due 30 September.'}	link={!revoked}	qr={!revoked}	targets={['whatsapp', 'email', shareTargets.telegram, intranet]}	actions={[		{ id: 'pdf', label: 'Download PDF', detail: '184 KB', glyph: shareGlyphs.download },		{			id: 'revoke',			label: revoked ? 'Issue a new link' : 'Revoke this link',			// Re-issuing brings the link bar back, which says it by itself.			done: revoked ? undefined : 'Link revoked',			glyph: shareGlyphs.cross,			destructive: !revoked,			onselect: () => {				revoked = !revoked;			}		}	]}/>

4. Overridden

The overridden case: a wider dialog, density="compact", no destination rail at all, and a consumer's classes on three separate parts. class still covers the dialog itself.

Fleet dashboard

Live, and shared read-only.

omaris.dev/dashboards/fleet
<script lang="ts">	import { Button, Share, shareGlyphs } from 'omaris';​	let open = $state(false);</script>​<Button variant="outlined" onclick={() => (open = true)}>Share a snapshot</Button>​<Share	bind:open	heading="Snapshot"	url="https://omaris.dev/dashboards/fleet"	title="Fleet dashboard"	text="Live, and shared read-only."	size="lg"	density="compact"	targets={false}	class="max-w-xl"	classes={{		thumb: 'rounded-full bg-tertiary-container text-tertiary-container-foreground',		link: 'bg-primary-container',		actions: 'bg-transparent ring-1 ring-border'	}}	actions={[		{ id: 'png', label: 'Save as PNG', detail: '1200 × 630', glyph: shareGlyphs.download },		{ id: 'open', label: 'Open in a new tab', glyph: shareGlyphs.globe }	]}/>