Modal
An overlay dialog that appears on top of the main content to focus user attention.
Usage
Use standalone.
<Modal {...props}>Content</Modal>Anatomy
The class attribute values represent part names. Other attributes represent their corresponding props.
<dialog class="whole" {...rest} aria-label>
{children}
</dialog>Props
| Name | Type | Default | Description |
|---|---|---|---|
children* | Snippet | - | Modal content; receives the variant as its argument |
open | boolean | false | Bindable open state |
closable | boolean | true | Whether light dismiss is enabled; false blocks both backdrop-click and Escape |
duration | number | 200 | Open/close animation timing in ms, published as the --svs-duration custom property |
cssvar | Record | - | Renames the published animation-timing custom property; cssvar.duration makes the Modal read --svs-duration from a caller-named token |
ariaLabel | string | - | Accessible label for the dialog |
element | HTMLDialogElement | - | Bindable root element |
styling | SVSClass | - | Styling override |
variant | SVSVariant | NEUTRAL | Modal variant |
* required. Other HTMLDialogAttributes are passed to <dialog> via rest props; class is merged onto the root.
Modal is a native modal <dialog> opened with showModal(): focus is trapped and background content is inert while open, and page scroll is locked with :root:has(dialog[open]).
Styling
Content renders directly inside the <dialog> (whole part), so background and padding belong on whole.
To learn more, see Styling.
Variant Management
No automatic switching.
Default Class Name
svs-modal
Behavior
Open/close animation timing is published as --svs-duration for caller CSS; cssvar.duration renames it (caller then owns reduced-motion for that token).
Accessibility
ARIA Roles and Attributes
The component applies these automatically:
- Dialog (
whole<dialog>):aria-labelfrom theariaLabelprop.
Provide an accessible name yourself because there is no built-in visible label. Pass ariaLabel, or pass aria-labelledby through the rest props. The managed aria-label attribute is omitted from ModalProps and cannot be passed as aria-label.
Standards Basis
Modal is built on a native <dialog> opened with showModal(), so keyboard and assistive-technology support follows the browser standard for modal dialogs. See the Concepts standards-first guidance for the library's approach. When closable is false, the component prevents the native Escape light-dismiss; note that a modal dialog that cannot be dismissed with Escape runs contrary to the WAI-ARIA authoring-practices recommendation for dialogs, so use it deliberately.
Exports
Types
interface ModalProps extends Omit<HTMLDialogAttributes, "children" | "style" | "aria-label"> {
children: Snippet<[string]>; // Snippet<[variant]>
open?: boolean; // bindable (false)
closable?: boolean; // (true)
duration?: number; // (200)
cssvar?: Partial<Record<ModalCssVar, string>>;
ariaLabel?: string;
element?: HTMLDialogElement; // bindable
styling?: SVSClass;
variant?: SVSVariant; // (VARIANT.NEUTRAL)
// other HTMLDialogAttributes are passed to <dialog> via ...rest; `class` is merged onto root
// style is component-owned (omitted)
}
type ModalReqdProps = "children";
type ModalBindProps = "open" | "element";
type ModalCssVar = "duration";Others
No additional exports are available.
Examples
The example code uses Tailwind CSS along with SVSClass.