Kumo Svelte
  • Home
  • Installation
  • Colors
  • Accessibility
  • Changelog
  • Autocomplete
  • Badge
  • Banner
  • Breadcrumbs
  • Button
  • Checkbox
  • Clipboard Text
  • Cloudflare Logo
  • CodeHighlighted
  • Collapsible
  • Combobox
  • Command Palette
  • Date Picker
  • Dialog
  • Dropdown
  • Empty
  • Flow
  • Grid
  • Input
  • InputArea
  • InputGroup
  • Label
  • Layer Card
  • Link
  • Loader
  • MenuBar
  • Meter
  • Pagination
  • Popover
  • Radio
  • Select
  • Sensitive Input
  • Sidebar
  • Skeleton Line
  • Switch
  • Table
  • Table of Contents
  • Tabs
  • Text
  • Toast
  • Toolbar
  • Tooltip
  • Charts
  • Colors
  • Timeseries
  • Maps
  • Sankey
  • Custom Chart
  • Page Header
  • Resource List
  • Delete Resource
Dialog
kumo-svelte

Dialog

A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.

<script lang="ts">
  import { Button } from "kumo-svelte/components/button";
  import * as Dialog from "kumo-svelte/components/dialog";
  import XIcon from "phosphor-svelte/lib/XIcon";
</script>

