0014. フロントエンド技術選定 (Vite + React + Tailwind + shadcn、ただし Select は native)¶
- ステータス: Accepted(実装済み)
- 関連: 0001 モノレポ構成 / 0013 「準備中」機能のゲーティング / 0015 品質ゲート
コンテキストと課題¶
Web フロント (apps/web) は、業務データの表示・編集 (一覧/フォーム/ダッシュボード) を多く持つ
管理画面。サーバ状態の同期、フォームのバリデーション、再利用可能な UI、ダーク/ライト両対応が要る。
モダンで枯れた組み合わせを選び、デザインシステムを一貫させたい。
決定¶
Vite + React 19 + TypeScript + Tailwind CSS v3 + shadcn/ui ベースのコンポーネント を採用する。 サーバ状態は React Query、フォームは React Hook Form + Zod。
- ビルド/言語: Vite
^6/ React^19.1/ TypeScript^5.7。 - スタイル: Tailwind CSS v3 (
^3.4.17)、darkMode: ['class']、tailwindcss-animate。テーマは HSL の CSS 変数で定義 (フォントは Geist / Noto Sans JP)。 - UI: shadcn/ui スタイル (コンポーネントをリポジトリに取り込む方式)。プリミティブとして Radix を
一部利用 (
@radix-ui/react-dialog/react-alert-dialog/react-label/react-slot)。 - サーバ状態 / 表:
@tanstack/react-query^5/@tanstack/react-table^8。 - フォーム / 検証:
react-hook-form^7+zod^3(共有スキーマは@workspace/shared)。
例外: Select は shadcn ではなく native <select>¶
shadcn の Select は Radix UI 依存を増やすため採用せず、native <select> を Tailwind でスタイルした
簡易版 を使う (components/ui/select.tsx)。SVG のシェブロンを背景画像で付け、value/onChange は
通常の HTML select として扱う。
ダークモードと native コントロールの可視化 (color-scheme)¶
ダーク時に native フォームコントロール (<select> の選択値/option リスト、日付・数値 input のピッカー、
スクロールバー等) をテーマに追従させるため、index.css で color-scheme を宣言する:
これが無いと、.dark でブラウザが light スキームの文字色で描画し、dark に塗った背景に対し
dark-on-dark となって「選択した文字列が見えない」症状になる。
影響 (Consequences)¶
良い点¶
- 枯れたモダン構成で、React Query (サーバ状態) と RHF+Zod (フォーム) により状態/検証の定型が安定する。 Zod スキーマは API/Mobile と共有できる (ADR 0001)。
- shadcn を「取り込み方式」で使うため、コンポーネントを完全に制御でき、デザインシステムを統一しやすい。
color-schemeの宣言で native コントロールがダークでも可視になり、Select の依存も増やさずに済む。
トレードオフ / 注意点¶
- native
<select>は shadcn の Radix Select に比べ、option の自由なレンダリング (アイコン/装飾) が できない。代わりに依存が減り、モバイルのネイティブ挙動が得られる。サイズ調整に癖があり、小さい高さ (例h-8) では文字が見切れることがある (適切な高さを使う)。 - shadcn の取り込み方式は 手動更新。上流の改善を取り込むには各コンポーネントを更新する必要がある。
- React 19 / Tailwind v3 という比較的新しめのバージョンに追従するコストがある。
- テスト環境では React のインスタンスが二重化しうるため、コンポーネント描画テストは
vitest.configの alias 固定が必要 (ADR 0015)。
根拠 (典拠)¶
apps/web/package.json:16-41— vite^6.0.7/ react^19.1.0/ typescript^5.7.2/ tailwindcss^3.4.17/@tanstack/react-query^5/@tanstack/react-table^8/react-hook-form^7/zod^3/@radix-ui/*。apps/web/tailwind.config.ts:5-6,90—darkMode: ['class']/ content /tailwindcss-animate。apps/web/src/components/ui/select.tsx:4-34— native<select>を採用する理由のコメントと実装。apps/web/src/index.css:17-24,58-60—:root { color-scheme: light }/.dark { color-scheme: dark }と理由のコメント。README.md:13-15— Biome 採用 (ESLint/Prettier 不採用)、Web = Vite + React + TailwindCSS + shadcn/ui。