@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

Prop Type Default Description
open boolean Controls visibility. Required.
onClose / @close () => void Called when the user dismisses the modal (Escape key or backdrop click).
size "sm" | "md" | "lg" | "full" "md" Modal width.
closeOnBackdrop boolean true Close when clicking the backdrop.
closeOnEsc boolean true Close when pressing Escape.
class / className string Additional CSS class on the modal panel.