Skip to content
tcpsystemsui

Theme

Colour scheme
Accent
Density
Radius
Esc

Dialog

Native modal dialog with focus return.

beta

Examples

Confirm delete

Delete gateway-vnext?

This deletes 14 release records and removes the production route. It cannot be undone.

Confirm delete.svelte
<script lang="ts">
	import Button from '@tcpsystems/ui/foundation/Button';
	import Dialog from '@tcpsystems/ui/foundation/Dialog';
	import Field from '@tcpsystems/ui/foundation/Field';
	import Input from '@tcpsystems/ui/foundation/Input';
	const uid = $props.id();
</script>

<Button data-tcp-open={uid}>Delete deployment</Button>
<Dialog id={uid} title="Delete gateway-vnext?">
	<p>This deletes 14 release records and removes the production route. It cannot be undone.</p>
	<Field label="Type gateway-vnext to confirm">
		{#snippet control(c)}<Input id={c.id} kind="mono" describedby={c.describedby} autocomplete="off" />{/snippet}
	</Field>
	{#snippet foot()}
		<form method="dialog"><Button type="submit">Cancel</Button></form>
		<Button variant="danger">Delete deployment</Button>
	{/snippet}
</Dialog>

Share invite

Share gateway-vnext

Share invite.svelte
<script lang="ts">
	import Button from '@tcpsystems/ui/foundation/Button';
	import Dialog from '@tcpsystems/ui/foundation/Dialog';
	import Field from '@tcpsystems/ui/foundation/Field';
	import Input from '@tcpsystems/ui/foundation/Input';
	import Textarea from '@tcpsystems/ui/foundation/Textarea';
	import Stack from '@tcpsystems/ui/foundation/Stack';
	const uid = $props.id();
</script>

<Button data-tcp-open={uid}>Share deployment</Button>
<Dialog id={uid} title="Share gateway-vnext">
	<Stack>
		<Field label="Invitee email">
			{#snippet control(c)}<Input id={c.id} type="email" describedby={c.describedby} placeholder="mara@tcp.systems" />{/snippet}
		</Field>
		<Field label="Message">
			{#snippet control(c)}<Textarea id={c.id} describedby={c.describedby} rows={3}>Can you review this deployment before we promote it?</Textarea>{/snippet}
		</Field>
	</Stack>
	{#snippet foot()}
		<form method="dialog"><Button type="submit">Cancel</Button></form>
		<Button variant="primary">Send invite</Button>
	{/snippet}
</Dialog>

Sizes

Rotate access key

This creates a new key for billing-api. The current key keeps working for 24 hours.

Invoice INV-2048

Acme Labs · April 2026 · €4,820.00 · Paid on 2026-04-03. Includes gateway traffic, 3 team members, and priority support.

Sizes.svelte
<script lang="ts">
	import Button from '@tcpsystems/ui/foundation/Button';
	import Dialog from '@tcpsystems/ui/foundation/Dialog';
	import Cluster from '@tcpsystems/ui/foundation/Cluster';
	const uid = $props.id();
	const sm = uid + '-sm';
	const lg = uid + '-lg';
</script>

<Cluster>
	<Button data-tcp-open={sm}>Small dialog</Button>
	<Button data-tcp-open={lg}>Large dialog</Button>
</Cluster>
<Dialog id={sm} title="Rotate access key" size="sm">
	<p>This creates a new key for billing-api. The current key keeps working for 24 hours.</p>
	{#snippet foot()}
		<form method="dialog"><Button type="submit">Cancel</Button></form>
		<Button variant="primary">Rotate key</Button>
	{/snippet}
</Dialog>
<Dialog id={lg} title="Invoice INV-2048" size="lg">
	<p>Acme Labs · April 2026 · €4,820.00 · Paid on 2026-04-03. Includes gateway traffic, 3 team members, and priority support.</p>
	{#snippet foot()}
		<form method="dialog"><Button type="submit">Close</Button></form>
		<Button variant="primary">Download PDF</Button>
	{/snippet}
</Dialog>

API

Import
import Dialog from '@tcpsystems/ui/foundation/Dialog';
PropTypeDefault
mode?'dialog' | 'alert''dialog'
idstringnone
titlestringnone
size?'sm' | 'lg'none
confirmLabel?string'Confirm'
cancelLabel?string'Cancel'
tone?'danger' | 'neutral''danger'
pending?booleanfalse
pendingLabel?stringnone
confirmText?stringnone
confirmTextLabel?stringnone
Snippet
foot
children
HookKind
.tcp-dialogRoot class
data-sizeData attribute
data-tcp-confirm-textData attribute
data-variantData attribute