Attachment
アップロード向けのファイルカードと画像カードです。進捗、状態、操作、カード全体のトリガーに対応し、名前は拡張子を保ったまま表示されます。
pnpm dlx shadcn@latest add https://hextaui.com/r/attachment.jsonコンポーネント、HextaUIのテーマトークン、依存するHextaUIコンポーネントを追加します。
まだ追加していない場合は、グローバルCSSにテーマトークンを追加してください。
依存関係をインストールします。
pnpm add @base-ui/react @tabler/icons-react class-variance-authority cn次のコードをコピーしてプロジェクトに貼り付けてください。
components/ui/attachment.tsx components/ui/aspect-ratio.tsx components/ui/skeleton.tsx components/ui/button.tsx components/ui/progress.tsx components/ui/scroll-area.tsx lib/motion.ts インポートパスは、お使いのプロジェクト構成に合わせて更新してください。
画像
<AttachmentMedia /> に variant="image" を指定すると、読み込み中にシマーする正方形のサムネイルが表示されます。プレビューを上に置くタイルにするには、orientation="vertical" を設定します。
状態
state はアップロードのライフサイクル全体をカバーします。待機中のファイルには破線の枠線が付き、アップロード中と処理中のタイトルはシマーし、エラー時はメディアと説明が赤くなります。
アップロードの流れ
state="uploading" のときに progress を渡すと、下端に細いプログレスバーが描画されます。画像のプレビューは、アップロードが完了するまで暗く表示されます。
サイズ
size はパディング、メディア、テキストをまとめて拡大縮小し、内側の角をカードと同心に保ちます。
長い名前
長いファイル名は拡張子の手前で省略されるため、.pdf と .zip を見分けられます。名前にホバーすると全体を読めます。
グループ
<AttachmentGroup /> は、添付ファイルを横スクロールする 1 行に並べます。端はフェードし、項目は所定の位置にスナップします。
トリガー
<AttachmentTrigger /> はカード全体をクリック可能にします。たとえばプレビューやリンクを開くときに使え、カード上のアクションは独立したままです。aria-label を付けてください。
コンポーザー
ページの読み込み後に追加されたファイルはポップインし、ファイルが削除されると、残りの行がなめらかにスライドして詰まります。
壊れた画像
画像のプレビューの読み込みに失敗すると、ファイルアイコンにフォールバックします。
ストレステスト
狭いカラムに敵対的な名前、60 ミリ秒ごとのランダムな状態、1 つのグループに 200 項目。何もはみ出さず、レイアウトは保たれます。
右から左
メディア、コンテンツ、アクションは反転し、プログレスバーは開始側の端から伸びます。
| キー | アクション |
|---|---|
| Tab | 各アクション、次にトリガーへフォーカスを移動します。縦長タイルの隠れたアクションは、フォーカスがカードに入ると表示されます。 |
| EnterSpace | フォーカス中のアクションまたはトリガーを実行します。 |
- アップロード中、プログレスバーには
role="progressbar"が付き、タイトルによってラベル付けされます。 - 文字列のタイトルにはフルネームを持つ
title属性が付くため、省略された名前も読めます。 - アイコンのみのアクションとトリガーにはテキストがないため、ファイル名を示す
aria-labelを必ず付けてください。 - モーションの低減が有効な場合、添付ファイルはポップインせずに表示され、プログレスバーはイージングせずに切り替わり、グループは即座にリフローします。
グループ、アクション、トリガーを除くすべてのパーツは、プレーンな要素をレンダリングし、その属性を受け付けます。カードのスタイルは attachmentVariants としてエクスポートされています。
| プロパティ | 型 | デフォルト |
|---|---|---|
state | "idle" | "uploading" | "processing" | "error" | "done" | "done" |
progress0 から 100。アップロード中のみ表示され、この範囲に丸められます。 | number | – |
size | "default" | "sm" | "xs" | "default" |
orientation | "horizontal" | "vertical" | "horizontal" |
| 属性 | 説明 |
|---|---|
data-slot="attachment" | CSSでカードを指定します。 |
data-state | 現在の状態。 |
data-size | 現在のサイズ。 |
data-orientation | 現在の向き。 |
data-slot="attachment-progress" | アップロード中に表示されるプログレスバー。 |
--attachment-radius | カードの角丸の半径。内側の角はこれをもとに算出されます。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
variantimage は、子要素を、ファイルアイコンのフォールバック付きの正方形の AspectRatio で包みます。 | "icon" | "image" | "icon" |
| 属性 | 説明 |
|---|---|
data-slot="attachment-media" | CSS でメディアを指定します。 |
data-variant | 現在のバリアント。 |
タイトルと説明を保持し、残りの幅を占める <div>。
| 属性 | 説明 |
|---|---|
data-slot="attachment-content" | CSS でコンテンツを指定します。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
children文字列は分割されるため、拡張子が省略されることはありません。 | ReactNode | – |
titleホバー時に表示されます。デフォルトはフルネームです。 | string | children |
id省略すると自動生成されます。プログレスバーのラベルとして使われます。 | string | – |
| 属性 | 説明 |
|---|---|
data-slot="attachment-title" | CSSでタイトルを指定します。 |
サイズ、種類、ステータス用の 1 行の <span>。スペースが足りなくなると省略されます。
| 属性 | 説明 |
|---|---|
data-slot="attachment-description" | CSSで説明を指定します。 |
アクションボタン用の <div>。縦長のタイルではプレビューの上に重なり、マウスのあるデバイスではホバー時またはフォーカス時に表示されます。
| 属性 | 説明 |
|---|---|
data-slot="attachment-actions" | CSS でアクションを指定します。 |
トリガーの上に配置される <Button />。Button のすべての props を受け付けます。
| プロパティ | 型 | デフォルト |
|---|---|---|
variant | ButtonVariant | "ghost" |
size | ButtonSize | "icon-xs" |
| 属性 | 説明 |
|---|---|
data-slot="attachment-action" | CSS でアクションを指定します。 |
カード全体を覆う不可視のレイヤー。ダイアログのトリガー、リンク、または任意のボタンと組み合わせて使います。
| プロパティ | 型 | デフォルト |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | <button type="button"> |
| 属性 | 説明 |
|---|---|
data-slot="attachment-trigger" | CSSでトリガーを指定します。 |
各添付ファイルにスナップし、項目の追加や削除時に行をアニメーションさせる横向きの <ScrollArea />。scrollbars を除く ScrollArea のすべての props を受け付けます。
| 属性 | 説明 |
|---|---|
data-slot="attachment-group" | CSSでグループを指定します。 |
data-slot="attachment-group-list" | 添付ファイルを保持する行。 |
- Aspect ratioメディアの読み込み前も形を保ち、読み込み中はシマー表示になり、メディアをフェードインさせ、失敗時はフォールバックを表示するボックスです。
- Buttonすべてのバリアントとサイズのボタンです。読み込み、成功、エラーのフローを内蔵し、高速なリクエストではスピナーを省略します。
- Motionすべてのコンポーネントがアニメーションに使うイージングカーブ、継続時間、モーション軽減のチェックと、サイズのモーフィングやスライドするハイライト用のフックです。
- Progressタスクの進み具合を示すバーまたはリングです。更新のたびに滑らかに動き、全体量が不明なときはスライドします。
- Scroll area最小限のスクロールバーを備えたネイティブスクロールです。端は続きがある側だけフェードし、最後の項目を半分で切って見せるピークも任意で使えます。
- Bubbleバリアント、グループ化された角、リアクション、インタラクティブなコンテンツの余地を備えたチャットのメッセージバブルです。
使用しているブロック
Attachment の上に構築されるブロック。
- Prompt Input最初は静かな1行で、入力に合わせてカードへ広がり、会話が始まると下へ移動するチャット入力欄です。Enterで送信でき、日本語や中国語の入力でも安全です。ファイルは貼り付け、ドロップ、選択でき、プレビュー、進捗、再試行に対応します。@でファイルを追加し、/でコマンドをカーソル位置のメニューから実行できます。数字キーで選べるモデルピッカー、Maxで動き出す推論量スライダー、コンテキストリング、リアルタイム波形つきの音声入力、ツールチップ、返信のストリーミング中に入力したメッセージのキュー、再読み込みしても残る下書きを備えています。
- Chat Threadコンポーザーを中心にした会話全体です。回答のストリーミング中も質問は上部に固定され、サイドのチェックポイントでメッセージ間を移動でき、すべての返信をコピー、編集、再試行、評価し、バージョン間で切り替えられます。返信はコードブロック、テーブル、引用を含むMarkdownとして描画され、思考、ツール呼び出し、Prompt Inputもそのまま組み込めます。