Dialog
A modal that stops the page for one question.
Overview
A confirmation or a short form the reader must answer before they go on.
Confirm
Do
import { useState } from "react";
import { Button, Dialog } from "@hackcove/ui";
function Example() {
const [open, setOpen] = useState(false);
return (
<>
<Button variant="outline" onClick={() => setOpen(true)}>
Delete build
</Button>
{open && (
<Dialog
title="Delete build"
description="This removes the build and every snapshot in it."
onClose={() => setOpen(false)}
footer={
<>
<Button variant="ghost" onClick={() => setOpen(false)}>
Cancel
</Button>
<Button tone="danger" onClick={() => setOpen(false)}>
Delete
</Button>
</>
}
/>
)}
</>
);
}Don't
import { useState } from "react";
import { Button, Dialog } from "@hackcove/ui";
function Example() {
const [open, setOpen] = useState(false);
return (
<>
<Button variant="outline" onClick={() => setOpen(true)}>
Delete build
</Button>
{open && (
<Dialog
title="Are you sure?"
onClose={() => setOpen(false)}
footer={
<Button tone="danger" onClick={() => setOpen(false)}>
Delete
</Button>
}
/>
)}
</>
);
}Notice
Do
Your review is saved.
import { Button, Callout, Stack } from "@hackcove/ui";
<Stack gap="sm">
<Button variant="outline">Save</Button>
<Callout tone="positive">Your review is saved.</Callout>
</Stack>Callout in the page, where it does not take the page away.Don't
import { useState } from "react";
import { Button, Dialog } from "@hackcove/ui";
function Example() {
const [open, setOpen] = useState(false);
return (
<>
<Button variant="outline" onClick={() => setOpen(true)}>
Save
</Button>
{open && (
<Dialog
title="Saved"
description="Your review is saved."
onClose={() => setOpen(false)}
footer={<Button onClick={() => setOpen(false)}>OK</Button>}
/>
)}
</>
);
}Usage
- Render it only while it is open:
{open && <Dialog … onClose={() => setOpen(false)} />}. It opens itself on mount. - A
titlethat names the action, adescriptionwith the consequence, and the actions infooter: Cancel asvariant="ghost"first, then the one action,tone="danger"when it destroys something. size="sm"is a short list;md, the default, holds a form. A submit button in the footer reaches a form in the body with itsformattribute.- One text field is a
FieldDialog. A record or a long form is aDrawer. A message that needs no answer is aCallout.
Accessibility
- A Dialog is the browser's own
<dialog>opened withshowModal(): the page behind goes inert, focus stays inside it and Esc closes it. - It is named by its
title, anh2, througharia-labelledby. - A click on the backdrop closes it, and so does a submit of a
<form method="dialog">; every close callsonClose. - The browser focuses the first focusable element in it when it opens; put
autoFocuson the button that should have focus first.
API
Dialog
A modal on the browser's own <dialog>: it is opened with showModal() on mount, so render it only while it is open. The page behind goes inert, Esc closes it and focus stays inside; a click on the backdrop (the <dialog> element itself, not its contents) closes it too.
description- Type
ReactNode
footerActions under the body, right-aligned. A submit button here can reach a form in the body with its form attribute.
- Type
ReactNode
onClose requiredCalled when the dialog closes: Esc, a click on the backdrop, or a <form method="dialog"> submit.
- Type
() => void
sizesm is a list; md (the default) holds a form.
- Type
"sm" | "md"- Default
md
title requiredThe dialog's accessible name, shown as its heading.
- Type
ReactNode