# Attachment (https://v2.s3.dimah.dev/docs/react/ui/components/attachment)

`FileAttachment` and `StatusAttachment` are the cards the upload family
renders, built on [shadcn Attachment](https://ui.shadcn.com/docs/components/attachment).
Use them, with the smaller pieces on this page, when you build your own
parts.

## Preview [#preview]

<AttachmentPlaygroundPreview />

## Install [#install]

Complete [UI Setup](https://v2.s3.dimah.dev/docs/react/ui) first: the stylesheet and one
`<Toaster />`. Then add this component:

<Tabs items={["npm package", "shadcn registry"]}>

<Tab value="npm package">

```tsx
import { FileAttachment, StatusAttachment } from "@dimah-s3/ui";
```

</Tab>

<Tab value="shadcn registry">

```npm
npx shadcn@latest add @dimah-s3/file-attachment
```

</Tab>

</Tabs>

---

## Usage [#usage]

`UploadStatus`, `UploadFileList`, and `UploadFieldValue` already render
these cards. Reach for them when you render a file yourself:

```tsx
"use client";

import { UploadFileList, FileAttachment } from "@dimah-s3/ui";

export function CompactFiles() {
  return (
    <UploadFileList className="flex-row flex-wrap">
      {(file) => (
        <FileAttachment
          className="w-32"
          state={
            file.phase === "success"
              ? "done"
              : file.phase === "error"
                ? "error"
                : "uploading"
          }
          fileName={file.fileName}
          fileSize={file.fileSize}
          contentType={file.contentType}
          previewUrl={file.previewUrl}
          percent={file.progress.percent}
          error={file.error}
        />
      )}
    </UploadFileList>
  );
}
```

Render `UploadFileList` inside [`Upload`](https://v2.s3.dimah.dev/docs/react/ui/components/upload).
`UploadFileItem` maps every phase and adds cancel for you.

## Layout [#layout]

Set the width with `className`. The card is a size container: below a 9rem
content width, such as `className="w-32"`, the media stacks above the text.
Wider, it is a row. `StatusAttachment` is always a row and fills its parent
unless you set a width.

`state` is `idle`, `uploading`, `processing`, `done`, or `error`. The ring
shows `percent` while the card is `idle` or `uploading`; `processing` shows a
spinner instead.

## Actions [#actions]

- `onCancel` adds a `Cancel {name}` action while the card is `idle`
  (queued), `uploading`, or `processing`.
- `onRetry` adds a `Retry {name}` action while it is `error`. It is the same
  button as cancel, so focus stays on it when the file goes back in flight.
- `onDismiss` adds a `Dismiss {name}` action once it is `done` or `error`.
- `actions` takes your own `AttachmentAction`s, placed before those.

The title is a `FileName`: a long name ends its stem in an ellipsis and keeps
the extension visible, and `title` holds the whole name.

- `trigger` takes an `AttachmentTrigger` that makes the whole card one
  control, such as opening the file. Give it an accessible name.

```tsx
<FileAttachment
  state="done"
  fileName={file.name}
  fileSize={file.size}
  trigger={
    <AttachmentTrigger aria-label={`Open ${file.name}`} onClick={open} />
  }
  actions={
    <AttachmentAction aria-label={`Share ${file.name}`} onClick={share}>
      <Share2Icon />
    </AttachmentAction>
  }
/>
```

Wrap several cards in `AttachmentGroup` for a scrolling row.

## Examples [#examples]

### Every state [#every-state]

`FileAttachment` for one file in each state, and `StatusAttachment` for a
result that has no single file.

<DemoPreview name="attachment-states-demo.tsx">
  <AttachmentStatesDemo />
</DemoPreview>

### Glyphs and progress [#glyphs-and-progress]

`FileTypeGlyph` picks a colored glyph from the content type, else the
extension. `FolderGlyph` is the object list's folder, and `CircleProgress`
the ring a card shows while its file uploads.

<DemoPreview name="attachment-glyphs-demo.tsx">
  <AttachmentGlyphsDemo />
</DemoPreview>

## Building blocks [#building-blocks]

| Export                    | Renders                                                                   |
| ------------------------- | ------------------------------------------------------------------------- |
| `CircleProgress`          | A progress ring with `role="progressbar"`, named `Progress for {name}`    |
| `FileName`                | A name that fits its width and keeps the extension (`report-for-q….pdf`)  |
| `FileTypeGlyph`           | A colored glyph for the file type, from the content type or the extension |
| `FolderGlyph`             | The folder glyph the object list uses                                     |
| `DismissAttachmentAction` | The dismiss icon button. `label` sets its accessible name                 |
| `AttachmentGroup`         | A horizontal, scrolling group of cards, from shadcn Attachment            |
| `AttachmentAction`        | An icon button in the card's actions, from shadcn Attachment              |
| `AttachmentTrigger`       | A button over the whole card, from shadcn Attachment                      |

For chrome that does not fit these, compose
[shadcn Attachment](https://ui.shadcn.com/docs/components/attachment) with the
headless hooks; see [Custom UI](https://v2.s3.dimah.dev/docs/react/ui/customization/custom-ui).

---

## Props [#props]

```ts
import type {
  FileAttachmentProps,
  StatusAttachmentProps,
  CircleProgressProps,
  FileNameProps,
  FileTypeGlyphProps,
  DismissAttachmentActionProps,
} from "@dimah-s3/ui";
```

### FileAttachment [#fileattachment]

<AutoTypeTable
  path="packages/ui/src/components/dimah-s3/attachment/file-attachment.tsx"
  name="FileAttachmentProps"
/>

### StatusAttachment [#statusattachment]

<AutoTypeTable
  path="packages/ui/src/components/dimah-s3/attachment/status-attachment.tsx"
  name="StatusAttachmentProps"
/>

### CircleProgress [#circleprogress]

<AutoTypeTable
  path="packages/ui/src/components/dimah-s3/attachment/circle-progress.tsx"
  name="CircleProgressProps"
/>

### FileName [#filename]

<AutoTypeTable
  path="packages/ui/src/components/dimah-s3/attachment/file-name.tsx"
  name="FileNameProps"
/>

### FileTypeGlyph [#filetypeglyph]

<AutoTypeTable
  path="packages/ui/src/components/dimah-s3/attachment/file-type-glyph.tsx"
  name="FileTypeGlyphProps"
/>

### DismissAttachmentAction [#dismissattachmentaction]

<AutoTypeTable
  path="packages/ui/src/components/dimah-s3/attachment/dismiss-attachment-action.tsx"
  name="DismissAttachmentActionProps"
/>
