> ## Documentation Index
> Fetch the complete documentation index at: https://araf.badr.co.id/llms.txt
> Use this file to discover all available pages before exploring further.

# Modal / Dialog

> An overlay dialog that interrupts the user to capture attention for critical actions or information — supports default, warning, and destructive variants.

## Overview

<div style={{padding:"28px 24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb",display:"flex",gap:"16px",flexWrap:"wrap",justifyContent:"center"}}>
  <div style={{background:"#fff",borderRadius:"12px",boxShadow:"0 20px 25px -5px rgba(0,0,0,0.1),0 8px 10px -6px rgba(0,0,0,0.1)",width:"320px",padding:"24px",display:"flex",flexDirection:"column",gap:"16px"}}>
    <div style={{display:"flex",flexDirection:"column",gap:"4px"}}>
      <div style={{fontSize:"16px",fontWeight:600,color:"#101828",fontFamily:"Inter,sans-serif"}}>Edit profile</div>
      <div style={{fontSize:"13px",color:"#667085",fontFamily:"Inter,sans-serif"}}>Update your display name and bio.</div>
    </div>

    <div style={{border:"1px solid #D0D5DD",borderRadius:"8px",padding:"9px 13px",fontSize:"14px",color:"#101828",fontFamily:"Inter,sans-serif",background:"#fff"}}>Ahmad Dani</div>

    <div style={{display:"flex",gap:"8px",justifyContent:"flex-end"}}>
      <button style={{padding:"8px 14px",borderRadius:"8px",border:"1px solid #D4D4D8",background:"#fff",color:"#52525B",fontSize:"13px",fontWeight:500,fontFamily:"Inter,sans-serif",cursor:"pointer"}}>Cancel</button>
      <button style={{padding:"8px 14px",borderRadius:"8px",border:"none",background:"#0479CE",color:"#fff",fontSize:"13px",fontWeight:500,fontFamily:"Inter,sans-serif",cursor:"pointer"}}>Save changes</button>
    </div>
  </div>

  <div style={{background:"#fff",borderRadius:"12px",boxShadow:"0 20px 25px -5px rgba(0,0,0,0.1),0 8px 10px -6px rgba(0,0,0,0.1)",width:"320px",padding:"24px",display:"flex",flexDirection:"column",gap:"16px"}}>
    <div style={{display:"flex",gap:"12px",alignItems:"flex-start"}}>
      <div style={{width:"40px",height:"40px",borderRadius:"50%",background:"#FEF2F2",display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0}}>
        <span style={{color:"#DC2626",fontSize:"16px"}}>🗑</span>
      </div>

      <div>
        <div style={{fontSize:"16px",fontWeight:600,color:"#101828",fontFamily:"Inter,sans-serif"}}>Delete account?</div>
        <div style={{fontSize:"13px",color:"#667085",fontFamily:"Inter,sans-serif",marginTop:"4px"}}>All your data will be permanently deleted.</div>
      </div>
    </div>

    <div style={{display:"flex",gap:"8px",justifyContent:"flex-end"}}>
      <button style={{padding:"8px 14px",borderRadius:"8px",border:"1px solid #D4D4D8",background:"#fff",color:"#52525B",fontSize:"13px",fontWeight:500,fontFamily:"Inter,sans-serif",cursor:"pointer"}}>Cancel</button>
      <button style={{padding:"8px 14px",borderRadius:"8px",border:"none",background:"#DC2626",color:"#fff",fontSize:"13px",fontWeight:500,fontFamily:"Inter,sans-serif",cursor:"pointer"}}>Delete account</button>
    </div>
  </div>
</div>

**Modal** renders a centered overlay panel over a dimmed backdrop. Use it for confirmations, form flows, detail views, and any interaction that requires the user's full attention.

<Note>
  For simple yes/no confirmations, consider a compact `AlertDialog`. Use `Drawer` or `Sheet` for side-panel interactions that don't block the full screen.
</Note>

***

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install @araf-ds/core
  ```

  ```bash yarn theme={null}
  yarn add @araf-ds/core
  ```

  ```bash pnpm theme={null}
  pnpm add @araf-ds/core
  ```
</CodeGroup>

***

## Usage

```tsx theme={null}
import {
  Modal,
  ModalContent,
  ModalDescription,
  ModalFooter,
  ModalHeader,
  ModalTitle,
  ModalTrigger,
} from "@araf-ds/core"

