Attachment
添付ファイル 1 件の表示を表現する shadcn/ui Attachment 相当の部品です(参照軸はイシュー #2001)。fandhe-frontend-headless-ui の attachment mod が構造・アクセシビリティ(WAI-ARIA)・表示状態(data-*)のみを提供する unstyled 部品で、root / media / content / name / meta / progress / actions / action の 8 anatomy パーツを持ちます。既存の File Upload(選択・ドロップの入力側部品)とは異なり、本部品は「表示側」を担います。状態機械を持たない静的部品です。
root は variant(file / image)・state(idle / uploading / error)・disabled の props を受け取り、それぞれ data-variant / data-state / data-disabled(存在属性)として出力します。会話系部品(message / bubble / attachment / marker)が共有する data-role / data-align は意図的に持ちません。添付ファイルは常に message / bubble の content スロット内に置かれ、整列はその親から継承する設計です。
media は画像プレビューまたは種別アイコンを children として受けるスロットで、独自の data-variant は持ちません([data-variant="image"] [data-part="media"] の子孫セレクタで分岐します)。content は name / meta を束ねるスロットです。name / meta は整形済み文字列を children で受け取るだけのスロットであり、byte → KB 変換等の数値・単位整形は行いません(数値・日時整形は UI コンポーネント層の責務外という既定判断の系です)。
progress は attachment scope の単純なスロットです。fandhe-frontend-headless-ui の Progress(data-scope="progress")のパーツ(root / track / range 等)をそのまま入れ子にする契約で、両 scope は独立して残ります。actions はアクションボタン群を束ねるコンテナで、action は削除等の個別アクション(ネイティブ <button type="button">)です。label を渡すと aria-label を出力し(空文字列のときは省略します)、disabled はネイティブ disabled と data-disabled の両方に反映します。削除処理そのものはアプリケーション側の責務です。
アクセシビリティ
actionはtype="button"を固定付与し、フォーム内配置時の意図しない submit を防ぎます。actionのlabelが空文字列でないときのみaria-labelを出力します。アイコンのみのボタンでは必ずlabelを渡してください。actionのdisabledはネイティブdisabled(ブラウザ標準の Space/Enter 抑止)とdata-disabledの両方に反映します。
fandhe-frontend-pre-styled-ui に対応するスタイル済み部品があります。Themes 版は Attachment を参照してください。
自前 CSS の最小例:
[data-scope="attachment"][data-part="root"] {
display: flex;
gap: 0.5rem;
padding: 0.5rem;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
}
[data-scope="attachment"][data-part="root"][data-disabled] {
opacity: 0.5;
}
[data-scope="attachment"][data-part="root"][data-state="error"] {
border-color: #dc2626;
}
[data-scope="attachment"][data-part="content"] {
display: flex;
flex-direction: column;
}関連 API: fandhe-frontend-headless-ui API
Demo
枠線・余白は docs サイト側のデモ枠であり、fandhe-frontend-headless-ui 自体はスタイルを持ちません。
Features
- 添付ファイル 1 件の表示を表現する 8 anatomy パーツ(root/media/content/name/meta/progress/actions/action)を提供する(attachment.rs)。イシュータイトルの 7 パーツに加え、削除等の個別操作を担う action を追加した(attachment.rs「イシュータイトルとの差分」節)。状態機械を持たない静的部品であり wasm-full 側の配線は不要。
- root へ data-variant(file/image)・data-state(idle/uploading/error)・data-disabled(存在属性)を付与する。会話系 4 部品(message/bubble/attachment/marker)の共通語彙(data-role/data-align)は意図的に持たない(attachment.rs「会話系 4 部品の共通語彙への不追随」節)。
- progress は attachment scope の単純なスロットであり、呼び出し側が crate::progress::Progress のパーツ(root/track/range 等)を入れ子にする契約とする(attachment.rs「progress は attachment scope のスロット」節。data-scope="progress" は attachment scope を上書きしない)。
- name/meta は整形済み文字列を children で受け取るだけのスロットであり、byte → KB 変換等の数値・単位整形は行わない(docs/policy/intentional-non-adoption.md §3.23 と同じ判断軸、attachment.rs参照)。参照実体は shadcn/ui の Attachment のみ(ark-ui・chakra-ui・Radix に対応部品なし、参照軸 #2001)。size/orientation・trigger(カード全面クリックオーバーレイ)・group(横スクロールコンテナ)は意図的に非採用(attachment.rs「shadcn/ui 実 API との意図的差分」節)。
Anatomy
root
media
content
name
meta
actions
action
progressAPI Reference
Arguments
| Name | Type | Default | Description |
|---|---|---|---|
root: props.variant | AttachmentVariant | AttachmentVariant::File | 表示形態(file/image)。data-variant へ出力する(attachment.rs)。 |
root: props.state | AttachmentState | AttachmentState::Idle | アップロード状態(idle/uploading/error)。data-state へ出力する(attachment.rs)。 |
root: props.disabled | bool | false | true のとき data-disabled 存在属性を付与する(attachment.rs)。 |
action: label | &str | "" | 空でなければ aria-label へ出力する(attachment.rs)。 |
action: disabled | bool | false | true のときネイティブ disabled と data-disabled の両方を出力する(attachment.rs)。 |
Data Attributes
| Part | Attribute | Observed Values |
|---|---|---|
action | data-disabled | (値なし) |
root | data-disabled | (値なし) |
root | data-state | error, idle, uploading |
root | data-variant | file, image |
Examples
Uploading with progress
画像プレビュー + アップロード進捗(Progress の入れ子)を表示する例です。
Error with delete action
アップロード失敗状態と削除アクション(aria-label 付き button)の例です。
自前 CSS の最小例
data-scope/data-part/data-state/data-disabled 属性セレクタでスタイルを当てる例です。
利用者が data-scope / data-part / data-state / data-disabled 属性セレクタで自前 CSS を当てる最小例です。headless-ui 自体はスタイルを持ちません。
[data-scope="attachment"][data-part="root"] {
display: flex;
gap: 0.5rem;
padding: 0.5rem;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
}
[data-scope="attachment"][data-part="root"][data-disabled] {
opacity: 0.5;
}
[data-scope="attachment"][data-part="root"][data-state="error"] {
border-color: #dc2626;
}
[data-scope="attachment"][data-part="content"] {
display: flex;
flex-direction: column;
}
Accessibility
Keyboard Interactions
| Key | Description |
|---|---|
| (なし) | root/media/content/name/meta/progress/actions はいずれもキー操作を提供しない静的コンテナである。action はネイティブ button のため Space/Enter で押下できる(attachment.rs)。 |
WAI-ARIA
| Attribute | Description |
|---|---|
| aria-label(action) | label が空でなければ action パーツへ出力する(attachment.rs「actions/action」節)。 |
| disabled(action、ネイティブ) | disabled 引数が true のとき action パーツへネイティブ disabled と data-disabled の両方を出力する(attachment.rs)。 |