Behive Tech Component Registry

Modal

v0.4.1Stable

A `Card` centered in the viewport with a dimmed backdrop that blocks interaction with the rest of the page, built on [Radix `Dialog`](https://www.radix-ui.com/primitives/docs/components/dialog) for focus trapping, Escape-to-close, and outside-click-to-close. It has no opinion on what goes inside the panel — an optional `title` renders a header with a close button, otherwise just the `children` are shown.

pnpm add @behivetech/atoms.modal

A Card centered in the viewport with a dimmed backdrop that blocks interaction with the rest of the page, built on Radix Dialog for focus trapping, Escape-to-close, and outside-click-to-close. It has no opinion on what goes inside the panel — an optional title renders a header with a close button, otherwise just the children are shown.

size="fullscreen" drops the Card and fills the viewport on the lowest surface tier: a top bar holds the title and the close button and children fill the rest. It is for content that needs the whole screen, such as a lightbox. Pass onCloseAutoFocus to choose where focus lands when the modal closes, and closeLabel to translate the close button's name.

Pass footer for the dialog's action buttons: they sit below the content and stay visible while the content scrolls under the panel's height cap, so a long form never pushes Save off the screen. It is ignored by size="fullscreen".

For a panel that docks to an edge of the viewport instead — optionally non-blocking — use @behivetech/atoms.drawer.

Usage

Open in new tab

Properties

Modal props

PropTypeDefaultDescription
children*ReactNode—Dialog content
onClose*() => void—Called when the modal is dismissed (backdrop click, Escape, or the close button)
classNamestring—Additional class names to merge with the component root element
closeLabelstringCloseAccessible name of the close button, for translation; defaults to "Close"
footerReactNode—Action buttons kept below the content. They stay visible while the content scrolls under the panel's height cap, so a long form never pushes Save off the screen. Ignored by `size="fullscreen"`, which has no panel.
headingLevel1 | 2 | 3 | 4 | 5 | 6—Which heading tag wraps `title` — same values as `Card`'s `headingLevel` prop
iconReactNode—Optional icon rendered before the title in the header; ignored if `title` is omitted
onCloseAutoFocus((event: Event) => void)—Called when focus is about to return to the element that was focused before the modal opened; call `event.preventDefault()` to move focus elsewhere.
padding"sm" | "md" | "none" | "lg"—Internal padding of the panel body — same values as `Card`'s `padding` prop
size"default" | "fullscreen"default`default` is a `Card` panel centered in the viewport. `fullscreen` fills the viewport with no `Card` panel: a top bar holds the `title` and the close button and `children` fill the rest, for content such as a lightbox. Fullscreen ignores `icon`, `padding` and `headingLevel`, and its title is not a heading. The close button is always there, with or without a title.
titleReactNode—Optional header title; omit to render no header and no close button

Also accepts the native attributes of its root element (className, aria-*, event handlers, …).