Components

Attachment

Displays a file or image attachment with media, metadata, upload state, and actions.

Overview

横向布局:图标 media + 标题/描述 + 移除按钮,对应 shadcn 的默认 Attachment 组合。点 × 发出 AttachmentRemoveEvent。

GPUI · Live previewGPUI WASM

Installation

Attachment 是单个 Rust 文件(src/attachment.rs),用 gpui 的 div / canvas / PathBuilder 自绘,不依赖额外原语。复制到你的 crate,或下载完整示例直接运行。

Cargo.toml
[dependencies]gpui-kit = "0.6.6"# attachment.rs is a single styled component —# it uses gpui's div / canvas / PathBuilder# directly, no extra primitives needed.

Download runnable example

Terminal
# Download the runnable example crate, then:cargo run --locked -- --attachment# Other demos:cargo run --locked -- --attachment imagecargo run --locked -- --attachment statescargo run --locked -- --attachment sizescargo run --locked -- --attachment groupcargo run --locked -- --attachment trigger

Usage

builder 链式配置 media、标题、描述、上传状态与交互;把实体保留在宿主视图上,渲染时放进任意容器,事件用 cx.subscribe 订阅。

Example.rs
use justdo_command::attachment::{Attachment, AttachmentMedia, AttachmentState};// Keep the entity on your host view.let attachment = cx.new(|_| {    Attachment::new()        .media(AttachmentMedia::FileText)        .title("sales-dashboard.pdf")        .description("PDF · 2.4 MB")        .state(AttachmentState::Uploading { progress: 0.64 })});// In render: div().child(self.attachment.clone())

网页预览与桌面端运行同一份 Rust / GPUI 组件。

Composition

组合结构对齐 shadcn/ui 的 Attachment:Media / Content / Actions / Trigger,外加横向滚动的 Group。

Structure
Attachment                    card container├── AttachmentMedia           icon box or image thumbnail├── AttachmentContent         title + metadata column│   ├── AttachmentTitle       .title(..)│   └── AttachmentDescription .description(..)├── AttachmentActions         remove button -> AttachmentRemoveEvent└── AttachmentTrigger         .openable(true) -> AttachmentOpenEventAttachmentGroup               horizontal scroll row  .overflow_x_scroll() + .track_scroll(&handle)

Accessibility

Keyboard

  • Tab 沿页面 tab 序聚焦移除按钮,focus-visible 描边
  • Enter Space 触发 AttachmentRemoveEvent
  • Group 行用滚轮 / 触控板横向滚动,每张卡仍可通过 Tab 到达

Semantics

Error 状态除红色描边外始终带文字失败原因,不单靠颜色;trigger 遮罩避开操作列,移除按钮保持独立可点;processing 状态同步降标题对比度。

API Reference

组件实体暴露的方法与事件。

APISignatureNotes
Attachment::new()-> AttachmentCreates the entity content; state Done, horizontal layout.
.media(..)AttachmentMediaFileText | FileCode | Image line icons, or Photo thumbnail.
.title(..)impl Into<SharedString>File name heading.
.description(..)impl Into<SharedString>Metadata line: type · size, or a failure reason on error.
.state(..)AttachmentStateIdle | Uploading { progress } | Processing | Error | Done.
.size(..)AttachmentSizeDefault | Sm | Xs — Xs renders media + title only.
.vertical()-> SelfStacks media above content; action pinned top-right.
.removable(bool)boolShows the focusable × action (default true).
.openable(bool)boolAdds a card-wide trigger emitting AttachmentOpenEvent.
.dark(bool)boolDark color scheme for surface, text and borders.
AttachmentRemoveEvent{ name }Emitted on × press; subscribe with cx.subscribe.
AttachmentOpenEvent{ name }Emitted on card press when openable.
Example.rs
// Both events carry the attachment title.cx.subscribe(&self.attachment, |view, _a, event: &AttachmentRemoveEvent, cx| {    view.files.retain(|f| *f != event.name);    cx.notify();});cx.subscribe(&self.attachment, |view, _a, event: &AttachmentOpenEvent, cx| {    view.preview = Some(event.name.clone());    cx.notify();});

Source & inspiration

结构与视觉参考 shadcn/ui Attachment 。本页交互由 Rust / GPUI 绘制,基础样式来自 gpui-kit 。