Modal
Centered dialog over a dimmed backdrop with header, body, and footer slots.
Component behavior
Modal is the blocking dialog: a dimmed backdrop makes the page behind it inert until the user commits or cancels. Because it interrupts the page, use it only when the interruption is warranted.
- Self-contained create, rename, or configuration tasks with confirm and cancel actions.
- Content requiring a dialog without a separate page route.
- Tasks that must block interaction with the underlying page.
Drawer: record editing must retain the background list.
AlertDialog: a destructive action requires confirmation without backdrop dismissal.
PopoverPanel: a nonmodal panel belongs beside one control.
A route: the task requires a separate URL or extensive content.
Props
Modal extends HTMLAttributes<HTMLDivElement>. Escape and backdrop click close it unless closeOnBackdrop is off.
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Whether the modal is visible. |
onClose | () => void | — | Called on Escape or backdrop click. |
width | number | 440 | Panel width in px. |
closeOnBackdrop | boolean | true | Set false for destructive confirms. |
children | ReactNode | — | ModalHeader, ModalBody, ModalFooter. |
Sub-components
ModalHeader
Inherits PanelHeader. Adds sub and onClose.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Title. |
sub | ReactNode | — | Dim sub-label after the title. |
onClose | () => void | — | Renders a close button at the trailing edge. |
subMono | boolean | — | Renders sub in mono at a smaller size. |
subPlacement | "inline" | "block" | "inline" | Stack sub beneath title when block. |
right | ReactNode | — | Right-aligned slot. |
closeLabel | string | — | Accessible label for the close button. |
density | PanelDensity | "default" | "compact" | "default" | "roomy". |
size | "md" | "lg" | "lg" | ModalHeader defaults to lg. |
plain | boolean | — | Removes the bottom border. |
banded | boolean | — | Tinted background band. |
ModalBody
Scrollable body region. Inherits PanelBody.
| Prop | Type | Default | Description |
|---|---|---|---|
density | PanelDensity | "default" | "compact" | "default" | "roomy". |
scroll | boolean | — | Makes the body the scrolling region (default true in ModalBody). |
children | ReactNode | — | Body content. |
ModalFooter
Right-aligned action row. Inherits PanelFooter.
| Prop | Type | Default | Description |
|---|---|---|---|
left | ReactNode | — | Left-aligned slot (e.g. step hint). |
children | ReactNode | — | Action buttons (right-aligned). |
density | PanelDensity | "default" | "compact" | "default" | "roomy". |
Examples
Live
Basic usage
import {
Modal,
ModalHeader,
ModalBody,
ModalFooter,
Button,
} from "@solarius/onset";
import { useState } from "react";
function Example() {
const [open, setOpen] = useState(false);
return (
<>
<Button onClick={() => setOpen(true)}>Open modal</Button>
<Modal open={open} onClose={() => setOpen(false)}>
<ModalHeader onClose={() => setOpen(false)}>
Account settings
</ModalHeader>
<ModalBody>
<p>Configure your account preferences here.</p>
</ModalBody>
<ModalFooter>
<Button variant="ghost" onClick={() => setOpen(false)}>
Cancel
</Button>
<Button variant="primary" onClick={() => setOpen(false)}>
Save
</Button>
</ModalFooter>
</Modal>
</>
);
}With sub-label
<Modal open={open} onClose={onClose}>
<ModalHeader sub="Record #456" subMono onClose={onClose}>
Edit deployment
</ModalHeader>
<ModalBody>…</ModalBody>
<ModalFooter left="Step 2 of 3">
<Button variant="ghost" onClick={onClose}>
Cancel
</Button>
<Button variant="primary" onClick={onClose}>
Continue
</Button>
</ModalFooter>
</Modal>Destructive confirm (closeOnBackdrop=false)
<Modal open={open} onClose={onClose} closeOnBackdrop={false}>
<ModalHeader onClose={onClose}>Delete cluster?</ModalHeader>
<ModalBody>
<p>
This action is irreversible. All associated resources will be deleted.
</p>
</ModalBody>
<ModalFooter>
<Button variant="ghost" onClick={onClose}>
Cancel
</Button>
<Button variant="danger" onClick={onClose}>
Delete
</Button>
</ModalFooter>
</Modal>