UIXHERO

File Upload(ファイルアップロード)

ファイル選択・ドラッグ&ドロップ・進捗表示・エラーハンドリングを統合したコンポーネント。ユーザーが「今どの状態にあるか」を常に把握できる設計が品質の核心。

2026年2月28日
更新: 2026年8月28日
19
by Dengen Yosho(DGYS)

ユーザーのローカルファイルをシステムに取り込むコンポーネント。シンプルなボタン1つから始まるが、ドラッグ&ドロップ・進捗表示・エラーハンドリング・複数ファイル管理まで、状態が複雑に絡み合う高難度の

この記事を読むと、ファイル選択UIの形式選択・アップロード状態設計・エラー種別の表現・A11y要件が自分でできるようになります。


1. UI例(Preview / Live)

実装で見る(GunjoUI)

この部品を、デザインシステム GUNJO の実装で確かめられます。

2. 定義(Definition)

ユーザーのローカルファイルをシステムに送信するための複合コンポーネント。ファイル選択(クリックまたはドラッグ&ドロップ)・バリデーション(形式・サイズ)・進捗表示・エラー表示・ファイル管理(追加・削除)を統合する。

単純な <input type="file"> との違い:HTMLネイティブの <input type="file"> は最低限の機能のみ。File Upload コンポーネントは進捗・エラー・ドラッグ&ドロップ・プレビューなどをUIとして統合したもの。


3. 使い分け(When to use / When NOT to use)

3.1 When to use

  • ユーザーがローカルファイルをシステムにアップロードする必要がある場面(プロフィール画像・添付ファイル・書類提出など)
  • 複数ファイルの一括アップロードや、進捗をリアルタイムで確認させたい場面
  • ファイル形式・サイズの制限があり、即時バリデーションが必要な場面

3.2 When NOT to use

  • テキスト入力で代替できる場面(URLや文字列を入力させる場合)
  • アップロードが不要でファイルの選択結果だけが必要な場面(<input type="file"> で十分)

3.3 代替UI(Alternatives)

  • シンプルなファイル選択のみ → <input type="file"> ネイティブ
  • URL入力でのメディア追加 → Text Input
  • カメラ撮影でのアップロード → <input type="file" capture="environment">

4. 設計判断の核(Decision Principles)

アップロードの「今」をユーザーに常に見せる——選択・検証・送信・完了・エラーの全ての状態が明示されていること。

