Skip to content

Dialog

A modal window on top of the page that asks for a decision or collects input. DialogTrigger opens it and DialogClose closes it.

Dialog.tsx
import {
  Dialog,
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
  TextField
} from 'alinea/components'

export function DialogExample() {
  return (
    <Dialog>
      <DialogTrigger variant="outline">Rename entry</DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Rename entry</DialogTitle>
          <DialogDescription>
            The URL of the entry stays the same.
          </DialogDescription>
        </DialogHeader>
        <TextField label="Title" defaultValue="Summer collection" autoFocus />
        <DialogFooter>
          <DialogClose variant="ghost">Cancel</DialogClose>
          <DialogClose color="primary">Save</DialogClose>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}

Confirm a destructive action

Use role="alertdialog" for a decision editors have to make. With dismissable={false} a click outside the dialog doesn't close it.

DialogAlert.tsx
import {
  Dialog,
  DialogClose,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger
} from 'alinea/components'
import {IcRoundDelete} from 'alinea/dashboard/icons'

export function DialogAlertExample() {
  return (
    <Dialog>
      <DialogTrigger color="destructive" variant="outline" icon={IcRoundDelete}>
        Delete
      </DialogTrigger>
      <DialogContent
        role="alertdialog"
        dismissable={false}
        showCloseButton={false}
      >
        <DialogHeader>
          <DialogTitle>Delete “Linen shirt”?</DialogTitle>
          <DialogDescription>
            The entry and its translations are removed. This can’t be undone.
          </DialogDescription>
        </DialogHeader>
        <DialogFooter>
          <DialogClose variant="ghost">Keep it</DialogClose>
          <DialogClose color="destructive">Delete entry</DialogClose>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}

Controlled

Pass open and onOpenChange to open a dialog from anywhere, and close it once a change is saved. useDialog gives the content of a dialog its open state and a close function.

DialogForm.tsx
import {
  Button,
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  TextField
} from 'alinea/components'
import {useState} from 'react'

export function DialogFormExample() {
  const [open, setOpen] = useState(false)
  const [name, setName] = useState('Oak & Loom')
  const [draft, setDraft] = useState(name)
  return (
    <>
      <Button onClick={() => setOpen(true)}>Site name: {name}</Button>
      <Dialog open={open} onOpenChange={setOpen}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>Site settings</DialogTitle>
          </DialogHeader>
          <TextField label="Site name" value={draft} onValueChange={setDraft} />
          <DialogFooter>
            <Button variant="ghost" onClick={() => setOpen(false)}>
              Cancel
            </Button>
            <Button
              color="primary"
              onClick={() => {
                setName(draft)
                setOpen(false)
              }}
            >
              Save
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  )
}

Props

<Dialog>

PropTypeDefaultDescription
openbooleanDefault –
defaultOpenbooleanDefault –
onOpenChange(open: boolean) => voidDefault –

<DialogTrigger>

Accepts every prop of Button.

<DialogContent>

PropTypeDefaultDescription
role'dialog' | 'alertdialog'Default –
size'default' | 'lg' | 'full'Default 'default'default fits its content up to a narrow width, lg is a fixed wide dialog and full fills the viewport (minus a margin), defaults to default
dismissablebooleanDefault trueClose the dialog when clicking outside of it, defaults to true
showCloseButtonbooleanDefault trueDefaults to true

Also accepts className and style, id and aria-* labelling attributes and data-* attributes.

<DialogHeader>

Accepts every prop of a <div> element.

<DialogTitle>

PropTypeDefaultDescription
children*ReactNodeDefault –

Also accepts className and style.

<DialogDescription>

Accepts every prop of a <p> element.

<DialogFooter>

Accepts every prop of a <div> element.

<DialogClose>

Closes the surrounding Dialog or Popover when pressed

Accepts every prop of Button.

useDialog()

The open state of the surrounding Dialog or Popover, to close it from within its content

Accessibility

Focus moves into the dialog when it opens and returns to the trigger when it closes. Focus stays inside while it is open, Escape closes it and the page behind it is hidden from screen readers.