components

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
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

Proposed

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

PropTypeDefaultDescription
open*booleanfalseControls whether the modal is visible.
onClose*() => voidCallback 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.
noClosebooleanfalseWhen true, hides the close button in the modal header. The user must interact with footer actions to dismiss the modal.