判断の優先順位:① → ② エラー種別の明示 → ③ 制約条件の事前告知 → ④ 復旧手順の提示

  • ファイルを選択した瞬間にファイル名とサイズを表示する(選択できたことの即時
  • (対応形式・最大サイズ・最大ファイル数)はアップロードゾーンに事前に明示する。エラーが起きてから知らせるのではなく、選択前に知らせる
  • エラーは「何が問題か」と「どう直すか」をセットで表示する(「エラー」だけでは不十分)
  • は「アップロード中」状態を示すだけでなく、完了・失敗でも状態を更新し続ける

5. 状態設計(States)

5.1 必須状態(Required)

  • Idle(待機):ファイルが選択されていない初期状態。制約条件と操作方法を表示
  • Selected:ファイルが選択された直後。ファイル名・サイズを表示し、バリデーション結果を即時フィードバック
  • Uploading:APIへの送信中。進捗バー(または不確定スピナー)で進行を示す
  • Done:アップロード完了。成功アイコンとを表示
  • Error:アップロード失敗またはバリデーション失敗。エラー理由と再試行手段を明示

5.2 条件付き状態(Conditional)

  • Dragging Over:ドラッグ&ドロップ操作中にゾーンがハイライトされる
  • Disabled:条件を満たすまでアップロード不可(最大ファイル数に達したなど)
  • Partial Error:複数ファイルの一部が成功・一部が失敗した混在状態
状態必須何を伝えるか
Idle操作方法と制約(形式・サイズ)を事前告知
Selected選択できたこと・バリデーション結果の即時フィードバック
Uploading今送信中であること・どれくらい進んだか
Done正常に完了したこと
Error何が問題で・どう修正すれば良いか
Dragging Overドロップできる場所であることを強調する
Disabledなぜアップロードできないかを伝える

6. バリエーション設計(Variants)

File Upload の形式は「ユーザーの操作」で選ぶ。

バリアント目的適した場面
Dropzoneドラッグ&ドロップ対応の大きなゾーン複数ファイル・大きなファイルの意識的なアップロード
Button onlyクリックで選択するシンプルな形式フォーム内の1項目として自然に溶け込む場合
With Preview選択後に画像サムネイルを表示画像アップロード(プロフィール・商品画像など)
Multi-file list複数ファイルをリスト管理書類提出・複数添付ファイル

禁止パターン:選択後に何も表示しない(「ファイルが選択されました」の確認なし) → アップロードできたのか否かが不明。


7. パターン集(Good / Bad / How to fix)

7.0 よく崩れる設計パターン(3つ)

  • 制約の後出し:ファイルを選択してアップロードボタンを押した後にはじめて「5MB以上は不可」と表示される → ユーザーは選ぶ前に知りたかった
  • 進捗の非表示:アップロード中にローダーも進捗バーもなく、UIが固まったように見える → ユーザーは「壊れた?」と思い再クリックする
  • エラーの曖昧さ:「アップロードに失敗しました」だけでは、サイズ問題か形式問題かネットワーク問題か判断できない

7.1 Bad(典型3つ)

  • 対応形式と最大サイズをDropzoneに書かず、制限外ファイルを選択した後にエラーを出す
  • アップロード中に進捗表示がなく、ボタンも押せたままで重複送信が発生する
  • <input type="file"> のネイティブUIだけで完結させ、選択後のフィードバックがゼロ

7.2 Good(対になる3つ)

  • Dropzone に「対応形式: JPEG, PNG, PDF(最大5MB)」を常時表示し、選択前に制約を伝える
  • アップロード開始と同時にプログレスバーを表示し、完了・エラーで状態を更新する
  • エラー時は「PDFのみ対応しています」「ファイルサイズが5MBを超えています。圧縮して再度お試しください」と原因と対処をセットで表示する

7.3 How to fix(手順)

  1. Dropzone / Button の近くに制約条件(形式・サイズ・件数)を書く
  2. ファイル選択直後にクライアントサイドバリデーションを実行し、エラーを即時表示する
  3. アップロード開始と同時に進捗UI(バーまたはスピナー)を表示し、ボタンを disabled にして重複送信を防ぐ
  4. 完了・エラーで状態を更新し、エラー時は再試行ボタンを提供する

8. ルール(Must / Better)

Must(守らないと壊れる)

Better(品質が跳ねる)


9. アクセシビリティ要件(必須)

Keyboard

  • Dropzone はキーボードでフォーカスでき、Enter または Space でファイル選択ダイアログを開けること
  • 各ファイルの削除ボタンは Tab でフォーカスでき、Enter/Space で削除できること

Focus

  • Dropzone・削除ボタンともにフォーカスリングを確保すること

Screen Reader

  • Dropzone に role="button"aria-label="ファイルをドラッグ&ドロップ、またはクリックして選択" を付与する
  • 進捗バーに role="progressbar" + aria-valuenow + aria-valuetext を付与する
  • エラーメッセージには role="alert" を付与してスクリーンリーダーに即時通知する
  • <input type="file"> 自体には aria-label を付与する
<!-- 基本パターン -->
<div
  role="button"
  tabindex="0"
  aria-label="ファイルをドラッグ&ドロップ、またはクリックして選択"
>
  <!-- Dropzone コンテンツ -->
</div>
<input type="file" aria-label="ファイルを選択" class="sr-only" />

<!-- 進捗バー -->
<div
  role="progressbar"
  aria-valuenow="45"
  aria-valuemin="0"
  aria-valuemax="100"
  aria-label="report.pdf のアップロード進捗"
></div>

<!-- エラーメッセージ -->
<p role="alert">ファイルサイズが5MBを超えています。圧縮して再度お試しください。</p>

Touch / Pointer

  • 削除ボタンのを44×44px以上確保する
  • モバイルではドラッグ&ドロップが難しいため、ボタンタップでのファイル選択(カメラロールなど)を必ず提供する

Contrast / Readability

  • エラーテキストは色と4.5:1以上のコントラスト比を確保する
  • Dropzone のボーダーと背景は3:1以上の比(WCAG 1.4.11)

10. 実装メモ(Implementation Notes)

  • ドラッグ&ドロップは onDragOvere.preventDefault() 必須)/ onDrop イベントで実装する。e.preventDefault() を忘れるとブラウザがファイルを直接開いてしまう
  • <input type="file">value はリセットできないため、同じファイルを再選択させたい場合は onChange 後に e.target.value = '' で値をクリアする
  • 大容量ファイルのアップロードは XMLHttpRequest(xhr.upload.onprogress)またはライブラリ(axios)を使うと進捗が取得できる。fetch API はでは進捗を取得できない
  • Radix UI / shadcn には標準の File Upload コンポーネントがないため、react-dropzone ライブラリが最もメンテナンスされた選択肢