export default function Example() {
  const [open, setOpen] = useState(false)
  return (
    <Modal open={open} onOpenChange={setOpen}>
      <ModalTrigger asChild>
        <Button>Edit profile</Button>
      </ModalTrigger>
      <ModalContent>
        <ModalHeader>
          <ModalTitle>Edit profile</ModalTitle>
          <ModalDescription>Update your display name and bio.</ModalDescription>
        </ModalHeader>
        <div className="px-6 py-4">
          <Input label="Display name" defaultValue="Ahmad Dani" />
        </div>
        <ModalFooter>
          <Button variant="outline" onClick={() => setOpen(false)}>Cancel</Button>
          <Button>Save changes</Button>
        </ModalFooter>
      </ModalContent>
    </Modal>
  )
}
```

***

## Variants

### Default Modal

Standard dialog for forms or informational content.

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb",display:"flex",justifyContent:"center"}}>
  <div style={{background:"#fff",borderRadius:"12px",boxShadow:"0 20px 25px -5px rgba(0,0,0,0.1),0 8px 10px -6px rgba(0,0,0,0.1)",width:"360px",padding:"24px",display:"flex",flexDirection:"column",gap:"16px"}}>
    <div>
      <div style={{fontSize:"16px",fontWeight:600,color:"#101828",fontFamily:"Inter,sans-serif"}}>Edit profile</div>
      <div style={{fontSize:"13px",color:"#667085",fontFamily:"Inter,sans-serif",marginTop:"4px"}}>Update your display name and bio.</div>
    </div>

    <div style={{display:"flex",flexDirection:"column",gap:"8px"}}>
      <label style={{fontSize:"13px",fontWeight:500,color:"#344054",fontFamily:"Inter,sans-serif"}}>Display name</label>
      <div style={{border:"1px solid #D0D5DD",borderRadius:"8px",padding:"9px 13px",fontSize:"14px",color:"#101828",fontFamily:"Inter,sans-serif"}}>Ahmad Dani</div>
    </div>

    <div style={{display:"flex",gap:"8px",justifyContent:"flex-end"}}>
      <button style={{padding:"9px 15px",borderRadius:"8px",border:"1px solid #D4D4D8",background:"#fff",color:"#52525B",fontSize:"13px",fontWeight:500,fontFamily:"Inter,sans-serif",cursor:"pointer"}}>Cancel</button>
      <button style={{padding:"9px 15px",borderRadius:"8px",border:"none",background:"#0479CE",color:"#fff",fontSize:"13px",fontWeight:500,fontFamily:"Inter,sans-serif",cursor:"pointer"}}>Save changes</button>
    </div>
  </div>
</div>

```tsx theme={null}
<Modal open={open} onOpenChange={setOpen}>
  <ModalContent>
    <ModalHeader>
      <ModalTitle>Edit profile</ModalTitle>
      <ModalDescription>Update your display name and bio.</ModalDescription>
    </ModalHeader>
    <div className="px-6 py-4">
      <Input label="Display name" defaultValue="Ahmad Dani" />
    </div>
    <ModalFooter>
      <Button variant="outline" onClick={() => setOpen(false)}>Cancel</Button>
      <Button>Save changes</Button>
    </ModalFooter>
  </ModalContent>
</Modal>
```

### Warning Modal

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb",display:"flex",justifyContent:"center"}}>
  <div style={{background:"#fff",borderRadius:"12px",boxShadow:"0 20px 25px -5px rgba(0,0,0,0.1),0 8px 10px -6px rgba(0,0,0,0.1)",width:"360px",padding:"24px",display:"flex",flexDirection:"column",gap:"16px"}}>
    <div style={{display:"flex",gap:"12px",alignItems:"flex-start"}}>
      <div style={{width:"40px",height:"40px",borderRadius:"50%",background:"#FFFAEB",display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0}}>
        <span style={{color:"#B54708",fontSize:"18px"}}>⚠</span>
      </div>

      <div>
        <div style={{fontSize:"16px",fontWeight:600,color:"#101828",fontFamily:"Inter,sans-serif"}}>Unpublish page?</div>
        <div style={{fontSize:"13px",color:"#667085",fontFamily:"Inter,sans-serif",marginTop:"4px"}}>This page will no longer be visible to users.</div>
      </div>
    </div>

    <div style={{display:"flex",gap:"8px",justifyContent:"flex-end"}}>
      <button style={{padding:"9px 15px",borderRadius:"8px",border:"1px solid #D4D4D8",background:"#fff",color:"#52525B",fontSize:"13px",fontWeight:500,fontFamily:"Inter,sans-serif",cursor:"pointer"}}>Cancel</button>
      <button style={{padding:"9px 15px",borderRadius:"8px",border:"none",background:"#B54708",color:"#fff",fontSize:"13px",fontWeight:500,fontFamily:"Inter,sans-serif",cursor:"pointer"}}>Unpublish</button>
    </div>
  </div>
</div>

```tsx theme={null}
<Modal open={open} onOpenChange={setOpen}>
  <ModalContent iconVariant="warning" icon={<AlertTriangleIcon />}>
    <ModalHeader>
      <ModalTitle>Unpublish page?</ModalTitle>
      <ModalDescription>This page will no longer be visible to users.</ModalDescription>
    </ModalHeader>
    <ModalFooter>
      <Button variant="outline" onClick={() => setOpen(false)}>Cancel</Button>
      <Button variant="warning">Unpublish</Button>
    </ModalFooter>
  </ModalContent>
