Skip to content
Aggarly OS
  • Getting Started
    • Introduction
  • Foundations
    • Colors
    • Spacing
    • Radius
    • Typography
    • Shadows
    • Z-Index
    • Gradients
    • Tokens
    • RTL & Direction
    • Theming
  • Layout
    • Containers
    • Grid System
    • Layout Utilities
  • Components
    • Alerts
    • Avatars
    • Buttons
    • Button Group
    • Badges
    • Inputs
    • Select
    • Checkbox
    • Counters-timers
    • Radio
    • Switch
    • Stepper
    • Select-pro
    • Cards
    • Modals
    • Dropdown
    • Popover
    • Tooltip
    • Accordion
    • Breadcrumb
    • Tabs
    • Navbar
    • List Group
    • Toasts
    • Skeleton
    • Pagination
    • Progress
    • Table
    • Icons
    • Form
    • Ribbons
    • Spinner
    • Offcanvas
    • Feedback
    • Grid
    • Data UI
  • Data UI
    • Overview
  • Platform
    • Reference DataCore
  • Widgets
    • KPI
    • Analytics
    • Behavior
  • Brand
    • Logo
    • Brand Usage
Components/Modals

Modals

Modals surface critical information or confirm important actions without navigating away from the current context. In Aggarly Platform they must be calm, accessible, and consistent: strong focus management, token-driven surfaces, clear headers/footers, and predictable sizing across responsive breakpoints.

Confirmation Modal

A focused confirmation pattern with explicit actions. Backdrop click and Escape close are supported by default.

Show code
Confirmation modal (JSX)
import { useState } from "react";
import { Modal } from "@/design-system/components/Modal";
import { Button } from "@/design-system/components/Button";

export function Example() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Button size="sm" variant="primary" onClick={() => setOpen(true)}>
        Open confirm modal
      </Button>

      <Modal
        open={open}
        onClose={() => setOpen(false)}
        title="End session?"
        showCloseButton
        footer={
          <>
            <Button size="sm" variant="ghost" onClick={() => setOpen(false)}>
              Cancel
            </Button>
            <Button size="sm" variant="danger" onClick={() => setOpen(false)}>
              End session
            </Button>
          </>
        }
      >
        <p>
          Are you sure you want to end this session? All unsaved notes will be lost.
        </p>
      </Modal>
    </>
  );
}

Form Modal With Inputs

Use for quick create/edit flows. The first field can receive focus via data-autofocus. Footer actions remain consistent with Buttons.

Show code
Form modal (JSX)
import { useState } from "react";
import { Modal } from "@/design-system/components/Modal";
import { Button } from "@/design-system/components/Button";
import { Input } from "@/design-system/components/Input";

export function Example() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Button size="sm" variant="primary" onClick={() => setOpen(true)}>
        Add student
      </Button>

      <Modal
        open={open}
        onClose={() => setOpen(false)}
        title="Add student"
        scrollable
        showCloseButton={false}
        footer={
          <>
            <Button size="sm" variant="ghost" onClick={() => setOpen(false)}>
              Cancel
            </Button>
            <Button size="sm" variant="primary" onClick={() => setOpen(false)}>
              Save
            </Button>
          </>
        }
      >
        <form className="modal-form" onSubmit={(e) => e.preventDefault()}>
          <Input label="Student name" placeholder="Full name" data-autofocus />
          <Input label="Workspace member email" type="email" placeholder="name@domain.com" />
          <Input label="Notes" placeholder="Optional notes" />
        </form>
      </Modal>
    </>
  );
}

Scrollable Modal

For long content: audit logs, policy text, or multi-paragraph explanations. Header and footer use separators; body scrolls internally.

Show code
Scrollable modal (JSX)
import { useState } from "react";
import { Modal } from "@/design-system/components/Modal";
import { Button } from "@/design-system/components/Button";

export function Example() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Button size="sm" variant="outline" onClick={() => setOpen(true)}>
        Open scrollable modal
      </Button>

      <Modal
        open={open}
        onClose={() => setOpen(false)}
        title="Audit log"
        scrollable
        size="lg"
        showCloseButton
        footer={
          <Button size="sm" variant="primary" onClick={() => setOpen(false)}>
            Done
          </Button>
        }
      >
        <div className="modal-long-content">
          <p>Scrollable content example for long narratives, logs, or policy text.</p>
          <p>Use this when content length exceeds typical viewport height.</p>
          <p>Header and footer remain visually separated and stable.</p>
          <p>Content continues...</p>
          <p>Content continues...</p>
          <p>Content continues...</p>
          <p>Content continues...</p>
          <p>Content continues...</p>
          <p>Content continues...</p>
          <p>Content continues...</p>
          <p>Content continues...</p>
          <p>Content continues...</p>
        </div>
      </Modal>
    </>
  );
}

Optional Sizes

Size presets for predictable layouts across the platform. Use sm for confirmations, lg/xl for forms and decision surfaces.

Show code
Modal sizes (JSX)
import { useState } from "react";
import { Modal } from "@/design-system/components/Modal";
import { Button } from "@/design-system/components/Button";

export function Example() {
  const [open, setOpen] = useState<null | "sm" | "md" | "lg" | "xl">(null);

  return (
    <>
      <div className="modal-docs__trigger-grid">
        <Button size="sm" variant="outline" onClick={() => setOpen("sm")}>Small</Button>
        <Button size="sm" variant="outline" onClick={() => setOpen("md")}>Default</Button>
        <Button size="sm" variant="outline" onClick={() => setOpen("lg")}>Large</Button>
        <Button size="sm" variant="outline" onClick={() => setOpen("xl")}>XL</Button>
      </div>

      <Modal
        open={open !== null}
        onClose={() => setOpen(null)}
        title="Sized modal"
        size={open ?? "md"}
        showCloseButton
        footer={
          <Button size="sm" variant="primary" onClick={() => setOpen(null)}>
            Close
          </Button>
        }
      >
        <p>This modal demonstrates size presets (sm, md, lg, xl).</p>
      </Modal>
    </>
  );
}

Fullscreen Responsive Modal

Becomes fullscreen on mobile while remaining a centered, sized modal on larger viewports. Recommended for complex configuration flows.

Show code
Responsive fullscreen modal (JSX)
import { useState } from "react";
import { Modal } from "@/design-system/components/Modal";
import { Button } from "@/design-system/components/Button";

export function Example() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <Button size="sm" variant="secondary" onClick={() => setOpen(true)}>
        Open responsive fullscreen
      </Button>

      <Modal
        open={open}
        onClose={() => setOpen(false)}
        title="Fullscreen (responsive)"
        fullScreenOnMobile
        scrollable
        size="xl"
        showCloseButton
        footer={
          <>
            <Button size="sm" variant="ghost" onClick={() => setOpen(false)}>
              Cancel
            </Button>
            <Button size="sm" variant="primary" onClick={() => setOpen(false)}>
              Save changes
            </Button>
          </>
        }
      >
        <div className="modal-long-content">
          <p>
            On smaller screens this modal becomes fullscreen (edge-to-edge) while retaining
            scrollable body and stable actions.
          </p>
          <p>Use for configuration panels, onboarding flows, and multi-step forms.</p>
          <p>More content...</p>
          <p>More content...</p>
          <p>More content...</p>
          <p>More content...</p>
          <p>More content...</p>
        </div>
      </Modal>
    </>
  );
}