Modal

Modal provides a way to add accessible labels to form elements.

Source
Theme Source
pnpm dlx dreamy add modal
export default function BasicModal() {
    const { isOpen, onClose, onOpen } = useControllable();
 
    return (
        <>
            <Button variant={"primary"} onClick={onOpen}>
                Open Modal
            </Button>
 
            <Modal.Root isOpen={isOpen} onClose={onClose}>
                <Modal.Overlay />
                <Modal.Content>
                    <Modal.Header>Modal Header</Modal.Header>
                    <Modal.CloseButton />
                    <Modal.Body>Modal Body</Modal.Body>
                    <Modal.Footer>
                        <Button onClick={onClose}>Close</Button>
                    </Modal.Footer>
                </Modal.Content>
            </Modal.Root>
        </>
    );
}
export function SizeModals() {
    const sizes = [
        "sm",
        "md",
        "lg",
        "xl",
        "2xl",
        "3xl",
        "4xl",
        "5xl",
        "6xl",
        "7xl",
        "8xl"
    ] as const;
 
    const ModalSize = useCallback(({ size }: { size: (typeof sizes)[number] }) => {
        const { isOpen, onClose, onOpen } = useControllable();
 
        return (
            <>
                <Button variant={"primary"} onClick={onOpen}>
                    Open {size} Modal
                </Button>
 
                <Modal.Root isOpen={isOpen} onClose={onClose} size={size}>
                    <Modal.Overlay />
                    <Modal.Content>
                        <Modal.Header>{size} Modal</Modal.Header>
                        <Modal.CloseButton />
                        <Modal.Body>This is a {size} modal!</Modal.Body>
                        <Modal.Footer>
                            <Button onClick={onClose}>Close</Button>
                        </Modal.Footer>
                    </Modal.Content>
                </Modal.Root>
            </>
        );
    }, []);
 
    return (
        <Flex wrapped gap={2}>
            {sizes.map((size) => (
                <ModalSize size={size} key={"modal-size-" + size} />
            ))}
        </Flex>
    );
}
  • inside: The modal body will scroll inside the modal.
export default function ScrollBehaviorModal() {
	const { isOpen, onClose, onOpen } = useControllable();
 
	return (
		<>
			<Button variant={"primary"} onClick={onOpen}>
				Open Modal
			</Button>
 
			<Modal.Root isOpen={isOpen} onClose={onClose} scrollBehavior={"inside"}>
				<Modal.Overlay />
				<Modal.Content>
					<Modal.Header>Modal Header</Modal.Header>
					<Modal.CloseButton />
					<Modal.Body>Modal Body</Modal.Body>
					<Modal.Footer>
						<Button onClick={onClose}>Close</Button>
					</Modal.Footer>
				</Modal.Content>
			</Modal.Root>
		</>
	);
}
  • outside: The modal body will scroll outside the modal. If your content is long and it bugs the modal position, ensure to set the placement="top" prop.
export function ScrollableOutsideModal() {
    const { isOpen, onClose, onOpen } = useControllable();
 
    return (
        <>
            <Button variant={"primary"} onClick={onOpen}>
                Open Modal
            </Button>
 
            <Modal.Root
                isOpen={isOpen}
                onClose={onClose}
                scrollBehavior="outside"
                placement="top"
                size={"lg"}
            >
                <Modal.Overlay />
                <Modal.Content>
                    <Modal.Header>Modal Header</Modal.Header>
                    <Modal.CloseButton />
                    <Modal.Body>
                        {[...Array(10)].map((_, i) => (
                            <LoremIpsum key={`ipsum-${i}`} p={1} />
                        ))}
                    </Modal.Body>
                    <Modal.Footer>
                        <Button onClick={onClose}>Close</Button>
                    </Modal.Footer>
                </Modal.Content>
            </Modal.Root>
        </>
    );
}

Sometimes you might want to place the modal on the top to avoid layout shifts.

export function PlacementModal() {
    const { isOpen, onClose, onOpen } = useControllable();
 
    return (
        <>
            <Button variant={"primary"} onClick={onOpen}>
                Open Modal
            </Button>
 
            <Modal.Root isOpen={isOpen} onClose={onClose} placement={"top"}>
                <Modal.Overlay />
                <Modal.Content>
                    <Modal.Header>Modal Header</Modal.Header>
                    <Modal.CloseButton />
                    <Modal.Body>Modal Body</Modal.Body>
                    <Modal.Footer>
                        <Button onClick={onClose}>Close</Button>
                    </Modal.Footer>
                </Modal.Content>
            </Modal.Root>
        </>
    );
}