COMPONENT
Modal
Overlay dialog for focused tasks. Supports ESC to close, click-outside, and body scroll lock.
Usage
import { Modal, ModalHeader, ModalBody, ModalFooter } from "@/components/ui";
import { Button } from "@/components/ui";
function DeleteConfirmation({ open, onClose, onConfirm }) {
return (
<Modal open={open} onClose={onClose} size="md">
<ModalHeader>
<h2 className="text-heading-lg">Confirmar exclusao</h2>
</ModalHeader>
<ModalBody>
<p className="text-body-md text-foreground-secondary">
Tem certeza que deseja excluir este membro?
Esta acao nao pode ser desfeita.
</p>
</ModalBody>
<ModalFooter>
<Button variant="outline" onClick={onClose}>Cancelar</Button>
<Button variant="danger" onClick={onConfirm}>Excluir</Button>
</ModalFooter>
</Modal>
);
}Sizes
| Size | Max Width | Use Case |
|---|---|---|
sm | 384px | Simple confirmations |
md | 512px | Forms, detail views |
lg | 672px | Complex forms, previews |
xl | 896px | Data-heavy content |
Interaction Behavior
- ESC key closes the modal
- Click outside (backdrop) closes the modal
- Body scroll is locked while modal is open
- Focus trap — add via your preferred focus-trap library
- Animation — backdrop fades in, panel scales in (200ms ease-out)
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| open* | boolean | — | Controls visibility |
| onClose* | () => void | — | Called on ESC or backdrop click |
| size | "sm" | "md" | "lg" | "xl" | "md" | Max width of the panel |
| children* | ReactNode | — | Modal content |
React Native
On mobile, Modal uses React Native's built-in Modal component withtransparent and animationType="fade". For bottom-anchored content, use BottomSheet instead — it supports swipe-to-dismiss via PanResponder.
Mobile — Modal
import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from "@/components/mobile";
<Modal visible={isOpen} onClose={close}>
<ModalHeader><Text style={textStyles["heading-lg"]}>Confirmar</Text></ModalHeader>
<ModalBody><Text>Tem certeza?</Text></ModalBody>
<ModalFooter>
<Button variant="outline" onPress={close}>Cancelar</Button>
<Button variant="danger" onPress={handleDelete}>Excluir</Button>
</ModalFooter>
</Modal>Mobile — BottomSheet
import { BottomSheet } from "@/components/mobile";
<BottomSheet visible={open} onClose={close} snapPoint={0.4}>
<Text>Swipe down to dismiss</Text>
</BottomSheet>