snapshot of https://github.com/shadcn-ui/ui.git (main, 2026-09-15; blobs > 131072B omitted)
This commit is contained in:
302
apps/v4/content/docs/components/base/attachment.mdx
Normal file
302
apps/v4/content/docs/components/base/attachment.mdx
Normal file
@@ -0,0 +1,302 @@
|
||||
---
|
||||
title: Attachment
|
||||
description: Displays a file or image attachment with media, metadata, upload state, and actions.
|
||||
base: base
|
||||
component: true
|
||||
---
|
||||
|
||||
<ComponentPreview
|
||||
styleName="base-rhea"
|
||||
name="attachment-demo"
|
||||
previewClassName="h-auto theme-blue bg-surface dark:bg-background"
|
||||
/>
|
||||
|
||||
The `Attachment` component displays a file or image attachment, its media, name, and metadata, with optional actions and upload state. Use it for files and images in chat composers, message threads, and upload lists.
|
||||
|
||||
## Installation
|
||||
|
||||
<CodeTabs>
|
||||
|
||||
<TabsList>
|
||||
<TabsTrigger value="cli">Command</TabsTrigger>
|
||||
<TabsTrigger value="manual">Manual</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="cli">
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add attachment
|
||||
```
|
||||
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="manual">
|
||||
|
||||
<Steps className="mb-0 pt-2">
|
||||
|
||||
<Step>Install the required shadcn/ui dependencies:</Step>
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add button
|
||||
```
|
||||
|
||||
<Step>Copy and paste the following code into your project.</Step>
|
||||
|
||||
<ComponentSource
|
||||
name="attachment"
|
||||
title="components/ui/attachment.tsx"
|
||||
styleName="base-rhea"
|
||||
/>
|
||||
|
||||
<Step>Update the import paths to match your project setup.</Step>
|
||||
|
||||
</Steps>
|
||||
|
||||
</TabsContent>
|
||||
|
||||
</CodeTabs>
|
||||
|
||||
## Usage
|
||||
|
||||
```tsx
|
||||
import {
|
||||
Attachment,
|
||||
AttachmentAction,
|
||||
AttachmentActions,
|
||||
AttachmentContent,
|
||||
AttachmentDescription,
|
||||
AttachmentMedia,
|
||||
AttachmentTitle,
|
||||
} from "@/components/ui/attachment"
|
||||
```
|
||||
|
||||
```tsx
|
||||
<Attachment>
|
||||
<AttachmentMedia>
|
||||
<FileTextIcon />
|
||||
</AttachmentMedia>
|
||||
<AttachmentContent>
|
||||
<AttachmentTitle>sales-dashboard.pdf</AttachmentTitle>
|
||||
<AttachmentDescription>PDF · 2.4 MB</AttachmentDescription>
|
||||
</AttachmentContent>
|
||||
<AttachmentActions>
|
||||
<AttachmentAction aria-label="Remove sales-dashboard.pdf">
|
||||
<XIcon />
|
||||
</AttachmentAction>
|
||||
</AttachmentActions>
|
||||
</Attachment>
|
||||
```
|
||||
|
||||
## Composition
|
||||
|
||||
Use the following composition to build an attachment:
|
||||
|
||||
```text
|
||||
Attachment
|
||||
├── AttachmentMedia
|
||||
├── AttachmentContent
|
||||
│ ├── AttachmentTitle
|
||||
│ └── AttachmentDescription
|
||||
├── AttachmentActions
|
||||
│ └── AttachmentAction
|
||||
└── AttachmentTrigger
|
||||
```
|
||||
|
||||
Use `AttachmentGroup` to lay out multiple attachments in a scrollable row:
|
||||
|
||||
```text
|
||||
AttachmentGroup
|
||||
├── Attachment
|
||||
└── Attachment
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Icon and image media through `AttachmentMedia`
|
||||
- Upload states: `idle`, `uploading`, `processing`, `error`, and `done` with built-in styling and a shimmer while in progress
|
||||
- Three sizes and horizontal or vertical orientation
|
||||
- A full-card `AttachmentTrigger` that opens a link or dialog while the actions stay independently clickable
|
||||
- Scrollable, snapping `AttachmentGroup` with an edge fade
|
||||
- Customizable styling through the `className` prop on every part
|
||||
|
||||
## Image
|
||||
|
||||
Set `variant="image"` on `AttachmentMedia` and render an `<img>` inside it. Use `orientation="vertical"` to stack the media above the content.
|
||||
|
||||
<ComponentPreview
|
||||
styleName="base-rhea"
|
||||
name="attachment-image"
|
||||
previewClassName="h-auto theme-blue bg-surface dark:bg-background"
|
||||
/>
|
||||
|
||||
## States
|
||||
|
||||
Set `state` to reflect the upload lifecycle. `uploading` and `processing` shimmer the title, and `error` switches to a destructive treatment.
|
||||
|
||||
<ComponentPreview
|
||||
styleName="base-rhea"
|
||||
name="attachment-states"
|
||||
previewClassName="h-auto theme-blue bg-surface dark:bg-background"
|
||||
/>
|
||||
|
||||
## Sizes
|
||||
|
||||
Use `size` to switch between `default`, `sm`, and `xs`.
|
||||
|
||||
<ComponentPreview
|
||||
styleName="base-rhea"
|
||||
name="attachment-sizes"
|
||||
previewClassName="h-auto theme-blue bg-surface dark:bg-background"
|
||||
/>
|
||||
|
||||
## Group
|
||||
|
||||
Wrap attachments in `AttachmentGroup` to lay them out in a horizontally scrollable, snapping row with an edge fade.
|
||||
|
||||
<ComponentPreview
|
||||
styleName="base-rhea"
|
||||
name="attachment-group"
|
||||
previewClassName="h-auto theme-blue bg-surface dark:bg-background"
|
||||
/>
|
||||
|
||||
## Trigger
|
||||
|
||||
Add an `AttachmentTrigger` to make the whole card open a link or dialog. It fills the card behind the actions, so the actions stay clickable.
|
||||
|
||||
<ComponentPreview
|
||||
styleName="base-rhea"
|
||||
name="attachment-trigger"
|
||||
previewClassName="h-auto theme-blue bg-surface dark:bg-background"
|
||||
/>
|
||||
|
||||
```tsx showLineNumbers
|
||||
<Dialog>
|
||||
<Attachment>
|
||||
{/* media, content, actions */}
|
||||
<DialogTrigger
|
||||
render={<AttachmentTrigger aria-label="Preview research-summary.pdf" />}
|
||||
/>
|
||||
</Attachment>
|
||||
<DialogContent>{/* ... */}</DialogContent>
|
||||
</Dialog>
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
`AttachmentAction` renders a `Button`, and `AttachmentTrigger` renders a real `<button>` (or your element via `render`). Follow the guidance below so both are operable and announced.
|
||||
|
||||
### Label icon-only actions
|
||||
|
||||
`AttachmentAction` is usually icon-only, so give each one an `aria-label` describing the action and its target.
|
||||
|
||||
```tsx showLineNumbers
|
||||
<AttachmentAction aria-label="Remove sales-dashboard.pdf">
|
||||
<XIcon />
|
||||
</AttachmentAction>
|
||||
```
|
||||
|
||||
### Label the trigger
|
||||
|
||||
`AttachmentTrigger` covers the card with no text of its own, so give it an `aria-label` for what activating it does.
|
||||
|
||||
```tsx showLineNumbers
|
||||
<AttachmentTrigger
|
||||
render={
|
||||
<a
|
||||
href={url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
aria-label="Open workspace.png"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
```
|
||||
|
||||
The trigger sits behind the actions in the stacking order, so an `AttachmentAction` and the `AttachmentTrigger` never trap each other — both remain separately focusable and clickable.
|
||||
|
||||
### Keyboard scrolling
|
||||
|
||||
An `AttachmentGroup` scrolls horizontally. When its attachments are interactive: a trigger or actions, keyboard users reach off-screen items by tabbing to them. For a row of presentational attachments, make the group itself focusable and scrollable by adding `tabIndex={0}`, `role="group"`, and an `aria-label`.
|
||||
|
||||
### Meaning beyond color
|
||||
|
||||
The `error` state uses a destructive color. Keep the failure reason in `AttachmentDescription` so the state is not conveyed by color alone.
|
||||
|
||||
## API Reference
|
||||
|
||||
### Attachment
|
||||
|
||||
The root attachment container.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| ------------- | ------------------------------------------------------------ | -------------- | ------------------------------------------------- |
|
||||
| `state` | `"idle" \| "uploading" \| "processing" \| "error" \| "done"` | `"done"` | The upload state. Drives styling and the shimmer. |
|
||||
| `size` | `"default" \| "sm" \| "xs"` | `"default"` | The attachment size. |
|
||||
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Lay the media beside or above the content. |
|
||||
| `className` | `string` | - | Additional classes to apply to the root element. |
|
||||
|
||||
### AttachmentMedia
|
||||
|
||||
The media slot for an icon or image preview.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| ----------- | ------------------- | -------- | ---------------------------------------------- |
|
||||
| `variant` | `"icon" \| "image"` | `"icon"` | Whether the media holds an icon or an `<img>`. |
|
||||
| `className` | `string` | - | Additional classes to apply to the media slot. |
|
||||
|
||||
### AttachmentContent
|
||||
|
||||
Wraps the title and description.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| ----------- | -------- | ------- | ------------------------------------------------ |
|
||||
| `className` | `string` | - | Additional classes to apply to the content slot. |
|
||||
|
||||
### AttachmentTitle
|
||||
|
||||
The attachment name. Shimmers while the attachment is `uploading` or `processing`.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| ----------- | -------- | ------- | ----------------------------------------- |
|
||||
| `className` | `string` | - | Additional classes to apply to the title. |
|
||||
|
||||
### AttachmentDescription
|
||||
|
||||
Secondary metadata such as the file type, size, or upload status.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| ----------- | -------- | ------- | ----------------------------------------------- |
|
||||
| `className` | `string` | - | Additional classes to apply to the description. |
|
||||
|
||||
### AttachmentActions
|
||||
|
||||
A container for one or more actions, aligned to the end of the attachment.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| ----------- | -------- | ------- | ------------------------------------------- |
|
||||
| `className` | `string` | - | Additional classes to apply to the actions. |
|
||||
|
||||
### AttachmentAction
|
||||
|
||||
An action button. Renders a [`Button`](/docs/components/button) and accepts all of its props.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| ---------- | ------------------------------------- | ----------- | ---------------------------------------- |
|
||||
| `size` | `Button["size"]` | `"icon-xs"` | The button size. |
|
||||
| `...props` | `React.ComponentProps<typeof Button>` | - | Props spread to the underlying `Button`. |
|
||||
|
||||
### AttachmentTrigger
|
||||
|
||||
A full-card overlay that activates the attachment. Renders a `<button>` by default.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| ---------- | -------------------------------- | ------- | ---------------------------------------------- |
|
||||
| `render` | `ReactElement \| function` | - | Render as a different element, such as a link. |
|
||||
| `...props` | `React.ComponentProps<"button">` | - | Props spread to the trigger element. |
|
||||
|
||||
### AttachmentGroup
|
||||
|
||||
Lays out attachments in a horizontally scrollable, snapping row.
|
||||
|
||||
| Prop | Type | Default | Description |
|
||||
| ----------- | -------- | ------- | ----------------------------------------- |
|
||||
| `className` | `string` | - | Additional classes to apply to the group. |
|
||||
Reference in New Issue
Block a user