@usevyre/react@usevyre/vue

Modal

An accessible dialog overlay rendered via Teleport / Portal to<body>. Traps focus, closes on Escape, and blocks background scroll.


Basic

import { useState } from "react";
import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from "@usevyre/react";

function Example() {
  const [open, setOpen] = useState(false);
  return (
    <>
      <Button variant="accent" onClick={() => setOpen(true)}>Open modal</Button>
      <Modal open={open} onClose={() => setOpen(false)}>
        <ModalHeader>
          <h2>Confirm deletion</h2>
        </ModalHeader>
        <ModalBody>
          <p>This action cannot be undone.</p>
        </ModalBody>
        <ModalFooter>
          <Button variant="ghost" onClick={() => setOpen(false)}>Cancel</Button>
          <Button variant="danger">Delete</Button>
        </ModalFooter>
      </Modal>
    </>
  );
}

Sizes

Use the size prop to control the modal panel width."full" fills the entire viewport.

<Modal open={open} onClose={close} size="sm">...</Modal>
<Modal open={open} onClose={close} size="md">...</Modal>  {/* default */}
<Modal open={open} onClose={close} size="lg">...</Modal>
<Modal open={open} onClose={close} size="full">...</Modal>

Accessibility

Modal renders role="dialog" with aria-modal="true". Focus is trapped inside and returns to the trigger element on close. Keyboard: Escape closes, Tab cycles through focusable elements.

Props

Props

PropTypeDefaultDescription
openbooleanControls visibility. Required.
onClose / @close() => voidCalled when the user dismisses the modal (Escape key or backdrop click).
size"sm" | "md" | "lg" | "full""md"Modal width.
closeOnBackdropbooleantrueClose when clicking the backdrop.
closeOnEscbooleantrueClose when pressing Escape.
class / classNamestringAdditional CSS class on the modal panel.