# Attachment

Attached files: rows, thumbnail cards and upload progress.

Group: Chat

## Import

```tsx
import { Attachment } from "@indoku/ui"
```

## Examples

### Basic usage

```tsx
function AttachmentDemo() {
  return (
    <Stack gap="3" maxW="sm">
      <Attachment.Root>
        <Attachment.Media />
        <Attachment.Content>
          <Attachment.Name>invoice-september.pdf</Attachment.Name>
          <Attachment.Meta size={482000} />
        </Attachment.Content>
      </Attachment.Root>

      <Attachment.Root>
        <Attachment.Media />
        <Attachment.Content>
          <Attachment.Name>rekap-penjualan.xlsx</Attachment.Name>
          <Attachment.Status status="uploading" progress={64} />
        </Attachment.Content>
        <Attachment.Actions>
          <Attachment.Action aria-label="Batalkan">✕</Attachment.Action>
        </Attachment.Actions>
      </Attachment.Root>
    </Stack>
  )
}

function AttachmentCardsDemo() {
  return (
    <Stack gap="2">
      <Attachment.Group>
        {["workspace.png", "desk-reference.jpg", "office-reference.jpg"].map((n) => (
          <Attachment.Root key={n} orientation="vertical">
            <Attachment.Media src={`https://picsum.photos/seed/${n}/320/240`} />
            <Attachment.Content>
              <Attachment.Name>{n}</Attachment.Name>
              <Attachment.Meta format={n.split(".")[1].toUpperCase()} size={840000} />
            </Attachment.Content>
          </Attachment.Root>
        ))}
      </Attachment.Group>
      <Attachment.Root>
        <Attachment.Media loading />
        <Attachment.Content>
          <Attachment.Name>sales-dashboard.pdf</Attachment.Name>
          <Attachment.Status status="uploading" progress={64} variant="text" />
        </Attachment.Content>
        <Attachment.Actions>
          <Attachment.Remove />
        </Attachment.Actions>
      </Attachment.Root>
      <Attachment.Root>
        <Attachment.Media />
        <Attachment.Content>
          <Attachment.Name>rekap-penjualan.xlsx</Attachment.Name>
          <Attachment.Status status="uploading" progress={65} />
        </Attachment.Content>
        <Attachment.Actions>
          <Attachment.Remove />
        </Attachment.Actions>
      </Attachment.Root>
    </Stack>
  )
}
```

## Props

### Root

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `onClick` | `() => void` |  | Click handler for the whole card (not the action buttons). Usually opens a preview. |
| `orientation` | `"horizontal" \| "vertical"` | `horizontal` | `"vertical"` renders a square card (thumbnail on top, name below). Pairs well with `Attachment.Group`. |

### Media

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `src` | `string` |  | Thumbnail image URL. Without it, an icon based on `kind` is shown. |
| `alt` | `string` |  |  |
| `kind` | `"file" \| "code"` | `file` | Built-in icon: `"file"` or `"code"` (`</>`). Ignored when `src` is set. |
| `loading` | `boolean` |  | Show a spinner (upload in progress). |

### Meta

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `size` | `number` |  | File size in bytes. Formatted automatically (e.g. 1200000 → "1.1 MB"). |
| `format` | `string` |  | Format label shown before the size, e.g. `"PNG"` → "PNG · 820 KB". |

### Status

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `status` * | `AttachmentStatus` |  |  |
| `progress` | `number` |  | 0–100. Used when `status` is `"uploading"`. |
| `variant` | `"bar" \| "text"` | `bar` | `"bar"` renders a progress bar. `"text"` renders "Uploading · 64%" (pair with `<Attachment.Media loading />`). |

### Action

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `"aria-label"` * | `string` |  | Defines a string value that labels the current element. |
| `children` | `ReactNode` |  |  |

`*` = required. Style props and HTML attributes are accepted too.