</Modal>
```

### Destructive Modal

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb",display:"flex",justifyContent:"center"}}>
  <div style={{background:"#fff",borderRadius:"12px",boxShadow:"0 20px 25px -5px rgba(0,0,0,0.1),0 8px 10px -6px rgba(0,0,0,0.1)",width:"360px",padding:"24px",display:"flex",flexDirection:"column",gap:"16px"}}>
    <div style={{display:"flex",gap:"12px",alignItems:"flex-start"}}>
      <div style={{width:"40px",height:"40px",borderRadius:"50%",background:"#FEF2F2",display:"flex",alignItems:"center",justifyContent:"center",flexShrink:0}}>
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#DC2626" strokeWidth="2">
          <polyline points="3 6 5 6 21 6" />

          <path d="M19 6l-1 14H6L5 6" />

          <path d="M10 11v6M14 11v6" />

          <path d="M9 6V4h6v2" />
        </svg>
      </div>

      <div>
        <div style={{fontSize:"16px",fontWeight:600,color:"#101828",fontFamily:"Inter,sans-serif"}}>Delete account?</div>
        <div style={{fontSize:"13px",color:"#667085",fontFamily:"Inter,sans-serif",marginTop:"4px"}}>All your data will be permanently deleted. This cannot be undone.</div>
      </div>
    </div>

    <div style={{display:"flex",gap:"8px",justifyContent:"flex-end"}}>
      <button style={{padding:"9px 15px",borderRadius:"8px",border:"1px solid #D4D4D8",background:"#fff",color:"#52525B",fontSize:"13px",fontWeight:500,fontFamily:"Inter,sans-serif",cursor:"pointer"}}>Cancel</button>
      <button style={{padding:"9px 15px",borderRadius:"8px",border:"none",background:"#DC2626",color:"#fff",fontSize:"13px",fontWeight:500,fontFamily:"Inter,sans-serif",cursor:"pointer"}}>Delete account</button>
    </div>
  </div>
</div>

```tsx theme={null}
<Modal open={open} onOpenChange={setOpen}>
  <ModalContent iconVariant="destructive" icon={<TrashIcon />}>
    <ModalHeader>
      <ModalTitle>Delete account?</ModalTitle>
      <ModalDescription>All your data will be permanently deleted. This cannot be undone.</ModalDescription>
    </ModalHeader>
    <ModalFooter>
      <Button variant="outline" onClick={() => setOpen(false)}>Cancel</Button>
      <Button variant="destructive">Delete account</Button>
    </ModalFooter>
  </ModalContent>
</Modal>
```

<Warning>
  Always require a second confirmation step before executing destructive actions in a Modal.
</Warning>

***

## API Reference

### Modal (Root)

<ParamField path="open" type="boolean">
  Controls the open state.
</ParamField>

<ParamField path="onOpenChange" type="(open: boolean) => void">
  Callback fired when the open state changes.
</ParamField>

<ParamField path="defaultOpen" type="boolean" default="false">
  Uncontrolled default open state.
</ParamField>

### ModalContent

<ParamField path="size" type="string" default="md">
  Dialog width. Values: `sm` · `md` · `lg` · `xl` · `full`
</ParamField>

<ParamField path="icon" type="ReactNode">
  Icon shown in the header area alongside the title.
</ParamField>

<ParamField path="iconVariant" type="string" default="default">
  Icon container background. Values: `default` · `warning` · `destructive`
</ParamField>

<ParamField path="className" type="string">
  Additional Tailwind classes for custom overrides.
</ParamField>

### ModalFooter

<ParamField path="align" type="string" default="end">
  Button alignment inside the footer. Values: `start` · `end` · `between`
</ParamField>

***

## Accessibility

* Modal uses `role="dialog"` with `aria-modal="true"`
* Focus is trapped inside the modal while open
* Pressing Escape closes the modal
* Focus returns to the trigger element when the modal closes
* `ModalTitle` is linked via `aria-labelledby`
* `ModalDescription` is linked via `aria-describedby`

***

## Do's & Don'ts

<CardGroup cols={2}>
  <Card title="Do" icon="check" iconType="solid" color="#16A34A">
    * Use Modal for actions that require the user's complete attention
    * Keep modals focused on a single task
    * Always provide a clear Cancel/Close action
    * Use destructive `iconVariant` for irreversible actions
  </Card>

  <Card title="Don't" icon="xmark" iconType="solid" color="#DC2626">
    * Don't use Modal for non-critical information — use Toast or Alert
    * Don't nest modals inside other modals
    * Don't make modals too large — keep content scannable
    * Don't auto-close a modal after a destructive action without confirmation
  </Card>
</CardGroup>
