Dialog
A modal window for displaying content and prompting user interaction
Sizes
Different dialog sizes for various use cases.
Code Svelte
1
2<script lang="ts">
3 import { Button, Input, Label, DialogPrimitives } from "@kareyes/aether";
4</script>
5
6<div class="flex flex-wrap gap-3">
7 <!-- Small -->
8 <DialogPrimitives.Dialog>
9 <DialogPrimitives.DialogTrigger>
10 <Button variant="outline">Small</Button>
11 </DialogPrimitives.DialogTrigger>
12 <DialogPrimitives.DialogContent size="sm">
13 <DialogPrimitives.DialogHeader>
14 <DialogPrimitives.DialogTitle>Small Dialog</DialogPrimitives.DialogTitle>
15 <DialogPrimitives.DialogDescription>
16 Perfect for simple confirmations and alerts.
17 </DialogPrimitives.DialogDescription>
18 </DialogPrimitives.DialogHeader>
19 <div class="py-4">
20 <p class="text-sm text-muted-foreground">This is a small dialog (max-w-sm).</p>
21 </div>
22 <DialogPrimitives.DialogFooter>
23 <DialogPrimitives.DialogClose>
24 <Button>Got it</Button>
25 </DialogPrimitives.DialogClose>
26 </DialogPrimitives.DialogFooter>
27 </DialogPrimitives.DialogContent>
28 </DialogPrimitives.Dialog>
29
30 <!-- Default -->
31 <DialogPrimitives.Dialog>
32 <DialogPrimitives.DialogTrigger>
33 <Button variant="outline">Default</Button>
34 </DialogPrimitives.DialogTrigger>
35 <DialogPrimitives.DialogContent size="default">
36 <DialogPrimitives.DialogHeader>
37 <DialogPrimitives.DialogTitle>Default Size Dialog</DialogPrimitives.DialogTitle>
38 <DialogPrimitives.DialogDescription>
39 The standard dialog size for most use cases.
40 </DialogPrimitives.DialogDescription>
41 </DialogPrimitives.DialogHeader>
42 <DialogPrimitives.DialogFooter>
43 <Button>Close</Button>
44 </DialogPrimitives.DialogFooter>
45 </DialogPrimitives.DialogContent>
46 </DialogPrimitives.Dialog>
47
48 <!-- Large -->
49 <DialogPrimitives.Dialog>
50 <DialogPrimitives.DialogTrigger>
51 <Button variant="outline">Large</Button>
52 </DialogPrimitives.DialogTrigger>
53 <DialogPrimitives.DialogContent size="lg">
54 <DialogPrimitives.DialogHeader>
55 <DialogPrimitives.DialogTitle>Large Dialog</DialogPrimitives.DialogTitle>
56 <DialogPrimitives.DialogDescription>
57 More space for detailed content and complex forms.
58 </DialogPrimitives.DialogDescription>
59 </DialogPrimitives.DialogHeader>
60 <div class="py-4 grid grid-cols-2 gap-4">
61 <div class="space-y-2">
62 <Label>First Name</Label>
63 <Input placeholder="John" />
64 </div>
65 <div class="space-y-2">
66 <Label>Last Name</Label>
67 <Input placeholder="Doe" />
68 </div>
69 </div>
70 <DialogPrimitives.DialogFooter>
71 <Button>Close</Button>
72 </DialogPrimitives.DialogFooter>
73 </DialogPrimitives.DialogContent>
74 </DialogPrimitives.Dialog>
75</div>Variants
Different layout variants for different contexts.
Code Svelte
1
2<script lang="ts">
3 import { Button, DialogPrimitives } from "@kareyes/aether";
4</script>
5
6<div class="flex flex-wrap gap-3">
7 <DialogPrimitives.Dialog>
8 <DialogPrimitives.DialogTrigger>
9 <Button variant="outline">Default Layout</Button>
10 </DialogPrimitives.DialogTrigger>
11 <DialogPrimitives.DialogContent variant="default">
12 <DialogPrimitives.DialogHeader>
13 <DialogPrimitives.DialogTitle>Default Layout</DialogPrimitives.DialogTitle>
14 <DialogPrimitives.DialogDescription>
15 Left-aligned on desktop, centered on mobile.
16 </DialogPrimitives.DialogDescription>
17 </DialogPrimitives.DialogHeader>
18 <DialogPrimitives.DialogFooter>
19 <Button variant="outline">Cancel</Button>
20 <Button>Confirm</Button>
21 </DialogPrimitives.DialogFooter>
22 </DialogPrimitives.DialogContent>
23 </DialogPrimitives.Dialog>
24
25 <DialogPrimitives.Dialog>
26 <DialogPrimitives.DialogTrigger>
27 <Button variant="outline">Centered Layout</Button>
28 </DialogPrimitives.DialogTrigger>
29 <DialogPrimitives.DialogContent variant="centered" size="sm">
30 <DialogPrimitives.DialogHeader>
31 <DialogPrimitives.DialogTitle>Centered Layout</DialogPrimitives.DialogTitle>
32 <DialogPrimitives.DialogDescription>
33 All content centered on all screen sizes.
34 </DialogPrimitives.DialogDescription>
35 </DialogPrimitives.DialogHeader>
36 <DialogPrimitives.DialogFooter>
37 <Button>Acknowledge</Button>
38 </DialogPrimitives.DialogFooter>
39 </DialogPrimitives.DialogContent>
40 </DialogPrimitives.Dialog>
41</div>Practical Examples
Real-world use cases and implementations.
Code Svelte
1
2<script lang="ts">
3 import { Button, Input, Label, Textarea, DialogPrimitives } from "@kareyes/aether";
4 import { Save, Trash2, Edit, Plus, FileText } from "@kareyes/aether/icons";
5
6 let profileDialogOpen = $state(false);
7 let name = $state("John Doe");
8 let email = $state("john@example.com");
9</script>
10
11<div class="flex flex-wrap gap-3">
12 <!-- Edit Profile -->
13 <DialogPrimitives.Dialog bind:open={profileDialogOpen}>
14 <DialogPrimitives.DialogTrigger>
15 <Button>
16 <Edit class="size-4 mr-2" />
17 Edit Profile
18 </Button>
19 </DialogPrimitives.DialogTrigger>
20 <DialogPrimitives.DialogContent>
21 <DialogPrimitives.DialogHeader>
22 <DialogPrimitives.DialogTitle>Edit Profile</DialogPrimitives.DialogTitle>
23 <DialogPrimitives.DialogDescription>
24 Make changes to your profile here.
25 </DialogPrimitives.DialogDescription>
26 </DialogPrimitives.DialogHeader>
27 <div class="grid gap-4 py-4">
28 <div class="grid grid-cols-4 items-center gap-4">
29 <Label for="name" class="text-end">Name</Label>
30 <Input id="name" bind:value={name} class="col-span-3" />
31 </div>
32 <div class="grid grid-cols-4 items-center gap-4">
33 <Label for="email" class="text-end">Email</Label>
34 <Input id="email" type="email" bind:value={email} class="col-span-3" />
35 </div>
36 </div>
37 <DialogPrimitives.DialogFooter>
38 <DialogPrimitives.DialogClose>
39 <Button variant="outline">Cancel</Button>
40 </DialogPrimitives.DialogClose>
41 <Button>
42 <Save class="size-4 mr-2" />
43 Save changes
44 </Button>
45 </DialogPrimitives.DialogFooter>
46 </DialogPrimitives.DialogContent>
47 </DialogPrimitives.Dialog>
48
49 <!-- Delete Confirmation -->
50 <DialogPrimitives.Dialog>
51 <DialogPrimitives.DialogTrigger>
52 <Button variant="destructive">
53 <Trash2 class="size-4 mr-2" />
54 Delete
55 </Button>
56 </DialogPrimitives.DialogTrigger>
57 <DialogPrimitives.DialogContent size="sm" variant="centered">
58 <DialogPrimitives.DialogHeader>
59 <DialogPrimitives.DialogTitle>Are you absolutely sure?</DialogPrimitives.DialogTitle>
60 <DialogPrimitives.DialogDescription>
61 This action cannot be undone.
62 </DialogPrimitives.DialogDescription>
63 </DialogPrimitives.DialogHeader>
64 <DialogPrimitives.DialogFooter>
65 <DialogPrimitives.DialogClose>
66 <Button variant="outline">Cancel</Button>
67 </DialogPrimitives.DialogClose>
68 <Button variant="destructive">
69 <Trash2 class="size-4 mr-2" />
70 Delete
71 </Button>
72 </DialogPrimitives.DialogFooter>
73 </DialogPrimitives.DialogContent>
74 </DialogPrimitives.Dialog>
75</div>Alert-Style Dialogs
Simple dialogs for alerts and notifications.
Code Svelte
1
2<script lang="ts">
3 import { Button, DialogPrimitives } from "@kareyes/aether";
4 import { CheckCircle2, AlertTriangle, Info } from "@kareyes/aether/icons";
5</script>
6
7<div class="flex flex-wrap gap-3">
8 <!-- Success -->
9 <DialogPrimitives.Dialog>
10 <DialogPrimitives.DialogTrigger>
11 <Button color="success">
12 <CheckCircle2 class="size-4 mr-2" />
13 Success
14 </Button>
15 </DialogPrimitives.DialogTrigger>
16 <DialogPrimitives.DialogContent size="sm" variant="centered">
17 <DialogPrimitives.DialogHeader>
18 <DialogPrimitives.DialogTitle class="flex items-center justify-center gap-2">
19 <CheckCircle2 class="size-5 text-success" />
20 Success!
21 </DialogPrimitives.DialogTitle>
22 <DialogPrimitives.DialogDescription>
23 Your changes have been saved successfully.
24 </DialogPrimitives.DialogDescription>
25 </DialogPrimitives.DialogHeader>
26 <DialogPrimitives.DialogFooter>
27 <DialogPrimitives.DialogClose>
28 <Button color="success">OK</Button>
29 </DialogPrimitives.DialogClose>
30 </DialogPrimitives.DialogFooter>
31 </DialogPrimitives.DialogContent>
32 </DialogPrimitives.Dialog>
33
34 <!-- Warning -->
35 <DialogPrimitives.Dialog>
36 <DialogPrimitives.DialogTrigger>
37 <Button color="warning">
38 <AlertTriangle class="size-4 mr-2" />
39 Warning
40 </Button>
41 </DialogPrimitives.DialogTrigger>
42 <DialogPrimitives.DialogContent size="sm" variant="centered">
43 <DialogPrimitives.DialogHeader>
44 <DialogPrimitives.DialogTitle class="flex items-center justify-center gap-2">
45 <AlertTriangle class="size-5 text-warning" />
46 Warning
47 </DialogPrimitives.DialogTitle>
48 <DialogPrimitives.DialogDescription>
49 You have unsaved changes. Continue?
50 </DialogPrimitives.DialogDescription>
51 </DialogPrimitives.DialogHeader>
52 <DialogPrimitives.DialogFooter>
53 <DialogPrimitives.DialogClose>
54 <Button variant="outline">Go Back</Button>
55 </DialogPrimitives.DialogClose>
56 <DialogPrimitives.DialogClose>
57 <Button color="warning">Continue</Button>
58 </DialogPrimitives.DialogClose>
59 </DialogPrimitives.DialogFooter>
60 </DialogPrimitives.DialogContent>
61 </DialogPrimitives.Dialog>
62</div>Special Features
Additional features and customization options.
Code Svelte
1
2<script lang="ts">
3 import { Button, DialogPrimitives } from "@kareyes/aether";
4</script>
5
6 <div class="flex flex-wrap gap-3">
7 <!-- No Close Button -->
8 <DialogPrimitives.Dialog>
9 <DialogPrimitives.DialogTrigger>
10 <Button variant="outline">No Close Button</Button>
11 </DialogPrimitives.DialogTrigger>
12 <DialogPrimitives.DialogContent showCloseButton={false}>
13 <DialogPrimitives.DialogHeader>
14 <DialogPrimitives.DialogTitle>Important Action</DialogPrimitives.DialogTitle>
15 <DialogPrimitives.DialogDescription>
16 This dialog requires you to make a choice. You must select an action.
17 </DialogPrimitives.DialogDescription>
18 </DialogPrimitives.DialogHeader>
19 <div class="py-4">
20 <p class="text-sm text-muted-foreground">
21 Without a close button, users must use one of the provided actions or press Escape.
22 </p>
23 </div>
24 <DialogPrimitives.DialogFooter>
25 <DialogPrimitives.DialogClose>
26 <Button variant="outline">Decline</Button>
27 </DialogPrimitives.DialogClose>
28 <DialogPrimitives.DialogClose>
29 <Button>Accept</Button>
30 </DialogPrimitives.DialogClose>
31 </DialogPrimitives.DialogFooter>
32 </DialogPrimitives.DialogContent>
33 </DialogPrimitives.Dialog>
34
35 <!-- Scrollable Content -->
36 <DialogPrimitives.Dialog>
37 <DialogPrimitives.DialogTrigger>
38 <Button variant="outline">Scrollable Content</Button>
39 </DialogPrimitives.DialogTrigger>
40 <DialogPrimitives.DialogContent size="lg">
41 <DialogPrimitives.DialogHeader>
42 <DialogPrimitives.DialogTitle>Terms and Conditions</DialogPrimitives.DialogTitle>
43 <DialogPrimitives.DialogDescription>Please read through our terms and conditions.</DialogPrimitives.DialogDescription>
44 </DialogPrimitives.DialogHeader>
45 <div class="max-h-[400px] overflow-y-auto py-4">
46 {#each Array(15) as _, i}
47 <div class="mb-4">
48 <h3 class="font-semibold text-sm mb-2">Section {i + 1}</h3>
49 <p class="text-sm text-muted-foreground">
50 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
51 tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
52 quis nostrud exercitation ullamco laboris.
53 </p>
54 </div>
55 {/each}
56 </div>
57 <DialogPrimitives.DialogFooter>
58 <DialogPrimitives.DialogClose>
59 <Button variant="outline">Decline</Button>
60 </DialogPrimitives.DialogClose>
61 <Button>Accept</Button>
62 </DialogPrimitives.DialogFooter>
63 </DialogPrimitives.DialogContent>
64 </DialogPrimitives.Dialog>
65
66 <!-- Custom Close Actions -->
67 <DialogPrimitives.Dialog>
68 <DialogPrimitives.DialogTrigger>
69 <Button variant="outline">Custom Close Actions</Button>
70 </DialogPrimitives.DialogTrigger>
71 <DialogPrimitives.DialogContent>
72 <DialogPrimitives.DialogHeader>
73 <DialogPrimitives.DialogTitle>Multiple Close Options</DialogPrimitives.DialogTitle>
74 <DialogPrimitives.DialogDescription>
75 This dialog can be closed in multiple ways with different actions.
76 </DialogPrimitives.DialogDescription>
77 </DialogPrimitives.DialogHeader>
78 <div class="py-4">
79 <p class="text-sm text-muted-foreground">
80 Each button performs a different action before closing.
81 </p>
82 </div>
83 <DialogPrimitives.DialogFooter>
84 <DialogPrimitives.DialogClose>
85 <Button variant="outline" onclick={() => (result = "Cancelled")}>Cancel</Button>
86 </DialogPrimitives.DialogClose>
87 <DialogPrimitives.DialogClose>
88 <Button variant="outline" onclick={() => (result = "Saved as draft")}>
89 Save Draft
90 </Button>
91 </DialogPrimitives.DialogClose>
92 <DialogPrimitives.DialogClose>
93 <Button onclick={() => (result = "Published")}>Publish</Button>
94 </DialogPrimitives.DialogClose>
95 </DialogPrimitives.DialogFooter>
96 </DialogPrimitives.DialogContent>
97 </DialogPrimitives.Dialog>
98 </div>Basic Usage
<script lang="ts">
import { DialogPrimitives, Button } from "@kareyes/aether";
</script>
<DialogPrimitives.Root>
<DialogPrimitives.Trigger>
<Button variant="outline">Open Dialog</Button>
</DialogPrimitives.Trigger>
<DialogPrimitives.Content>
<DialogPrimitives.Header>
<DialogPrimitives.Title>Edit Profile</DialogPrimitives.Title>
<DialogPrimitives.Description>
Make changes to your profile here. Click save when you're done.
</DialogPrimitives.Description>
</DialogPrimitives.Header>
<div class="py-4">
<!-- Your content here -->
</div>
<DialogPrimitives.Footer>
<DialogPrimitives.Close>
<Button variant="outline">Cancel</Button>
</DialogPrimitives.Close>
<Button>Save changes</Button>
</DialogPrimitives.Footer>
</DialogPrimitives.Content>
</DialogPrimitives.Root>
With Namespace Import
<script lang="ts">
import * as Dialog from "@kareyes/aether";
</script>
<Dialog.Root>
<Dialog.Trigger>
<Button>Open</Button>
</Dialog.Trigger>
<Dialog.Content>
<!-- ... -->
</Dialog.Content>
</Dialog.Root>
Components
| Component | Description |
|---|---|
Root |
Root component that manages dialog state |
Trigger |
Button or element that opens the dialog |
Content |
Main content container with size and variant options |
Overlay |
Semi-transparent backdrop |
Header |
Container for title and description |
Footer |
Container for action buttons |
Title |
Accessible title for the dialog |
Description |
Description text for the dialog |
Close |
Button to close the dialog |
Portal |
Portal component for DOM positioning |
Props Reference
Root
| Prop | Type | Default | Description |
|---|---|---|---|
open |
boolean |
false |
Controls the open state (bindable) |
onOpenChange |
(open: boolean) => void |
- | Callback when open state changes |
openFocus |
FocusProp |
- | Element to focus when opening |
closeFocus |
FocusProp |
- | Element to focus when closing |
portal |
HTMLElement | string |
body |
Portal target |
Content
| Prop | Type | Default | Description |
|---|---|---|---|
size |
"sm" | "default" | "lg" | "xl" | "full" |
"default" |
Size of the dialog |
variant |
"default" | "centered" |
"default" |
Layout variant |
showCloseButton |
boolean |
true |
Show/hide the close button |
class |
string |
- | Additional CSS classes |
Trigger
| Prop | Type | Default | Description |
|---|---|---|---|
class |
string |
- | Additional CSS classes |
Title
| Prop | Type | Default | Description |
|---|---|---|---|
class |
string |
- | Additional CSS classes |
Description
| Prop | Type | Default | Description |
|---|---|---|---|
class |
string |
- | Additional CSS classes |
Sizes
Small Dialog
<DialogPrimitives.Content size="sm">
<DialogPrimitives.Header>
<DialogPrimitives.Title>Small Dialog</DialogPrimitives.Title>
</DialogPrimitives.Header>
</DialogPrimitives.Content>
Default Size
<DialogPrimitives.Content size="default">
<!-- Default size -->
</DialogPrimitives.Content>
Large Dialog
<DialogPrimitives.Content size="lg">
<!-- More space for detailed content -->
</DialogPrimitives.Content>
Extra Large Dialog
<DialogPrimitives.Content size="xl">
<!-- Maximum space for complex content -->
</DialogPrimitives.Content>
Full Width Dialog
<DialogPrimitives.Content size="full">
<!-- 90vw width on desktop -->
</DialogPrimitives.Content>
Variants
Default Variant
Left-aligned on desktop, centered on mobile:
<DialogPrimitives.Content variant="default">
<!-- ... -->
</DialogPrimitives.Content>
Centered Variant
Centered layout for all screen sizes:
<DialogPrimitives.Content variant="centered">
<!-- ... -->
</DialogPrimitives.Content>
Examples
Controlled State
<script lang="ts">
import { DialogPrimitives, Button } from "@kareyes/aether";
let open = $state(false);
function handleSubmit() {
// Do something
open = false;
}
</script>
<DialogPrimitives.Root bind:open>
<DialogPrimitives.Trigger>
<Button>Open</Button>
</DialogPrimitives.Trigger>
<DialogPrimitives.Content>
<form onsubmit={handleSubmit}>
<!-- Form content -->
</form>
</DialogPrimitives.Content>
</DialogPrimitives.Root>
<Button onclick={() => open = true}>
Open from anywhere
</Button>
Form in Dialog
<script lang="ts">
import { DialogPrimitives, Button, Input, Label } from "@kareyes/aether";
let name = $state("");
let email = $state("");
function handleSave() {
console.log({ name, email });
}
</script>
<DialogPrimitives.Root>
<DialogPrimitives.Trigger>
<Button>Edit Profile</Button>
</DialogPrimitives.Trigger>
<DialogPrimitives.Content>
<DialogPrimitives.Header>
<DialogPrimitives.Title>Edit Profile</DialogPrimitives.Title>
<DialogPrimitives.Description>
Make changes to your profile here. Click save when you're done.
</DialogPrimitives.Description>
</DialogPrimitives.Header>
<div class="grid gap-4 py-4">
<div class="grid grid-cols-4 items-center gap-4">
<Label for="name" class="text-end">Name</Label>
<Input id="name" bind:value={name} class="col-span-3" />
</div>
<div class="grid grid-cols-4 items-center gap-4">
<Label for="email" class="text-end">Email</Label>
<Input id="email" type="email" bind:value={email} class="col-span-3" />
</div>
</div>
<DialogPrimitives.Footer>
<DialogPrimitives.Close>
<Button variant="outline">Cancel</Button>
</DialogPrimitives.Close>
<Button onclick={handleSave}>Save changes</Button>
</DialogPrimitives.Footer>
</DialogPrimitives.Content>
</DialogPrimitives.Root>
Confirmation Dialog
<script lang="ts">
import { DialogPrimitives, Button } from "@kareyes/aether";
import Trash2Icon from "@lucide/svelte/icons/trash-2";
function handleDelete() {
console.log("Item deleted");
}
</script>
<DialogPrimitives.Root>
<DialogPrimitives.Trigger>
<Button variant="destructive">
<Trash2Icon class="size-4 mr-2" />
Delete
</Button>
</DialogPrimitives.Trigger>
<DialogPrimitives.Content size="sm" variant="centered">
<DialogPrimitives.Header>
<DialogPrimitives.Title>Are you sure?</DialogPrimitives.Title>
<DialogPrimitives.Description>
This action cannot be undone. This will permanently delete the item.
</DialogPrimitives.Description>
</DialogPrimitives.Header>
<DialogPrimitives.Footer>
<DialogPrimitives.Close>
<Button variant="outline">Cancel</Button>
</DialogPrimitives.Close>
<Button variant="destructive" onclick={handleDelete}>
Delete
</Button>
</DialogPrimitives.Footer>
</DialogPrimitives.Content>
</DialogPrimitives.Root>
Without Close Button
<DialogPrimitives.Content showCloseButton={false}>
<DialogPrimitives.Header>
<DialogPrimitives.Title>Important Action</DialogPrimitives.Title>
<DialogPrimitives.Description>
This requires your attention. You must choose an action.
</DialogPrimitives.Description>
</DialogPrimitives.Header>
<DialogPrimitives.Footer>
<DialogPrimitives.Close>
<Button>Confirm</Button>
</DialogPrimitives.Close>
</DialogPrimitives.Footer>
</DialogPrimitives.Content>
Scrollable Content
<DialogPrimitives.Content size="lg">
<DialogPrimitives.Header>
<DialogPrimitives.Title>Long Content</DialogPrimitives.Title>
</DialogPrimitives.Header>
<div class="max-h-[400px] overflow-y-auto py-4">
{#each Array(20) as _, i}
<p class="mb-4">Content item {i + 1}</p>
{/each}
</div>
<DialogPrimitives.Footer>
<Button>Close</Button>
</DialogPrimitives.Footer>
</DialogPrimitives.Content>
Accessibility
The Dialog component follows the WAI-ARIA dialog pattern:
Keyboard Navigation
| Key | Action |
|---|---|
Escape |
Close the dialog |
Tab |
Move focus forward within dialog |
Shift + Tab |
Move focus backward within dialog |
Focus Management
- Focus is trapped within the dialog when open
- First focusable element receives focus when opened
- Focus returns to trigger element when closed
ARIA Attributes
role="dialog"on dialog contentaria-labelledbyconnects to Titlearia-describedbyconnects to Descriptionaria-modal="true"indicates modal behavior
Best Practices
- Always include a title: Use Title for accessibility
- Provide descriptions: Use Description to explain the dialog's purpose
- Keep content focused: Dialogs should have a single, clear purpose
- Choose appropriate size: Use smaller sizes for confirmations, larger for forms
- Avoid nesting: Don't open dialogs within dialogs
- Close actions: Provide clear ways to close the dialog