# Attachment

> A compound card presenting one attached file or image — media preview, name, supporting details, actions — plus a horizontally scrolling row for several cards side by side.

```ts
import { Attachment } from "@sdxc/ui";
```

The card's outer host, recolored to the danger tint at `state="error"` and
declaring the `ui-attachment` named container so nested parts reflow at the
card's width. A busy state sets `aria-busy` to the token ARIA recognizes.

## Examples

```tsx
<Attachment state="uploading">
	<Attachment.Media><FileIcon aria-hidden /></Attachment.Media>
	<Attachment.Content>
		<Attachment.Title state="uploading">quarterly-report.pdf</Attachment.Title>
		<Attachment.Description>{t("attachment.uploading")}</Attachment.Description>
	</Attachment.Content>
</Attachment>
```

```tsx
<Attachment state="error">
	<Attachment.Media><FileIcon aria-hidden /></Attachment.Media>
	<Attachment.Content>
		<Attachment.Title>quarterly-report.pdf</Attachment.Title>
		<Attachment.Description>{t("attachment.uploadFailed")}</Attachment.Description>
	</Attachment.Content>
	<Attachment.Actions>
		<Attachment.Action aria-label={t("attachment.retry")}><RotateCwIcon /></Attachment.Action>
	</Attachment.Actions>
</Attachment>
```

## Props

| Prop | Type | Description |
| --- | --- | --- |
| `state?` | `"idle" \| "uploading" \| "processing" \| "error" \| "done"` | Lifecycle state of the file or image the card represents. Defaults to `"idle"`. |
| `children` | `RemixNode` | The card's compound parts: Attachment.Media, Attachment.Content, and Attachment.Actions. |

Also accepts everything in `TagProps<"div">`.


### Attachment.Media

The card's media well: a fixed-size, rounded box clipping the preview a consumer nests inside.

| Prop | Type | Description |
| --- | --- | --- |
| `children` | `RemixNode` | The preview itself: an `<img>`, or a decorative icon standing in for the file's type. |

Also accepts everything in `TagProps<"div">`.


### Attachment.Content

The card's text column, growing into whatever inline space Attachment.Media and Attachment.Actions leave it.

| Prop | Type | Description |
| --- | --- | --- |
| `children` | `RemixNode` | Attachment.Title and, optionally, Attachment.Description. |

Also accepts everything in `TagProps<"div">`.


### Attachment.Title

The file or image name in a native `<p>`, truncated to a single line with an ellipsis.

| Prop | Type | Description |
| --- | --- | --- |
| `state?` | `Attachment.State` | The ancestor Attachment's own `state`, repeated here because a component reads only its own props; passing the same value to both is what keeps them in sync. Left unset, the title renders plain. |
| `children` | `RemixNode` | The file or image name. |

Also accepts everything in `TagProps<"p">`.


### Attachment.Description

The card's supporting detail line: a muted, single-line `<p>` carrying a file size, a page count, or the explanation of what went wrong once the ancestor Attachment's `state` reads `"error"`.

| Prop | Type | Description |
| --- | --- | --- |
| `children` | `RemixNode` | Supporting detail — a file size, a page count, an error message. |

Also accepts everything in `TagProps<"p">`.


### Attachment.Actions

The card's action row, shrink-proof so a narrow card's width is absorbed by Attachment.Content's own truncation while the actions keep their size.

| Prop | Type | Description |
| --- | --- | --- |
| `children` | `RemixNode` | A run of Attachment.Action controls. |

Also accepts everything in `TagProps<"div">`.


### Attachment.Action

A single card action as a Button, defaulting to a compact, `"ghost"`, neutral control so a row of actions reads as secondary to the card's title.

Also accepts everything in `Button.Props`.


### Attachment.Trigger

A wrapper `<div>` whose `href` or `commandfor` stays an inert attribute until a consumer mixes in `attachmentTrigger()`.

| Prop | Type | Description |
| --- | --- | --- |
| `href?` | `string` | Destination the whole card follows once `attachmentTrigger()` is mixed in, opened in place unless the activation asks for a new tab. It rides on a `<div>` so a nested Attachment.Action stays valid markup. |
| `commandfor?` | `string` | `id` of a `<dialog>` element the whole card opens once `attachmentTrigger()` is mixed in, instead of following `href`. |
| `command?` | `"show-modal"` | Invoker Commands verb dispatched to `commandfor`'s dialog. Defaults to `"show-modal"`. |
| `target?` | `string` | Where `href` opens: a window/frame name, or `"_blank"` for a new tab. Meaningful only alongside `href`. |
| `children` | `RemixNode` | The card's own markup — typically an Attachment. |

Also accepts everything in `TagProps<"div">`.


### Attachment.Group

A horizontally scroll-snapping row of cards, faded at both inline edges to hint at cards beyond the current view.

| Prop | Type | Description |
| --- | --- | --- |
| `children` | `RemixNode` | A run of Attachment or Attachment.Trigger cards. |

Also accepts everything in `TagProps<"div">`.


## Types

| Name | Values | What it decides |
| --- | --- | --- |
| `State` | `"idle" \| "uploading" \| "processing" \| "error" \| "done"` | Lifecycle state of a card's file or image. |