11. 関連リンク


12. まとめ

File Upload の設計は「今どの状態にあるかを常にユーザーに見せる」ことに尽きます。迷ったら 4. 設計判断の核 に戻り、制約の事前告知・選択直後のフィードバック・進捗表示・エラーの明示の4点を確認してください。ネイティブの <input type="file"> はスタートラインに過ぎません——状態管理とフィードバックを統合して初めて「使えるFile Upload」になります。

更新のお知らせ

サイトに載せていない実例や、新しい記事のお知らせはこちらで出しています。

読んだ内容を、自分の画面に当てるとき

UIXHEROは、記事を書くほかに、画面の検品・判定、デザインシステムの構築、実装と改善の伴走を受けています。何を頼めばいいか決まっていない段階の相談も、同じ窓口で受けます。

UIXHEROに頼めることを見る

※ 記事の内容についての質問や、書いてほしいテーマの要望も同じ窓口で受けています

記事をシェア

メールでお知らせを受け取る

最終更新: 2026年8月28日

この記事を書いた人

Dengen Yosho(DGYS)

Dengen Yosho(DGYS)

UI/UXデザイナー兼デザインエンジニア デザイン歴25年以上 情報設計〜UIデザイン〜React/TypeScriptによる実装までを一気通貫で担当 大手企業のDXプロジェクトや決済アプリ領域で、デザインリードとして改善と構築を経験 現在はフリーランスとして、プロダクトのUI/UX改善とデザインシステム構築を支援 長年の実務の中で感じてきたのは、 「良いUI」はセンスではなく、再現可能な判断の積み重ねであるということ UIXHEROは、 心理学や行動科学の知見を、現場で使える設計言語に翻訳するための場所 関心領域は「ユーザーの行動が変わるUI」 人の認知・注意・意思決定の構造を理解し、 “なぜそのUIが機能するのか”を言語化することを目指している

あわせて読みたい

この記事に関連する記事をご紹介します

Bar Chart(棒グラフ)

カテゴリごとの量を棒の長さで比べるチャート。ゼロ基線の扱い、並び順、縦横の選び方、しきい値の見せ方という設計判断と、色だけに頼らないアクセシビリティ要件を解説する。

2026年8月27日
18

Donut Chart(ドーナツチャート)

中央をくり抜いた円で構成比を示すチャート。中央に置く値の選び方、円グラフとの使い分け、リングの太さ、凡例の作りという設計判断と、色だけに頼らないアクセシビリティ要件を解説する。

2026年8月27日
17

Gauge Chart(ゲージチャート)

1つの値を範囲の中に置いて示す半円のチャート。範囲の両端に意味があるかという条件、しきい値の帯の設計、色だけで良否を伝えない書き方という設計判断とアクセシビリティ要件を解説する。

2026年8月27日
16

もっと深く知りたいですか?

ここに掲載されていないトピックについても、リクエストがあれば解説記事を追加します。 わかりにくい点や、具体的な事例について知りたいことがあれば教えてください。

リクエストを送る