- 手风琴
- 提示
- 警告对话框
- 宽高比
- 附件
- 头像
- 徽章
- 面包屑导航
- Bubble
- 按钮
- 按钮组
- 日历 Calendar
- 卡片
- 轮播图
- 图表 Chart
- 复选框
- 折叠面板
- 组合框
- 命令
- 上下文菜单
- 数据表格 Data Table
- 日期选择器 Date Picker
- 对话框 Dialog
- 方向
- 抽屉
- 下拉菜单
- 空状态
- 字段
- 悬停卡片
- 输入
- 输入组
- Input OTP
- 项目
- Kbd
- 标签
- 标记
- 菜单栏
- 消息
- 消息滚动器
- 原生选择框
- 导航菜单 Navigation Menu
- 分页
- 弹出框
- 进度 Progress
- 单选框组
- 可调整大小
- 滚动区域 Scroll Area
- 选择框
- 分隔符 Separator
- 侧边栏 Sheet
- 侧边栏 Sidebar
- 骨架屏
- 滑块
- Sonner
- 加载指示器 Spinner
- 开关
- 表格
- 标签页 Tabs
- 文本域
- 吐司
- 切换按钮 Toggle
- 切换组
- 提示 Tooltip
- 排版
import { FileCodeIcon, XIcon } from "lucide-react"
import {Attachment 组件用于显示文件或图片附件及其媒体、名称和元数据,并可带有可选的操作和上传状态。可将其用于聊天编辑器、消息线程和上传列表中的文件与图片。
安装#
pnpm dlx shadcn@latest add attachment
用法#
import {
Attachment,
AttachmentAction,
AttachmentActions,
AttachmentContent,
AttachmentDescription,
AttachmentMedia,
AttachmentTitle,
} from "@/components/ui/attachment"<Attachment>
<AttachmentMedia>
<FileTextIcon />
</AttachmentMedia>
<AttachmentContent>
<AttachmentTitle>sales-dashboard.pdf</AttachmentTitle>
<AttachmentDescription>PDF · 2.4 MB</AttachmentDescription>
</AttachmentContent>
<AttachmentActions>
<AttachmentAction aria-label="移除 sales-dashboard.pdf">
<XIcon />
</AttachmentAction>
</AttachmentActions>
</Attachment>组成#
使用以下组合来构建附件:
Attachment
├── AttachmentMedia
├── AttachmentContent
│ ├── AttachmentTitle
│ └── AttachmentDescription
├── AttachmentActions
│ └── AttachmentAction
└── AttachmentTrigger使用 AttachmentGroup 将多个附件布局为可滚动的行:
AttachmentGroup
├── Attachment
└── Attachment功能#
- 通过
AttachmentMedia支持图标和图片媒体 - 上传状态:
idle、uploading、processing、error和done,带有内置样式,并在进行中显示闪烁效果 - 三种尺寸以及横向或纵向布局
- 全卡片的
AttachmentTrigger,可打开链接或对话框,同时操作按钮仍可独立点击 - 可滚动、带吸附效果的
AttachmentGroup,并带有边缘渐隐效果 - 通过各部分的
className属性可自定义样式
示例#
图片#
在 AttachmentMedia 上设置 variant="image",并在其中渲染一个 <img>。使用 orientation="vertical" 将媒体堆叠在内容上方。
import { XIcon } from "lucide-react"
import {状态#
设置 state 以反映上传生命周期。uploading 和 processing 会让标题显示闪烁效果,而 error 会切换为破坏性样式。
import {
CheckIcon,
ClockIcon,尺寸#
使用 size 在 default、sm 和 xs 之间切换。
import { FileTextIcon } from "lucide-react"
import {分组#
将附件包裹在 AttachmentGroup 中,以将它们布局为一个可水平滚动、带吸附效果的行,并带有边缘渐隐。
import {
FileCodeIcon,
FileTextIcon,触发器#
添加 AttachmentTrigger,让整个卡片打开链接或对话框。它会填充卡片中动作按钮后方的区域,因此这些动作仍然可以点击。
import { CopyIcon, FileSearchIcon, XIcon } from "lucide-react"
import {<Dialog>
<Attachment>
{/* 媒体、内容、操作 */}
<DialogTrigger asChild>
<AttachmentTrigger aria-label="预览 research-summary.pdf" />
</DialogTrigger>
</Attachment>
<DialogContent>{/* ... */}</DialogContent>
</Dialog>无障碍#
AttachmentAction 会渲染一个 Button,而 AttachmentTrigger 会渲染一个真正的 <button>(或者通过 asChild 使用你的元素)。请遵循下面的指导,以确保它们都能被操作并被正确播报。
为仅图标操作添加标签#
AttachmentAction 通常只有图标,因此请为每个操作提供一个 aria-label,描述该操作及其目标。
<AttachmentAction aria-label="移除 sales-dashboard.pdf">
<XIcon />
</AttachmentAction>为触发器添加标签#
AttachmentTrigger 会在没有自身文字内容的情况下覆盖卡片,因此请为它添加一个 aria-label,说明激活它会执行什么操作。
<AttachmentTrigger asChild>
<a
href={url}
target="_blank"
rel="noreferrer"
aria-label="打开 workspace.png"
/>
</AttachmentTrigger>触发器位于堆叠顺序中操作按钮的后面,因此 AttachmentAction 和 AttachmentTrigger 不会互相阻挡——两者仍然可以分别聚焦和点击。
键盘滚动#
AttachmentGroup 会水平滚动。当其中的附件具有交互性时:触发器或操作按钮,键盘用户可以通过 Tab 键切换到屏幕外的项目。对于仅展示用途的一排附件,可以通过添加 tabIndex={0}、role="group" 和 aria-label 让该组本身也可聚焦并可滚动。
不仅仅依赖颜色传达含义#
error 状态使用的是危险色。请将失败原因保留在 AttachmentDescription 中,这样该状态就不会只通过颜色来传达。
API 参考#
Attachment#
根附件容器。
| Prop | Type | Default | Description |
|---|---|---|---|
state | "idle" | "uploading" | "processing" | "error" | "done" | "done" | 上传状态。驱动样式和闪烁效果。 |
size | "default" | "sm" | "xs" | "default" | 附件大小。 |
orientation | "horizontal" | "vertical" | "horizontal" | 将媒体放在内容旁边或上方。 |
className | string | - | 应用于根元素的附加类。 |
AttachmentMedia#
用于图标或图片预览的媒体槽位。
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "icon" | "image" | "icon" | 媒体是图标还是 <img>。 |
className | string | - | 应用于媒体槽位的附加类。 |
AttachmentContent#
包裹标题和描述。
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | 应用于内容槽位的附加类。 |
AttachmentTitle#
附件名称。当附件处于 uploading 或 processing 状态时会显示闪烁效果。
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | 应用于标题的附加类。 |
AttachmentDescription#
文件类型、大小或上传状态等次要元数据。
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | 应用于描述的附加类。 |
AttachmentActions#
一个或多个操作的容器,右对齐到附件末尾。
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | 应用于操作区域的附加类。 |
AttachmentAction#
一个操作按钮。渲染为 Button,并接受其全部属性。
| Prop | Type | Default | Description |
|---|---|---|---|
size | Button["size"] | "icon-xs" | 按钮大小。 |
...props | React.ComponentProps<typeof Button> | - | 传递给底层 Button 的属性。 |
AttachmentTrigger#
覆盖整张卡片、用于激活附件的叠加层。默认渲染为 <button>。
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | 作为子元素渲染,例如链接。 |
...props | React.ComponentProps<"button"> | - | 传递给触发元素的属性。 |
AttachmentGroup#
以可水平滚动、可吸附的行布局排列附件。
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | 应用于组的附加类。 |