Modal
Modals are used to display content in a layer above the main page. They block interaction with the rest of the page until dismissed. Use modals for confirmations, forms, or detailed content that requires focused user attention.
import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from "@skedulo/breeze-ui-react";Usage Guidance
When to use
- +Collect user input via forms that need focused attention.
- +Display detailed content that would clutter the main page.
- +Confirm destructive or important actions before proceeding.
When not to use
- −For simple yes/no confirmations — use ConfirmationDialog instead.
- −For supplementary info on hover — use Tooltip or Popover.
- −For page-level navigation — use Tabs or separate routes.
Examples
Code Samples
Basic Modal
A modal with a header, body content, and footer actions using the left and right props on ModalFooter.
import { useState } from "react";
import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from "@skedulo/breeze-ui-react";
export default function BasicModal() {
const [open, setOpen] = useState(false);
return (
<>
<Button onClick={() => setOpen(true)}>Open Modal</Button>
<Modal open={open} onClose={() => setOpen(false)}>
<ModalHeader>Confirm Assignment</ModalHeader>
<ModalBody>
<p>Are you sure you want to assign this job to Sarah Connor?</p>
<p className="mt-2 text-gray-500">
This will send a notification to the resource.
</p>
</ModalBody>
<ModalFooter
left={
<Button buttonType="transparent" onClick={() => setOpen(false)}>
Cancel
</Button>
}
right={
<Button buttonType="primary" onClick={() => setOpen(false)}>
Confirm
</Button>
}
/>
</Modal>
</>
);
}Small Confirmation Modal
A small modal used for delete confirmations or simple decisions.
import { useState } from "react";
import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from "@skedulo/breeze-ui-react";
export default function SmallModal() {
const [open, setOpen] = useState(false);
return (
<>
<Button onClick={() => setOpen(true)}>Delete Item</Button>
<Modal size="small" open={open} onClose={() => setOpen(false)}>
<ModalHeader>Delete Item</ModalHeader>
<ModalBody>
<p>Are you sure you want to delete this item? This action cannot be undone.</p>
</ModalBody>
<ModalFooter
left={
<Button buttonType="transparent" onClick={() => setOpen(false)}>
Cancel
</Button>
}
right={
<Button buttonType="primary" onClick={() => setOpen(false)}>
Delete
</Button>
}
/>
</Modal>
</>
);
}Large Modal with Scrollable Body
A large modal with scrollable body content for detailed views or long forms. Set the scrollable prop on ModalBody to enable scrolling within the modal.
import { useState } from "react";
import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from "@skedulo/breeze-ui-react";
export default function LargeModal() {
const [open, setOpen] = useState(false);
return (
<>
<Button onClick={() => setOpen(true)}>Open Large Modal</Button>
<Modal size="large" open={open} onClose={() => setOpen(false)}>
<ModalHeader>Detailed View</ModalHeader>
<ModalBody scrollable>
<p>This is a large modal with scrollable content.</p>
<p>Content that exceeds the available height will scroll within the modal.</p>
</ModalBody>
<ModalFooter
right={
<Button buttonType="primary" onClick={() => setOpen(false)}>
Done
</Button>
}
/>
</Modal>
</>
);
}Modal without Close Button
A modal with noClose that hides the header close button, requiring the user to interact with footer actions to dismiss.
import { useState } from "react";
import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from "@skedulo/breeze-ui-react";
export default function NoCloseModal() {
const [open, setOpen] = useState(false);
return (
<>
<Button onClick={() => setOpen(true)}>Open Required Action</Button>
<Modal size="small" open={open} noClose onClose={() => setOpen(false)}>
<ModalHeader>Required Action</ModalHeader>
<ModalBody>
<p>This modal has no close button. You must interact with the actions below.</p>
</ModalBody>
<ModalFooter
right={
<Button buttonType="primary" onClick={() => setOpen(false)}>
I Understand
</Button>
}
/>
</Modal>
</>
);
}Guidelines
Do
- ✓Always provide an onClose handler — modals must be dismissible.
- ✓Use ModalHeader, ModalBody, and ModalFooter for consistent structure.
- ✓Put the primary action on the right side of ModalFooter and cancel on the left.
- ✓Use size='small' for confirmations, 'medium' for forms, 'large' for complex content.
- ✓Use ModalBody scrollable prop when content may exceed viewport height.
Don't
- ✗Don't nest modals inside modals.
- ✗Don't use noClose without providing an alternative way to dismiss.
- ✗Don't put critical navigation inside modals — users expect to return to the page.
- ✗Don't use modals for content that should be part of the page flow.
- ✗Don't leave modals open after the action is complete — close them in the success handler.
Proposed Modifications
XL Size
An extra-large modal size that fills the majority of the viewport with 50px padding on all sides. Designed for complex workflows, data-heavy views, multi-step forms, or content that benefits from maximum screen real estate while still maintaining the modal interaction pattern (backdrop, header/footer, dismissibility). Usage: <Modal size="xlarge"> — the dialog expands to fill the available space minus 50px on each edge, with a scrollable body to handle overflow.
import { useState } from "react";
import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from "@skedulo/breeze-ui-react";
export default function XLargeModal() {
const [open, setOpen] = useState(false);
return (
<>
<Button onClick={() => setOpen(true)}>Open XL Modal</Button>
<Modal size="xlarge" open={open} onClose={() => setOpen(false)}>
<ModalHeader>Data Explorer</ModalHeader>
<ModalBody scrollable>
{/* Full-width content: data tables, multi-column layouts, dashboards */}
<p>This modal fills the viewport with 50px padding on all sides.</p>
</ModalBody>
<ModalFooter
left={
<Button buttonType="transparent" onClick={() => setOpen(false)}>
Close
</Button>
}
right={
<Button buttonType="primary" onClick={() => setOpen(false)}>
Save Changes
</Button>
}
/>
</Modal>
</>
);
}API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| open* | boolean | false | Controls whether the modal is visible. |
| onClose* | () => void | — | Callback fired when the modal requests to be closed (e.g. clicking the close button or the backdrop). |
| size | "small" | "medium" | "large" | "xlarge" | "medium" | Controls the width of the modal dialog. Use small for confirmations, medium for standard forms, large for complex content, and xlarge (proposed) for full-page modal experiences with 50px padding on all sides. |
| noClose | boolean | false | When true, hides the close button in the modal header. The user must interact with footer actions to dismiss the modal. |