<!-- Generated by scripts/gen-docs.mts from the JSDoc in registry/. Do not edit; run `pnpm run docs`. -->

# Attachment

A file attached to a chat message, or waiting to be sent with one: its icon, name and size. With `href` it is a link that opens or downloads the file; with `onRemove` it has a remove button, named after the file, for the composer. Long names truncate.

```tsx
import { Attachment } from "@/components/ouro/message/attachment";
```

## Example

```tsx
<Attachment name="menu.pdf" size={file.size} contentType={file.type} href={file.url} />
<Attachment name={file.name} size={file.size} onRemove={() => remove(file)} />
```

## Use instead when

- Use `Link` instead for a link that is not a file, and `Avatar` for a person's picture.

## Props

Type: `AttachmentProps`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `className` | `string` |  | Layout only: margins, width (`mt-2`). Appearance classes warn in development. |
| `contentType` | `string` |  | The file's MIME type (`file.type`): `image/*` shows an image icon, anything else a file icon. |
| `download` | `boolean` |  | Downloads the file instead of opening it (the link's `download` attribute). Needs `href`. |
| `formatSize` | `((bytes: number) => string)` | `"512 B"`, "2 kB", "1.2 MB", in steps of 1024 | Writes `size` for other languages or units. |
| `href` | `string` |  | Where the file opens or downloads. With it, the attachment is a link named by the file and its size. |
| `name` (required) | `string` |  | The file's name, as the user sees it: "menu.pdf". Required, so every file has a name. |
| `onRemove` | `(() => void)` |  | Shows a remove button, which calls this. Use it while composing a message, before it is sent. |
| `ref` | `Ref<HTMLDivElement>` |  | Reaches the rendered element. |
| `removeLabel` | `((name: string) => string)` | (name) => `Remove ${name}` | The remove button's accessible name, for other languages. |
| `size` | `number` |  | The file's size in bytes (`file.size`), shown as "1.2 MB". |

## Native attributes

Also accepts the attributes in React's `HTMLAttributes` (`id`, `aria-*`, event handlers), passed to the rendered element, except those named on this page.

## Don't use

These are not props. Passing one fails the type check with the fix in the error, and in development a console message names the fix.

- `filename`: Not a prop. The file's name is `name`: `<Attachment name="menu.pdf" />`.
- `fileName`: Not a prop. The file's name is `name`: `<Attachment name="menu.pdf" />`.
- `onDelete`: Not a prop. Use `onRemove`: `<Attachment name="menu.pdf" onRemove={remove} />`.
- `onDismiss`: Not a prop. Use `onRemove`: `<Attachment name="menu.pdf" onRemove={remove} />`.
- `url`: Not a prop. The file's address is `href`: `<Attachment name="menu.pdf" href="/menu.pdf" />`.

## `className` is for layout only

Pass margins, width and grid placement (`mt-4`, `w-full`, `col-span-2`). Your classes always win over Ouro UI's: Attachment merges `className` last with `cn` (tailwind-merge), so a class that conflicts with its own replaces it.[^layout-classes]

Appearance comes from props, not classes. In development, a class that sets appearance logs one warning per component instance, naming the prop to use instead. A class sets appearance when, after its variants (`hover:`, `sm:`) and any `!` are removed, it starts with `bg-`, `text-`, `border-`, `rounded-`, `shadow-`, `font-`, `ring-`, `from-`, `via-`, `to-`, `fill-` or `stroke-`, or is `border`, `rounded`, `shadow` or `ring`, or has a `dark:` variant. Text wrapping, overflow and table layout classes (`text-wrap`, `text-ellipsis`, `border-collapse`) are layout and do not warn.

Alignment classes (`text-center`) warn too: set alignment on a parent element.

[^layout-classes]: test:registry/ouro/components/ouro/message/attachment.test.tsx::Attachment > forwards a ref and lets app layout classes win verify:testExists(registry/ouro/components/ouro/message/attachment.test.tsx::Attachment > forwards a ref and lets app layout classes win)
