Modal
Overlays

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.

Use cases
  • 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.
Alternatives

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.

ModalProps props
PropTypeDefaultDescription
openboolean—Whether the modal is visible.
onClose() => void—Called on Escape or backdrop click.
widthnumber440Panel width in px.
closeOnBackdropbooleantrueSet false for destructive confirms.
childrenReactNode—ModalHeader, ModalBody, ModalFooter.

Sub-components

ModalHeader

Inherits PanelHeader. Adds sub and onClose.

ModalHeaderProps extends PanelHeaderProps props
PropTypeDefaultDescription
childrenReactNode—Title.
subReactNode—Dim sub-label after the title.
onClose() => void—Renders a close button at the trailing edge.
subMonoboolean—Renders sub in mono at a smaller size.
subPlacement"inline" | "block""inline"Stack sub beneath title when block.
rightReactNode—Right-aligned slot.
closeLabelstring—Accessible label for the close button.
densityPanelDensity"default""compact" | "default" | "roomy".
size"md" | "lg""lg"ModalHeader defaults to lg.
plainboolean—Removes the bottom border.
bandedboolean—Tinted background band.

ModalBody

Scrollable body region. Inherits PanelBody.

ModalBodyProps extends PanelBodyProps props
PropTypeDefaultDescription
densityPanelDensity"default""compact" | "default" | "roomy".
scrollboolean—Makes the body the scrolling region (default true in ModalBody).
childrenReactNode—Body content.

ModalFooter

Right-aligned action row. Inherits PanelFooter.

ModalFooterProps extends PanelFooterProps props
PropTypeDefaultDescription
leftReactNode—Left-aligned slot (e.g. step hint).
childrenReactNode—Action buttons (right-aligned).
densityPanelDensity"default""compact" | "default" | "roomy".

Examples

Live

Modal

Basic usage

ImportTSX
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

ModalHeader with subTSX
<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)

Alert-style modalTSX
<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>