Clidey UXDocs

Dialog

Dialog renders content in an overlay that blocks interaction with the rest of the page. Built on Radix UI's dialog primitive with focus trapping and scroll locking.

Interactive example#

Dialog · Live example

Open the dialog, tab through its fields, and press Escape to return focus.

The code uses shared demo presentation helpers. Their complete source and styling are included in the LLM build context.

Import#

TSX

import {
  Dialog,
  DialogTrigger,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
  DialogClose,
} from '@clidey/ux';

Basic dialog#

TSX

<Dialog>
  <DialogTrigger>
    <Button variant="outline">Open dialog</Button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Edit profile</DialogTitle>
      <DialogDescription>
        Make changes to your profile here. Click save when you're done.
      </DialogDescription>
    </DialogHeader>
    <div className="space-y-4 py-4">
      <div className="space-y-1">
        <Label htmlFor="name">Name</Label>
        <Input id="name" defaultValue="Jane Doe" />
      </div>
      <div className="space-y-1">
        <Label htmlFor="username">Username</Label>
        <Input id="username" defaultValue="@janedoe" />
      </div>
    </div>
    <DialogFooter>
      <DialogClose>
        <Button variant="outline">Cancel</Button>
      </DialogClose>
      <Button>Save changes</Button>
    </DialogFooter>
  </DialogContent>
</Dialog>

Controlled dialog#

TSX

import { useState } from 'react';

function ControlledDialog() {
  const [open, setOpen] = useState(false);

  async function handleSave() {
    await saveData();
    setOpen(false);
  }

  return (
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogTrigger>
        <Button>Open</Button>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Confirm action</DialogTitle>
          <DialogDescription>
            This will apply changes to all selected items.
          </DialogDescription>
        </DialogHeader>
        <DialogFooter>
          <Button variant="outline" onClick={() => setOpen(false)}>Cancel</Button>
          <Button onClick={handleSave}>Confirm</Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

Without close button#

Pass showCloseButton={false} to hide the default X button in the corner:

TSX

<DialogContent showCloseButton={false}>
  <DialogHeader>
    <DialogTitle>Processing...</DialogTitle>
  </DialogHeader>
  <div className="flex justify-center py-4">
    <Spinner size="lg" />
  </div>
</DialogContent>

Large content dialog#

TSX

<DialogContent className="max-w-2xl">
  <DialogHeader>
    <DialogTitle>Terms of Service</DialogTitle>
  </DialogHeader>
  <ScrollArea className="h-64">
    <div className="space-y-4 text-sm">
      {/* long content */}
    </div>
  </ScrollArea>
  <DialogFooter>
    <DialogClose>
      <Button variant="outline">Decline</Button>
    </DialogClose>
    <Button>Accept</Button>
  </DialogFooter>
</DialogContent>

Sub-components#

ComponentDescription
DialogRoot component. Manages open state.
DialogTriggerButton or element that opens the dialog. Renders as its child automatically for ux components (Button, Badge, ...) and intrinsic elements, so no asChild is needed; pass asChild only for other ref-forwarding elements. See Triggers and asChild.
DialogPortalRenders dialog outside the DOM tree. Used internally.
DialogOverlaySemi-transparent backdrop using the --backdrop CSS token. Used internally.
DialogContentThe dialog panel itself. Contains all visible content.
DialogHeaderTop section with consistent spacing for title/description.
DialogTitleAccessible dialog title (required for a11y).
DialogDescriptionSupporting text below the title.
DialogFooterBottom section, flex row right-aligned for action buttons.
DialogCloseButton that closes the dialog. Use asChild to render as any element.

DialogContent Props

PropTypeDefaultDescription
showCloseButtonbooleantrueShows or hides the default close (X) button in the top-right corner.
classNamestring—Additional CSS classes. Use to change max-width.
onOpenAutoFocus(e: Event) => void—Override default focus behavior on open.

Was this page helpful?