ダッシュボードデザイン
ルール
- サイドバー + メインコンテンツのレイアウト: 固定サイドバー(w-64)、余白付きの流動的なメインエリア
- サイドバーナビゲーション: アイコン+ラベルリンク、アクティブ状態のハイライト、モバイルで折りたたみ可能
- 上部のKPIカード行: レスポンシブグリッドに3~4枚のカード — メトリック名、値、トレンド(上昇/下降%)、スパークラインは任意
- データテーブル: ソート可能な列、検索/ステータスによるフィルタリング、ページネーション(デフォルト10~25行)
- ヘッドレステーブルロジックには
@tanstack/react-table を使用 — shadcn/ui Tableコンポーネントと組み合わせる
- レスポンシブ: サイドバーは
md ブレークポイントでハンバーガーメニューに折りたたみ、カードは1~2列に積み重なる
- ローディング状態: カード/テーブルの形状に合わせたスケルトンプレースホルダー — レイアウトシフトは発生させない
- ダッシュボードデータフィルタリング用の日付範囲ピッカー — デフォルトは過去30日間
レイアウト構造
┌──────────┬────────────────────────────┐
│ サイドバー │ ヘッダー / パンくずリスト │
│ ├────────────────────────────┤
│ ナビ │ KPIカード (3~4グリッド) │
│ リンク ├────────────────────────────┤
│ │ チャート / グラフ │
│ ├────────────────────────────┤
│ │ データテーブル │
└──────────┴────────────────────────────┘
パターン
function KPICard({ title, value, change }: { title: string; value: string; change: number }) {
return (
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium text-muted-foreground">{title}</CardTitle>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{value}</div>
<p className={cn("text-xs", change >= 0 ? "text-green-600" : "text-red-600")}>
{change >= 0 ? "+" : ""}{change}% 前回比
</p>
</CardContent>
</Card>
);
}
避けるべきこと
- 固定幅のメインコンテンツ — 常に利用可能なスペースを埋める流動的レイアウトを使用する
- ページネーションのないテーブル — データセットが大きいとパフォーマンスとユーザビリティが低下する
- ローディング/空状態の欠如 — 常にスケルトンまたは「データがありません」というメッセージを表示する
- 折りたためないサイドバー — モバイルユーザーはビューポートの全幅を必要とする
- 部分的なページ更新にローディングスピナーを使用する — 特定のセクションにはスケルトンを使用する
- KPIを詰め込みすぎる — 重要なメトリックを3~5個に絞り、残りは展開可能なセクションに配置する
- ゼロからサイドバーをカスタム実装する — shadcnのサイドバーコンポーネントを使用する
- アクションのない空状態 — 常にCTAを含める(「キャンペーンがまだありません。最初のキャンペーンを作成する →」)