Navigation
Inputs & Forms
Selection
Containers & Overlays
Overview
A Modal opens a dialog above the page and a blanket. The focus stays within the dialog until it is closed with an action, the close button or Escape.
"use client";import {Button, IconErrorWarning, Modal, ModalActions, ModalTitle} from "@brynlabs/fusion-ui";import React, {useState} from "react";export const ModalExample = () => {const [open, setOpen] = useState(false);return (<div style={{display: "grid", gap: "1rem", placeItems: "start"}}><Button color={"critical"} onClick={() => setOpen(true)}>Delete project</Button><Modalopen={open}size={"small"}onAbort={() => setOpen(false)}modalTitle={<ModalTitleicon={<span style={{color: "var(--color--critical-500)"}}><IconErrorWarning /></span>}onAbort={() => setOpen(false)}>Delete project?</ModalTitle>}actions={<ModalActions><Button color={"critical"} onClick={() => setOpen(false)}>Delete project</Button><Button color={"neutral"} onClick={() => setOpen(false)}>Keep project</Button></ModalActions>}>The project, its tasks and files are deleted for everyone. This can’t be undone.</Modal></div>);};
Sizes
size sets the width: small for confirmations, medium and large (the default) for short forms, extraLarge for wide content such as a table. On narrow screens the modal takes the width of the viewport.
"use client";import {Button,ButtonGroup,Modal,ModalActions,ModalProps,ModalTitle,} from "@brynlabs/fusion-ui";import React, {useState} from "react";type Size = NonNullable<ModalProps["size"]>;const sizes: {size: Size; label: string; width: string}[] = [{size: "small", label: "Small", width: "25rem"},{size: "medium", label: "Medium", width: "37.5rem"},{size: "large", label: "Large", width: "50rem"},{size: "extraLarge", label: "Extra large", width: "62.5rem"},];export const ModalSizesExample = () => {const [size, setSize] = useState<Size>("small");const [open, setOpen] = useState(false);const current = sizes.find(s => s.size === size)!;return (<div style={{display: "grid", gap: "1rem", placeItems: "start"}}><ButtonGroup>{sizes.map(s => (<Buttonkey={s.size}color={"neutral"}onClick={() => {setSize(s.size);setOpen(true);}}>{s.label}</Button>))}</ButtonGroup><Modalopen={open}size={size}onAbort={() => setOpen(false)}modalTitle={<ModalTitle onAbort={() => setOpen(false)}>{current.label} modal</ModalTitle>}actions={<ModalActions><Button onClick={() => setOpen(false)}>Close</Button></ModalActions>}>This modal is {current.width} wide. On narrow screens it shrinks to the width of theviewport.</Modal></div>);};
Long content
With the default heightMode maxHeight the modal fits into the viewport and its content scrolls, the title and the actions stay visible. With overflow the modal grows with its content and scrolls with the page.
"use client";import {Button,ButtonGroup,Modal,ModalActions,ModalProps,ModalTitle,} from "@brynlabs/fusion-ui";import React, {useState} from "react";type HeightMode = NonNullable<ModalProps["heightMode"]>;const terms = Array.from({length: 12}, (_, i) => i + 1);export const ModalHeightExample = () => {const [heightMode, setHeightMode] = useState<HeightMode>("maxHeight");const [open, setOpen] = useState(false);const show = (mode: HeightMode) => {setHeightMode(mode);setOpen(true);};return (<div style={{display: "grid", gap: "1rem", placeItems: "start"}}><ButtonGroup><Button color={"neutral"} onClick={() => show("maxHeight")}>Max height</Button><Button color={"neutral"} onClick={() => show("overflow")}>Overflow</Button></ButtonGroup><Modalopen={open}size={"medium"}heightMode={heightMode}onAbort={() => setOpen(false)}modalTitle={<ModalTitle onAbort={() => setOpen(false)}>Terms of service</ModalTitle>}actions={<ModalActions><Button onClick={() => setOpen(false)}>Accept terms</Button><Button color={"neutral"} onClick={() => setOpen(false)}>Decline</Button></ModalActions>}><div style={{display: "grid", gap: "1rem"}}>{terms.map(term => (<p key={term}>{term}. Lorem ipsum dolor sit amet, consectetur adipisicing elit. In praesentiumrepellat tempore? Ea eaque earum facere iure laboriosam molestias nulla officiispariatur perspiciatis ratione! Assumenda doloremque fuga magni numquam quam?</p>))}</div></Modal></div>);};

