# AppDialog

## Overview

Enhanced modal dialog component built on top of the base Dialog component. Provides a simplified API with built-in header, body, and footer sections, multiple size variants, and support for both controlled and uncontrolled usage patterns.

---

## Props

### AppDialogProps

| Prop               | Type                                          | Default      | Description                                   |
| ------------------ | --------------------------------------------- | ------------ | --------------------------------------------- |
| `trigger`          | `React.ReactNode`                             | `undefined`  | Element that triggers the dialog on click.    |
| `title`            | `string \| React.ReactNode`                   | **required** | Dialog title displayed in the header.         |
| `description`      | `string \| React.ReactNode`                   | `undefined`  | Dialog description displayed below the title. |
| `footer`           | `React.ReactNode`                             | `undefined`  | Footer content (typically action buttons).    |
| `size`             | `"sm" \| "default" \| "lg" \| "xl" \| "full"` | `"default"`  | Size variant of the dialog.                   |
| `open`             | `boolean`                                     | `undefined`  | Controlled open state.                        |
| `defaultOpen`      | `boolean`                                     | `undefined`  | Default open state for uncontrolled usage.    |
| `onOpenChange`     | `(open: boolean) => void`                     | `undefined`  | Callback when open state changes.             |
| `disabled`         | `boolean`                                     | `false`      | Whether to disable the trigger.               |
| `asChild`          | `boolean`                                     | `false`      | Whether to use asChild pattern for trigger.   |
| `preventClose`     | `"overlay" \| "all"`                          | `undefined`  | Prevent closing via overlay or all methods.   |
| `triggerClassName` | `string`                                      | `undefined`  | Additional className for the trigger wrapper. |
| `contentClassName` | `string`                                      | `undefined`  | Additional className for the dialog content.  |
| `headerClassName`  | `string`                                      | `undefined`  | Additional className for the dialog header.   |
| `bodyClassName`    | `string`                                      | `undefined`  | Additional className for the dialog body.     |
| `footerClassName`  | `string`                                      | `undefined`  | Additional className for the dialog footer.   |

### Size Variants

| Size      | Dimensions                         |
| --------- | ---------------------------------- |
| `sm`      | 5/12 width and height              |
| `default` | 7/12 width and height              |
| `lg`      | 9/12 width and height              |
| `xl`      | 11/12 width and height             |
| `full`    | Full viewport (no rounded corners) |

---

## Exports

- **AppDialog**: Main dialog component.
- **AppDialogClose**: Re-export of DialogClose for closing the dialog programmatically.

---

## Behavior

- **Responsive**: On small screens (`max-sm`), the dialog takes full viewport.
- **Scrollable body**: Content in the body section scrolls if it exceeds available space.
- **Close button**: Built-in close button in the header (top-right).
- **Border separators**: Automatic borders between header/body and body/footer when content exists.
- **Focus management**: Inherits Radix Dialog focus trapping behavior.

---

## Examples

### Basic Usage

```tsx
import { AppDialog, Button } from "laif-ds";

export function BasicAppDialog() {
  return (
    <AppDialog
      title="Dialog Title"
      description="Optional description text."
      trigger={<Button>Open Dialog</Button>}
      asChild
    >
      <p>Dialog content goes here.</p>
    </AppDialog>
  );
}
```

### With Footer Actions

```tsx
import { AppDialog, AppDialogClose, Button } from "laif-ds";

export function DialogWithFooter() {
  return (
    <AppDialog
      title="Confirm Action"
      description="Are you sure you want to proceed?"
      trigger={<Button>Open Dialog</Button>}
      footer={
        <>
          <AppDialogClose asChild>
            <Button variant="outline">Cancel</Button>
          </AppDialogClose>
          <AppDialogClose asChild>
            <Button>Confirm</Button>
          </AppDialogClose>
        </>
      }
      asChild
    >
      <p>This action cannot be undone.</p>
    </AppDialog>
  );
}
```

### Controlled Dialog

```tsx
import { useState } from "react";
import { AppDialog, Button } from "laif-ds";

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

  return (
    <>
      <Button onClick={() => setOpen(true)}>Open Dialog</Button>

      <AppDialog
        open={open}
        onOpenChange={setOpen}
        title="Controlled Dialog"
        description="This dialog is controlled externally."
        footer={<Button onClick={() => setOpen(false)}>Close</Button>}
      >
        <p>The dialog state is managed by the parent component.</p>
      </AppDialog>
    </>
  );
}
```

### Size Variants

```tsx
import { AppDialog, Button } from "laif-ds";

export function SizeVariants() {
  return (
    <div className="flex flex-wrap gap-4">
      <AppDialog
        title="Small Dialog"
        size="sm"
        trigger={<Button variant="outline">Small</Button>}
        asChild
      >
        <p>Small dialog content.</p>
      </AppDialog>

      <AppDialog
        title="Default Dialog"
        size="default"
        trigger={<Button variant="outline">Default</Button>}
        asChild
      >
        <p>Default dialog content.</p>
      </AppDialog>

      <AppDialog
        title="Large Dialog"
        size="lg"
        trigger={<Button variant="outline">Large</Button>}
        asChild
      >
        <p>Large dialog content.</p>
      </AppDialog>

      <AppDialog
        title="Extra Large Dialog"
        size="xl"
        trigger={<Button variant="outline">Extra Large</Button>}
        asChild
      >
        <p>Extra large dialog content.</p>
      </AppDialog>

      <AppDialog
        title="Full Dialog"
        size="full"
        trigger={<Button variant="outline">Full</Button>}
        asChild
      >
        <p>Full screen dialog content.</p>
      </AppDialog>
    </div>
  );
}
```

### With Form

```tsx
import { useState } from "react";
import { AppDialog, AppDialogClose, Button, Input, Label } from "laif-ds";

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

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    // Handle form submission
    setOpen(false);
  };

  return (
    <AppDialog
      open={open}
      onOpenChange={setOpen}
      title="Edit Profile"
      description="Update your profile information."
      trigger={<Button>Edit Profile</Button>}
      footer={
        <>
          <AppDialogClose asChild>
            <Button variant="outline">Cancel</Button>
          </AppDialogClose>
          <Button type="submit" onClick={handleSubmit}>
            Save
          </Button>
        </>
      }
      asChild
    >
      <form onSubmit={handleSubmit} className="space-y-4">
        <div className="space-y-2">
          <Label htmlFor="name">Name</Label>
          <Input id="name" placeholder="Your name" />
        </div>
        <div className="space-y-2">
          <Label htmlFor="email">Email</Label>
          <Input id="email" type="email" placeholder="Your email" />
        </div>
      </form>
    </AppDialog>
  );
}
```

### Disabled Trigger

```tsx
import { AppDialog, Button } from "laif-ds";

export function DisabledDialog() {
  return (
    <AppDialog
      title="Disabled Dialog"
      trigger={<Button disabled>Cannot Open</Button>}
      disabled
      asChild
    >
      <p>This content won't be accessible.</p>
    </AppDialog>
  );
}
```

---

## Notes

- **Use `asChild`**: When passing a Button or other interactive element as trigger, set `asChild={true}` to avoid nesting buttons.
- **AppDialogClose**: Use this component to create buttons that close the dialog. Wrap with `asChild` when using custom elements.
- **Scrolling content**: The body section automatically handles overflow with scrolling.
- **Accessibility**: Title is rendered as an `h5` heading; description uses caption typography.
- **vs Dialog**: Use `AppDialog` for simpler use cases with consistent header/body/footer layout. Use base `Dialog` for more complex custom layouts.
