Overlays
Modal
YunUI's controlled modal — a portalled card with title, scrollable body and footer.
YunUI's own controlled modal — a portalled, centered card with a header (title + optional subtitle), a scrollable body, and an optional footer. It locks body scroll, closes on backdrop click or the Escape key, animates open and closed, and is SSR-safe. Unlike the Radix Dialog, you own the open state via isOpen + onClose.
Import
import { Modal } from "@yuhuanowo/yunui";
Basic
A Modal is fully controlled: keep its isOpen in state and pass onClose to flip it back. The example below wires a trigger button to local state.
Controlled modal
"use client";
import { useState } from "react";
import { Modal, Button } from "@yuhuanowo/yunui";
export function ModalDemo() {
const [open, setOpen] = useState(false);
return (
<>
<Button onClick={() => setOpen(true)}>Open modal</Button>
<Modal
isOpen={open}
onClose={() => setOpen(false)}
title="Invite your team"
subtitle="They'll get an email with a join link."
size="md"
footer={
<div className="flex justify-end gap-3">
<Button variant="secondary" onClick={() => setOpen(false)}>Cancel</Button>
<Button onClick={() => setOpen(false)}>Send invites</Button>
</div>
}
>
<p className="text-sm text-muted-foreground">
Enter the email addresses of the people you want to invite.
</p>
</Modal>
</>
);
}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| children* | ReactNode | — | Modal content |
| className | string | — | Additional CSS classes |
| footer | ReactNode | — | Optional footer content |
| isClosing | boolean | — | Whether modal is in closing animation state |
| isOpen* | boolean | — | Whether the modal is open |
| maxHeight | string | 85vh | Custom max-height override |
| onBackdropClick | (() => void) | — | Called when backdrop is clicked (defaults to onClose) |
| onClose* | () => void | — | Callback when modal should close |
| setIsClosing | ((closing: boolean) => void) | — | Callback to set closing state |
| showCloseButton | boolean | true | Whether to show the close button |
| showUnsavedBadge | boolean | false | Whether to show unsaved changes badge |
| size | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "4xl" | "5xl" | "6xl" | "full" | lg | Modal size |
| subtitle | string | — | Optional subtitle displayed below title |
| title* | string | — | Modal title (required for accessibility) |