Vercel の UI SDK 0.1.0-beta.2 上に構築。API は変わる可能性があります。
File input
Vercel の UI SDK で作るファイル入力。ドロップゾーン、貼り付け、種類とサイズのチェック、理由つきの却下ファイル、画像プレビュー、フォーム対応。
- フォームのコンポーネント
- 14 個のパーツ
- 12 個の例
@tabler/icons-react@ui-sdk/core@ui-sdk/reactclass-variance-authority
Drop files here
Images or PDFs, up to 5 files of 5 MB each. You can paste them too.
pnpm dlx shadcn@latest add https://hextaui.com/r/ui-sdk-file-input.jsonコンポーネント、HextaUIのテーマトークン、依存するHextaUIコンポーネントを追加します。
まだ追加していない場合は、グローバルCSSにテーマトークンを追加してください。
依存関係をインストールします。
pnpm add @ui-sdk/react@0.1.0-beta.2 @ui-sdk/core@0.1.0-beta.2 @tabler/icons-react class-variance-authority cn次のコードをコピーしてプロジェクトに貼り付けてください。
components/ui/ui-sdk-file-input.tsx components/ui/button.tsx インポートパスは、お使いのプロジェクト構成に合わせて更新してください。
UI SDK は ui-sdk というカスケードレイヤーに少しだけ独自の CSS を追加します。自分のクラスが優先されるよう、グローバルスタイルシートの先頭、Tailwind の import より上でこのレイヤーを宣言してください。
ファイル入力は、選んだ・ドロップした・貼り付けたファイルを保持し、フォームと一緒に送信します。アップロードはアプリ側の仕事です。子要素なしの FileInputItem は、リストのファイルごとにプレビュー・名前・サイズ・削除ボタンのそろった行を描きます。
accept、サイズ、件数、validate のチェックはブラウザだけで動き、ファイルが外された理由を早めに伝えます。誰でも回避できるので、アップロードはすべてサーバーで改めて確認してください。
accept には MIME タイプ、ワイルドカード、拡張子を指定できます。maxFiles、minSize、maxSize で上限を決め、validate で独自のチェックを足します。FileInputRejections は、外されたファイルをすべての理由とともに、次に受け入れられるファイルまで一覧します。
FileInputItemPreview は、ファイルがなくなると破棄するオブジェクト URL から画像を、ほかの種類にはアイコンを表示します。layout="grid" では各ファイルが正方形のタイルになります。
トリガーだけでもシステムのファイル選択を開けます。multiple がなければ新しいファイルが今のファイルを置き換え、ルートの子要素は状態を受け取る関数にできます。
variant="composer" ではドロップゾーンがメッセージ欄を囲むカードになり、layout="chips" でファイルをコンパクトなチップとして並べます。pasteTarget はテキストエリアに貼り付けたスクリーンショットを受け取り、貼り付けたテキストはテキストのままです。
target="document" と variant="overlay" を指定すると、ファイルがウィンドウ上でドラッグされている間ゾーンがページを覆い、どこにドロップしても受け取ります。別のゾーンへのドロップはそのゾーンのものです。
directory はフォルダごと選び、multiple を有効にします。項目名にはフォルダ内のパスが表示されます。
value と onValueChange を渡します。createFileInputController() のコントローラーなら、どのボタンからでも選択画面を開き、ファイルを消したり足したりできます。
name があれば、ページのハイドレーション前でもネイティブのファイル入力からファイルが送信されます。却下されたファイルは送信されず、フォームのリセットでリストは空になります。
invalid はドロップゾーンとトリガーに印を付け、トリガーがスクリーンリーダーに伝えます。トリガーの aria-describedby をメッセージに向けてください。
行とドロップゾーンは左右反転し、ファイル名は自身の向きを保ち、サイズは渡したロケールで書式化されます。
| キー | アクション |
|---|---|
| Tab | トリガーへ移り、次にリストの、最後にフォーカスしたファイルか先頭のファイルへ移ります。 |
| EnterSpace | トリガーからファイル選択を開きます。 |
| ↑↓←→ | リスト内のファイル間を移動します。 |
| HomeEnd | 最初または最後のファイルへ移動します。 |
| DeleteBackspace | フォーカス中のファイルを削除し、次のファイルにフォーカスします。 |
| ⌘V | フォーカスがドロップゾーンかその貼り付け先にあるとき、ファイルを貼り付けます。 |
ドロップゾーンはコントロールではないので、キーボードやスクリーンリーダーの利用者のために、必ず横にトリガーを置いてください。リストはひとつのタブストップです。削除ボタンは「Remove photo.png」のようにファイル名で名付けられ、項目上の Delete で同じことができるため、タブ順には入りません。
受け入れ・削除・却下されたファイルは、英語で polite なライブリージョンから読み上げられます。自分の言語にするには announcement を、却下理由には FileInputRejections に getReasonLabel を渡します。ドロップゾーンのアイコンが浮き上がるのも、新しい行がフェードインするのも、モーションが許可されているときだけです。
各パーツは同名の UI SDK パーツをラップし、render やパーツの状態を受け取る関数にもできる className を含むすべての props を受け付けます。
| プロパティ | 型 | デフォルト |
|---|---|---|
value | File[] | – |
defaultValue | File[] | [] |
onValueChangedetails には理由と、追加・削除・却下されたファイルが入ります。 | (value: File[], details) => void | – |
onRejectファイルがチェックに通らなかったとき、ひとつも受け入れられなくても実行されます。 | (rejected: FileRejection[], details) => void | – |
accept | string | string[] | – |
multiple | boolean | false |
maxFiles | number | – |
maxSizeバイト単位。 | number | – |
minSizeバイト単位。 | number | – |
validate組み込みのチェックの後で、ファイルを却下する理由を返します。 | (file: File) => string | null | – |
directory | boolean | false |
captureスマートフォンではカメラを開きます。 | "user" | "environment" | boolean | – |
invalid | boolean | false |
disabled | boolean | false |
required | boolean | false |
name | string | – |
form | string | – |
announcement変更後にスクリーンリーダーが読み上げる内容。 | (change) => string | null | – |
controllercreateFileInputController() で作成。 | FileInputController | – |
children | ReactNode | (state) => ReactNode | – |
| 属性 | 説明 |
|---|---|
data-slot="file-input" | CSS でファイル入力を指定します。 |
data-dragging | ファイルがいずれかのドロップゾーン上でドラッグされている間に付きます。 |
data-invalid | 無効なときに付きます。 |
data-required | ファイルが必須のときに付きます。 |
data-disabled | 無効のときに存在します。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
variant破線のゾーン、メッセージ入力欄を包むカード、またはドラッグ中に出る全画面のオーバーレイ。 | "default" | "composer" | "overlay" | "default" |
target | "element" | "document" | "element" |
pasteTarget貼り付けたファイルを受け取る別の場所。 | "document" | string | Element | () => Element | – |
render | ReactElement | (props, state) => ReactElement | – |
| 属性 | 説明 |
|---|---|
data-slot="file-input-dropzone" | CSS でドロップゾーンを指定します。 |
data-variant | バリアント:default、composer、overlay。 |
data-dragging | ファイルがその上でドラッグされている間に付きます。 |
data-drag-accept | ドラッグ中のファイルが種類と数から見て受け入れられそうな間に付きます。 |
data-drag-reject | ドラッグ中のファイルに受け入れない種類があるか、数が多すぎる間に付きます。 |
data-disabled | 無効のときに存在します。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
variant | Button variant | "outline" |
size | Button size | "sm" |
controllerツールバーの中など、ファイル入力の外にあるトリガーをつなぎます。 | FileInputController | – |
render | ReactElement | (props, state) => ReactElement | – |
| プロパティ | 型 | デフォルト |
|---|---|---|
layout行、正方形の画像タイル、またはコンパクトなチップ。項目の見た目はここから決まります。 | "list" | "grid" | "chips" | "list" |
render | ReactElement | (props, state) => ReactElement | – |
| 属性 | 説明 |
|---|---|
data-slot="file-input-list" | CSS でリストを指定します。 |
data-layout | レイアウト:list、grid、chips。項目にも付きます。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
children既定はプレビュー、名前、サイズ、削除ボタン。状態にはファイルとそのインデックスが入ります。 | ReactNode | (state) => ReactNode | – |
render | ReactElement | (props, state) => ReactElement | – |
| 属性 | 説明 |
|---|---|
data-slot="file-input-item" | CSS でファイルの行を指定します。 |
data-disabled | 無効のときに存在します。 |
| 属性 | 説明 |
|---|---|
data-slot="file-input-item-preview" | CSS でプレビューを指定します。 |
data-kind | 画像プレビューなら image、ファイル種別のアイコンなら icon。 |
| プロパティ | 型 | デフォルト |
|---|---|---|
localeサイズ(2.4 kB など)をこのロケールで書式化します。既定はブラウザのロケールです。 | string | – |
| プロパティ | 型 | デフォルト |
|---|---|---|
children既定は X アイコンです。 | ReactNode | – |
render | ReactElement | (props, state) => ReactElement | – |
| プロパティ | 型 | デフォルト |
|---|---|---|
getReasonLabel各理由に名前を付けます。既定は英語で、「Larger than 5 MB」のようになります。 | (reason, rules, rejection) => string | – |
| 属性 | 説明 |
|---|---|
data-slot="file-input-rejections" | CSS で却下されたファイルのリストを指定します。 |
- Buttonすべてのバリアントとサイズのボタンです。読み込み、成功、エラーのフローを内蔵し、高速なリクエストではスピナーを省略します。
- Calendar単一、範囲、複数選択に対応する日付グリッドです。月のスライド、範囲のプレビュー、タッチしやすいサイズの日付セルを備えています。
- Checkboxチェックが描かれるように表示されるチェックボックスです。中間状態の親、グループ、ホバーを共有するラベルに対応します。
- Comboboxチップ、グループ、非同期の結果に対応した、絞り込み可能なセレクトです。入力に合わせてポップアップのサイズが変わります。
- Date picker押すとポップオーバーでカレンダーを開くボタンです。スマートフォンではボトムシートになり、単一の日付も範囲も選べます。
- Fieldコントロールに紐付いたラベル、説明、エラーです。バリデーション状態とフォーム向けのレイアウトを備えています。