<Dialog.Root>
  <Dialog.Trigger>
    {#snippet child({ props })}
      <Button {...props}>Delete</Button>
    {/snippet}
  </Dialog.Trigger>
  <Dialog.Content class="p-8">
    <div class="mb-4 flex items-start justify-between gap-4">
      <Dialog.Title class="text-2xl font-semibold">Modal Title</Dialog.Title>
      <Dialog.Close aria-label="Close">
        {#snippet child({ props })}
          <Button {...props} variant="secondary" shape="square" icon={XIcon} aria-label="Close" />
        {/snippet}
      </Dialog.Close>
    </div>
    <Dialog.Description class="text-kumo-subtle">
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
      labore et dolore magna aliqua.
    </Dialog.Description>
    <div class="mt-8 flex justify-end gap-2">
      <Dialog.Close>
        {#snippet child({ props })}
          <Button {...props} variant="secondary">Cancel</Button>
        {/snippet}
      </Dialog.Close>
      <Dialog.Close>
        {#snippet child({ props })}
          <Button {...props} variant="destructive">Delete</Button>
        {/snippet}
      </Dialog.Close>
    </div>
  </Dialog.Content>
</Dialog.Root>

Import

import * as Dialog from "kumo-svelte/components/dialog";

Usage

<script lang="ts">
  import { Button } from "kumo-svelte/components/button";
  import * as Dialog from "kumo-svelte/components/dialog";
</script>

<Dialog.Root>
  <Dialog.Trigger>
    {#snippet child({ props })}
      <Button {...props}>Open</Button>
    {/snippet}
  </Dialog.Trigger>
  <Dialog.Content class="p-8">
    <Dialog.Title>Dialog Title</Dialog.Title>
    <Dialog.Description>Dialog content goes here.</Dialog.Description>
    <div class="mt-4 flex justify-end gap-2">
      <Dialog.Close>
        {#snippet child({ props })}
          <Button {...props} variant="secondary">Cancel</Button>
        {/snippet}
      </Dialog.Close>
    </div>
  </Dialog.Content>
</Dialog.Root>

Dialog vs Alert Dialog

The Dialog component supports two ARIA roles to properly convey semantic meaning to assistive technologies:

RoleUse CaseBehavior
role="dialog"General-purpose modals, forms, content displayDismissible by default
role="alertdialog"Destructive actions, confirmations, critical warningsRequires explicit user acknowledgment

Examples

Basic Dialog

<script lang="ts">
  import { Button } from "kumo-svelte/components/button";
  import * as Dialog from "kumo-svelte/components/dialog";
  import XIcon from "phosphor-svelte/lib/XIcon";
</script>

<Dialog.Root>
  <Dialog.Trigger>
    {#snippet child({ props })}
      <Button {...props}>Click me</Button>
    {/snippet}
  </Dialog.Trigger>
  <Dialog.Content class="p-8">
    <div class="mb-4 flex items-start justify-between gap-4">
      <Dialog.Title class="text-2xl font-semibold">Modal Title</Dialog.Title>
      <Dialog.Close aria-label="Close">
        {#snippet child({ props })}
          <Button {...props} variant="secondary" shape="square" icon={XIcon} aria-label="Close" />
        {/snippet}
      </Dialog.Close>
    </div>
    <Dialog.Description class="text-kumo-subtle">
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
      labore et dolore magna aliqua.
    </Dialog.Description>
  </Dialog.Content>
</Dialog.Root>

Alert Dialog (role="alertdialog")

For destructive or confirmation dialogs, use role="alertdialog" on Dialog.Root. This provides proper accessibility semantics by rendering the dialog with role="alertdialog" instead of role="dialog".

<script lang="ts">
  import { Button } from "kumo-svelte/components/button";
  import * as Dialog from "kumo-svelte/components/dialog";
  import WarningIcon from "phosphor-svelte/lib/WarningIcon";
</script>

<Dialog.Root role="alertdialog">
  <Dialog.Trigger>
    {#snippet child({ props })}
      <Button {...props} variant="destructive">Delete Account</Button>
    {/snippet}
  </Dialog.Trigger>
  <Dialog.Content class="p-8">
    <div class="mb-4 flex items-center gap-3">
      <div class="flex h-10 w-10 items-center justify-center rounded-full bg-kumo-danger/20">
        <WarningIcon size={20} weight="fill" class="text-kumo-danger" />
      </div>
      <Dialog.Title class="text-xl font-semibold">Delete Account?</Dialog.Title>
    </div>
    <Dialog.Description class="text-kumo-subtle">
      This action cannot be undone. All your data will be permanently removed from our servers. Are you sure you want to
      proceed?
    </Dialog.Description>
    <div class="mt-8 flex justify-end gap-2">
      <Dialog.Close>
        {#snippet child({ props })}
          <Button {...props} variant="secondary">Cancel</Button>
        {/snippet}
      </Dialog.Close>
      <Dialog.Close>
        {#snippet child({ props })}
          <Button {...props} variant="destructive">Delete Account</Button>
        {/snippet}
      </Dialog.Close>
    </div>
  </Dialog.Content>
</Dialog.Root>

Confirmation Dialog (with disablePointerDismissal)

For confirmation dialogs that should not be dismissed by clicking outside, use disablePointerDismissal on Dialog.Root.

<script lang="ts">
  import { Button } from "kumo-svelte/components/button";
  import * as Dialog from "kumo-svelte/components/dialog";
  import WarningIcon from "phosphor-svelte/lib/WarningIcon";
</script>

<Dialog.Root disablePointerDismissal>
  <Dialog.Trigger>
    {#snippet child({ props })}
      <Button {...props} variant="destructive">Delete Project</Button>
    {/snippet}
  </Dialog.Trigger>
  <Dialog.Content class="p-8">
    <div class="mb-4 flex items-center gap-3">
      <div class="flex h-10 w-10 items-center justify-center rounded-full bg-kumo-danger/20">
        <WarningIcon size={20} class="text-kumo-danger" />
      </div>
      <Dialog.Title class="text-xl font-semibold">Delete Project?</Dialog.Title>
    </div>
    <Dialog.Description class="text-kumo-subtle">
      This action cannot be undone. This will permanently delete the project and all associated data.
    </Dialog.Description>
    <div class="mt-8 flex justify-end gap-2">
      <Dialog.Close>
        {#snippet child({ props })}
          <Button {...props} variant="secondary">Cancel</Button>
        {/snippet}
      </Dialog.Close>
      <Dialog.Close>
        {#snippet child({ props })}
          <Button {...props} variant="destructive">Delete</Button>
        {/snippet}
      </Dialog.Close>
    </div>
  </Dialog.Content>
</Dialog.Root>

With Actions

<script lang="ts">
  import { Button } from "kumo-svelte/components/button";
  import * as Dialog from "kumo-svelte/components/dialog";
  import XIcon from "phosphor-svelte/lib/XIcon";
</script>

<Dialog.Root>
  <Dialog.Trigger>
    {#snippet child({ props })}
      <Button {...props}>Delete</Button>
    {/snippet}
  </Dialog.Trigger>
  <Dialog.Content class="p-8">
    <div class="mb-4 flex items-start justify-between gap-4">
      <Dialog.Title class="text-2xl font-semibold">Modal Title</Dialog.Title>
      <Dialog.Close aria-label="Close">
        {#snippet child({ props })}
          <Button {...props} variant="secondary" shape="square" icon={XIcon} aria-label="Close" />
        {/snippet}
      </Dialog.Close>
    </div>
    <Dialog.Description class="text-kumo-subtle">
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
      labore et dolore magna aliqua.
    </Dialog.Description>
    <div class="mt-8 flex justify-end gap-2">
      <Dialog.Close>
        {#snippet child({ props })}
          <Button {...props} variant="secondary">Cancel</Button>
        {/snippet}
      </Dialog.Close>
      <Dialog.Close>
        {#snippet child({ props })}
          <Button {...props} variant="destructive">Delete</Button>
        {/snippet}
      </Dialog.Close>
    </div>
  </Dialog.Content>
</Dialog.Root>

With Select

Dialog containing a Select dropdown.

<script lang="ts">
  import { Button } from "kumo-svelte/components/button";
  import * as Dialog from "kumo-svelte/components/dialog";
  import * as Select from "kumo-svelte/components/select";
  import XIcon from "phosphor-svelte/lib/XIcon";

  const regions = [
    { value: "us-east", label: "US East" },
    { value: "us-west", label: "US West" },
    { value: "eu-west", label: "EU West" },
    { value: "ap-south", label: "AP South" },
  ];

  let region = $state("");
</script>

<Dialog.Root>
  <Dialog.Trigger>
    {#snippet child({ props })}
      <Button {...props}>Open Form</Button>
    {/snippet}
  </Dialog.Trigger>
  <Dialog.Content class="p-8">
    <div class="mb-4 flex items-start justify-between gap-4">
      <Dialog.Title class="text-2xl font-semibold">Create Resource</Dialog.Title>
      <Dialog.Close aria-label="Close">
        {#snippet child({ props })}
          <Button {...props} variant="secondary" shape="square" icon={XIcon} aria-label="Close" />
        {/snippet}
      </Dialog.Close>
    </div>
    <Dialog.Description class="mb-4 text-kumo-subtle">Select a region for your new resource.</Dialog.Description>
    <Select.Root
      items={regions}
      value={region}
      onValueChange={(value) => {
        region = value as string;
      }}
      placeholder="Select region..."
      class="w-full"
    />
    <div class="mt-8 flex justify-end gap-2">
      <Dialog.Close>
        {#snippet child({ props })}
          <Button {...props} variant="secondary">Cancel</Button>
        {/snippet}
      </Dialog.Close>
      <Button variant="primary">Create</Button>
    </div>
  </Dialog.Content>
</Dialog.Root>

With Combobox

Dialog containing a Combobox for searchable selection.

<script lang="ts">
  import { Button } from "kumo-svelte/components/button";
  import * as Combobox from "kumo-svelte/components/combobox";
  import * as Dialog from "kumo-svelte/components/dialog";
  import XIcon from "phosphor-svelte/lib/XIcon";

  const regions = [
    { value: "us-east", label: "US East" },
    { value: "us-west", label: "US West" },
    { value: "eu-west", label: "EU West" },
    { value: "ap-south", label: "AP South" },
  ];

  let region = $state("");
</script>

<Dialog.Root>
  <Dialog.Trigger>
    {#snippet child({ props })}
      <Button {...props}>Open Form</Button>
    {/snippet}
  </Dialog.Trigger>
  <Dialog.Content class="p-8">
    <div class="mb-4 flex items-start justify-between gap-4">
      <Dialog.Title class="text-2xl font-semibold">Create Resource</Dialog.Title>
      <Dialog.Close aria-label="Close">
        {#snippet child({ props })}
          <Button {...props} variant="secondary" shape="square" icon={XIcon} aria-label="Close" />
        {/snippet}
      </Dialog.Close>
    </div>
    <Dialog.Description class="mb-4 text-kumo-subtle">
      Search and select a region for your new resource.
    </Dialog.Description>
    <Combobox.Root bind:value={region}>
      <Combobox.TriggerInput class="w-full" placeholder="Search regions..." />
      <Combobox.Content>
        <Combobox.Empty>No regions found</Combobox.Empty>
        <Combobox.List>
          {#each regions as item (item.value)}
            <Combobox.Item value={item.value}>{item.label}</Combobox.Item>
          {/each}
        </Combobox.List>
      </Combobox.Content>
    </Combobox.Root>
    <div class="mt-8 flex justify-end gap-2">
      <Dialog.Close>
        {#snippet child({ props })}
          <Button {...props} variant="secondary">Cancel</Button>
        {/snippet}
      </Dialog.Close>
      <Button variant="primary">Create</Button>
    </div>
  </Dialog.Content>
</Dialog.Root>

With Dropdown

Dialog containing a Dropdown menu.

<script lang="ts">
  import { Button } from "kumo-svelte/components/button";
  import * as Dialog from "kumo-svelte/components/dialog";
  import * as DropdownMenu from "kumo-svelte/components/dropdown";
  import XIcon from "phosphor-svelte/lib/XIcon";
</script>

<Dialog.Root>
  <Dialog.Trigger>
    {#snippet child({ props })}
      <Button {...props}>Open Form</Button>
    {/snippet}
  </Dialog.Trigger>
  <Dialog.Content class="p-8">
    <div class="mb-4 flex items-start justify-between gap-4">
      <Dialog.Title class="text-2xl font-semibold">Resource Actions</Dialog.Title>
      <Dialog.Close aria-label="Close">
        {#snippet child({ props })}
          <Button {...props} variant="secondary" shape="square" icon={XIcon} aria-label="Close" />
        {/snippet}
      </Dialog.Close>
    </div>
    <Dialog.Description class="mb-4 text-kumo-subtle">Choose an action for the selected resource.</Dialog.Description>
    <DropdownMenu.Root>
      <DropdownMenu.Trigger>
        {#snippet child({ props })}
          <Button {...props}>Actions</Button>
        {/snippet}
      </DropdownMenu.Trigger>
      <DropdownMenu.Content>
        <DropdownMenu.Item>Edit</DropdownMenu.Item>
        <DropdownMenu.Item>Duplicate</DropdownMenu.Item>
        <DropdownMenu.Separator />
        <DropdownMenu.Item variant="danger">Delete</DropdownMenu.Item>
      </DropdownMenu.Content>
    </DropdownMenu.Root>
    <div class="mt-8 flex justify-end">
      <Dialog.Close>
        {#snippet child({ props })}
          <Button {...props} variant="secondary">Close</Button>
        {/snippet}
      </Dialog.Close>
    </div>
  </Dialog.Content>
</Dialog.Root>

API Reference

Dialog.Close

No component-specific props. This component accepts child content or standard forwarded attributes.

Dialog.Content

PropTypeDefault
children*Snippet—
classstring—
containerPortalProps["to"]—
sizeKumoDialogSizeKUMO_DIALOG_DEFAULT_VARIANTS.size
stylestring—
idstring—

Dialog.Description

PropTypeDefault
children*Snippet—
classstring—
idstring—

Dialog.Footer

PropTypeDefault
childrenSnippet—

Dialog.Header

PropTypeDefault
childrenSnippet—

Dialog.Overlay

No component-specific props. This component accepts child content or standard forwarded attributes.

Dialog.Portal

PropTypeDefault
childrenSnippet—
toPortalProps["to"]—

Dialog.Root

PropTypeDefault
children*Snippet—
roleKumoDialogRoleKUMO_DIALOG_DEFAULT_VARIANTS.role
disablePointerDismissalbooleanfalse
openbooleanfalse
onOpenChange(open: boolean) => void—

Dialog.Title

PropTypeDefault
children*Snippet—
classstring—
idstring—
level1 | 2 | 3 | 4 | 5 | 62

Dialog.Trigger

No component-specific props. This component accepts child content or standard forwarded attributes.

On this page

  • Import
  • Usage
  • Dialog vs Alert Dialog
  • Examples
    • Basic Dialog
    • Alert Dialog (role="alertdialog")
    • Confirmation Dialog (with disablePointerDismissal)
    • With Actions
    • With Select
    • With Combobox
    • With Dropdown
  • API Reference
    • Dialog.Close
    • Dialog.Content
    • Dialog.Description
    • Dialog.Footer
    • Dialog.Header
    • Dialog.Overlay
    • Dialog.Portal
    • Dialog.Root
    • Dialog.Title
    • Dialog.Trigger