Skip to main content
AxModal provides dialog overlays for forms, confirmations, and focused content. It features built-in description text, danger mode for destructive actions, and three preset sizes.

Basic Usage

import { AxModal, AxButton } from 'axmed-design-system'
import { useState } from 'react'

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

  return (
    <>
      <AxButton onClick={() => setOpen(true)}>Open Modal</AxButton>
      <AxModal
        title="Modal Title"
        description="This is a description below the title."
        open={open}
        onOk={() => setOpen(false)}
        onCancel={() => setOpen(false)}
      >
        Modal body content goes here.
      </AxModal>
    </>
  )
}

Sizes

Three preset widths:
<AxModal size="sm" title="Small Modal" open={open}>  {/* 380px */}
  Compact size for simple confirmations
</AxModal>

<AxModal size="md" title="Medium Modal" open={open}>  {/* 520px - default */}
  Standard size for forms and content
</AxModal>

<AxModal size="lg" title="Large Modal" open={open}>  {/* 720px */}
  Wide size for tables and complex content
</AxModal>

Danger Mode

Make the primary action button red for destructive actions:
<AxModal
  title="Cancel this order?"
  description="This action cannot be undone. The order will be permanently cancelled."
  open={open}
  danger
  size="sm"
  okText="Yes, Cancel Order"
  cancelText="Keep Order"
  onOk={handleDelete}
  onCancel={() => setOpen(false)}
>
  <Alert type="warning" showIcon message="2 suppliers have already submitted bids." />
</AxModal>

Loading State

Show loading spinner on the OK button:
import { useState } from 'react'

function ModalWithLoading() {
  const [open, setOpen] = useState(false)
  const [loading, setLoading] = useState(false)

  const handleOk = async () => {
    setLoading(true)
    await saveChanges()
    setLoading(false)
    setOpen(false)
  }

  return (
    <AxModal
      title="Save changes?"
      open={open}
      confirmLoading={loading}
      onOk={handleOk}
      onCancel={() => setOpen(false)}
    >
      Your changes will be applied immediately.
    </AxModal>
  )
}
Replace the default footer buttons:
<AxModal
  title="Success"
  open={open}
  footer={
    <AxButton onClick={() => setOpen(false)} style={{ width: '100%' }}>
      View Your Orders
    </AxButton>
  }
  onCancel={() => setOpen(false)}
>
  Your order has been submitted successfully.
</AxModal>
Set footer={null} to remove the footer entirely.

Common Patterns

Confirmation Modal

import { Alert } from 'antd'

function DeleteConfirmation() {
  const [open, setOpen] = useState(false)

  return (
    <>
      <AxButton variant="danger" onClick={() => setOpen(true)}>
        Cancel Order
      </AxButton>
      <AxModal
        title="Cancel this order?"
        description="This action cannot be undone. The order will be permanently cancelled and all associated bids will be withdrawn."
        open={open}
        danger
        size="sm"
        okText="Yes, Cancel Order"
        cancelText="Keep Order"
        onOk={() => {
          handleCancel()
          setOpen(false)
        }}
        onCancel={() => setOpen(false)}
      >
        <Alert
          type="warning"
          showIcon
          message="2 suppliers have already submitted bids for this order."
        />
      </AxModal>
    </>
  )
}

Success Modal

import { CheckCircleFilled } from '@ant-design/icons'

<AxModal
  title={
    <div style={{ textAlign: 'center' }}>
      <CheckCircleFilled style={{ fontSize: 40, color: 'var(--success)', display: 'block', marginBottom: 12 }} />
      Order submitted successfully
    </div>
  }
  description={
    <span style={{ display: 'block', textAlign: 'center' }}>
      Your order has been received and is being reviewed by our team.
    </span>
  }
  open={open}
  size="sm"
  footer={
    <AxButton onClick={() => setOpen(false)} style={{ width: '100%' }}>
      View Your Orders
    </AxButton>
  }
  onCancel={() => setOpen(false)}
/>

Form Modal

import { AxInput } from 'axmed-design-system'
import { Select, Checkbox } from 'antd'

function AddAddressModal() {
  const [open, setOpen] = useState(false)

  return (
    <>
      <AxButton onClick={() => setOpen(true)}>Add Address</AxButton>
      <AxModal
        title="Add delivery address"
        description="This address will be available for all future orders."
        open={open}
        okText="Add Address"
        onOk={() => setOpen(false)}
        onCancel={() => setOpen(false)}
      >
        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          <AxInput label="Address Name" placeholder="e.g. Main Warehouse" />
          <div style={{ display: 'flex', gap: 12 }}>
            <div style={{ flex: 1 }}>
              <label style={{ display: 'block', marginBottom: 4, fontSize: 13, fontWeight: 500 }}>
                Country
              </label>
              <Select
                placeholder="Select country"
                style={{ width: '100%' }}
                options={[
                  { value: 'ke', label: 'Kenya' },
                  { value: 'ng', label: 'Nigeria' },
                ]}
              />
            </div>
            <div style={{ flex: 1 }}>
              <label style={{ display: 'block', marginBottom: 4, fontSize: 13, fontWeight: 500 }}>
                City
              </label>
              <Select placeholder="Select city" style={{ width: '100%' }} />
            </div>
          </div>
          <AxInput label="Address Line" placeholder="Street address, building, floor..." />
          <Checkbox>Use as billing address</Checkbox>
        </div>
      </AxModal>
    </>
  )
}

Detail View Modal

import { AxText } from 'axmed-design-system'

<AxModal
  title="Supplier Details"
  open={open}
  footer={
    <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}>
      <AxButton variant="secondary" onClick={() => setOpen(false)}>
        View Full Profile
      </AxButton>
      <AxButton onClick={() => setOpen(false)}>Got It</AxButton>
    </div>
  }
  onCancel={() => setOpen(false)}
>
  <div style={{
    background: 'var(--neutral-50)',
    borderRadius: 8,
    padding: 16,
    display: 'flex',
    flexDirection: 'column',
    gap: 12
  }}>
    {[
      { label: 'Supplier', value: 'PharmaCorp Ltd' },
      { label: 'Unit Price', value: '$2.40 / unit' },
      { label: 'Lead Time', value: '14 days' },
    ].map((item) => (
      <div key={item.label} style={{ display: 'flex', justifyContent: 'space-between' }}>
        <AxText variant="body-sm" color="secondary">{item.label}</AxText>
        <AxText variant="body-sm" weight="medium">{item.value}</AxText>
      </div>
    ))}
  </div>
</AxModal>

Props

title
ReactNode
required
Modal title text
description
ReactNode
Muted subtitle displayed below the title
open
boolean
required
Whether the modal is visible
size
string
default:"md"
Preset width: sm (380px), md (520px), or lg (720px)
danger
boolean
default:"false"
Make the primary action button red for destructive actions
okText
string
default:"OK"
Text for the OK button
cancelText
string
default:"Cancel"
Text for the Cancel button
confirmLoading
boolean
default:"false"
Show loading spinner on the OK button
Custom footer content. Set to null to hide footer.
centered
boolean
default:"true"
Center the modal vertically on the screen
onOk
function
OK button click handler
onCancel
function
Cancel button and close icon click handler
See the full API reference for all available props.

Build docs developers (and LLMs) love