Docs·Modal

Modal

An accessible modal with focus trapping, focus restoration, nested Escape handling, scroll locking, responsive sizes, optional close control, and flexible footer alignment.

Installation

$pnpm dlx shadcn@latest add @spiderui/modal

Usage

API Reference

PropTypeDefault
openControls modal visibility.
boolean—
onCloseCalled by Escape, backdrop, and close-button actions.
() => void—
titleRequired accessible modal title.
ReactNode—
descriptionOptional description linked to the dialog.
ReactNode—
childrenScrollable modal body content.
ReactNode—
footerFooter actions.
ReactNode—
footerAlignmentAligns all actions right or separates first and last actions.
"right" | "split""right"
sizeSets modal maximum width.
"sm" | "md" | "lg""md"
showCloseShows or hides the top close button.
booleantrue
closeOnEscapeAllows Escape to close the topmost modal.
booleantrue
closeOnBackdropAllows pointer clicks that start and end outside to close.
booleantrue
lockScrollLocks document scrolling while open.
booleantrue
initialFocusRefElement focused when the modal opens.
RefObject<HTMLElement>—
maxHeightOverrides the modal maximum height.
string"min(78vh, 620px)"

Click on the icon in the top right of the example preview to view the source code for specific variants.

Keep in mind

This component is inspired by various open-source projects and patterns. Please verify licenses and implementation details before using in production.

Have any questions?
Contact on@ctrlcat0x
import { Modal } from "@/components/ui/modal"
export function DeleteProject() {
  const [open, setOpen] = useState(false)
  const cancelRef = useRef<HTMLButtonElement>(null)

  return (
    <>
      <Button onClick={() => setOpen(true)}>Delete project</Button>
      <Modal
        open={open}
        onClose={() => setOpen(false)}
        initialFocusRef={cancelRef}
        title="Delete atlas-edge?"
        description="This removes the project and cannot be undone."
        size="md"
        footerAlignment="right"
        footer={
          <>
            <Button ref={cancelRef} variant="outline">Cancel</Button>
            <Button variant="destructive">Delete</Button>
          </>
        }
      >
        Four deployments and one custom domain are attached.
      </Modal>
    </>
  )
}