diff --git a/DESIGN.md b/DESIGN.md index 1951e09d..a6fe2095 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -40,14 +40,14 @@ RoastPlus の主軸は「現場オペレーション重視」です。明るく 優先順位は次の順に固定します。 -| 優先 | 原則 | 内容 | -|------|------|------| -| 1 | 現場で迷わない | 画面を開いた瞬間に、今の状態と次の操作が分かる。 | -| 2 | ページごとの型を揃える | 同じ目的の画面は、ヘッダー、余白、最大幅、主要アクション位置、空状態を揃える。 | -| 3 | iPadで押しやすい | 現場iPad、タブレット、補助端末でのPWA利用を前提にし、44px以上のタッチ領域を確保する。 | -| 4 | 情報が一目で読める | 時間、担当、状態、次アクションは本文より強く見せる。 | -| 5 | コーヒーらしさは控えめに効かせる | コーヒーらしい色や演出は、業務理解を邪魔しない範囲で使う。 | -| 6 | 毎日使って疲れない | 強いアニメーション、過度なグラデーション、重い装飾は限定する。 | +| 優先 | 原則 | 内容 | +| ---- | -------------------------------- | ------------------------------------------------------------------------------------- | +| 1 | 現場で迷わない | 画面を開いた瞬間に、今の状態と次の操作が分かる。 | +| 2 | ページごとの型を揃える | 同じ目的の画面は、ヘッダー、余白、最大幅、主要アクション位置、空状態を揃える。 | +| 3 | iPadで押しやすい | 現場iPad、タブレット、補助端末でのPWA利用を前提にし、44px以上のタッチ領域を確保する。 | +| 4 | 情報が一目で読める | 時間、担当、状態、次アクションは本文より強く見せる。 | +| 5 | コーヒーらしさは控えめに効かせる | コーヒーらしい色や演出は、業務理解を邪魔しない範囲で使う。 | +| 6 | 毎日使って疲れない | 強いアニメーション、過度なグラデーション、重い装飾は限定する。 | --- @@ -55,14 +55,14 @@ RoastPlus の主軸は「現場オペレーション重視」です。明るく RoastPlus のページは、見た目ではなく「ユーザーが何をする画面か」で分類します。新しい画面を作るときは、まずこの6タイプのどれに当たるかを決めます。 -| タイプ | 主な用途 | 対象ページ例 | 推奨レイアウト | ヘッダー | 最大幅 | 主要アクション位置 | 使う共通UI | 避けること | -|--------|----------|--------------|----------------|----------|--------|--------------------|------------|------------| -| ホーム / ハブ | 機能選択 | ホーム | 2列中心の機能カード | ブランドヘッダー | `max-w-6xl` | カード全体を入口にする | `Card`, `ActionCard` | カード内説明を増やしすぎる | -| 一覧 / 管理 | 探す、追加、編集 | 担当表、スケジュール、欠点豆、生産記録、試飲一覧 | iPadではカード、広い画面はテーブルやグリッド | `FloatingNav` + タイトル | `max-w-4xl` から `max-w-7xl` | 上部右側、または下部固定 | `Card`, `Button`, `Tabs`, `EmptyState` | 検索、絞り込み、追加を離れた場所に置く | -| フォーム / 編集 | 入力して保存 | レシピ作成、試飲作成、設定入力、お問い合わせ | 縦積みフォーム | `FloatingNav` + タイトル | `max-w-2xl` または `max-w-lg` | 下部、右下、固定フッターのいずれか | `Input`, `Textarea`, `Select`, `Button`, `Card` | 危険操作を保存ボタンの近くに置く | -| 集中操作 / 実行 | 作業中に状態と次操作を見る | ドリップガイド、時計 | 固定または準固定画面 | 最小ナビ、固定ヘッダー | 画面全体 | 下部操作、中央に主要状態 | `Button`, `IconButton`, `ProgressBar` | 説明文やカードを増やしすぎる | -| 詳細 / 参照 | 読む、判断材料を見る | 欠点豆詳細、開発秘話、規約、履歴詳細 | 読み物レイアウト | `FloatingNav` + タイトル | `max-w-3xl` 前後 | 必要な場合のみ本文末尾 | `Card`, `Badge`, `Accordion` | 操作ボタンを主役にする | -| モーダル / 確認 | 短い判断、設定、確認 | 削除確認、フィルター、OCR確認、詳細設定 | 中央ダイアログ、またはモバイル下寄せ | モーダル内タイトル | `max-w-sm` から `max-w-md` | 下部にキャンセル、実行 | `Modal`, `Dialog`, `Button` | 長い内容や複雑な設定を詰め込む | +| タイプ | 主な用途 | 対象ページ例 | 推奨レイアウト | ヘッダー | 最大幅 | 主要アクション位置 | 使う共通UI | 避けること | +| --------------- | -------------------------- | ------------------------------------------------ | -------------------------------------------- | ------------------------ | ----------------------------- | ---------------------------------- | ----------------------------------------------- | -------------------------------------- | +| ホーム / ハブ | 機能選択 | ホーム | 2列中心の機能カード | ブランドヘッダー | `max-w-6xl` | カード全体を入口にする | `Card`, `ActionCard` | カード内説明を増やしすぎる | +| 一覧 / 管理 | 探す、追加、編集 | 担当表、スケジュール、欠点豆、生産記録、試飲一覧 | iPadではカード、広い画面はテーブルやグリッド | `FloatingNav` + タイトル | `max-w-4xl` から `max-w-7xl` | 上部右側、または下部固定 | `Card`, `Button`, `Tabs`, `EmptyState` | 検索、絞り込み、追加を離れた場所に置く | +| フォーム / 編集 | 入力して保存 | レシピ作成、試飲作成、設定入力、お問い合わせ | 縦積みフォーム | `FloatingNav` + タイトル | `max-w-2xl` または `max-w-lg` | 下部、右下、固定フッターのいずれか | `Input`, `Textarea`, `Select`, `Button`, `Card` | 危険操作を保存ボタンの近くに置く | +| 集中操作 / 実行 | 作業中に状態と次操作を見る | ドリップガイド、時計 | 固定または準固定画面 | 最小ナビ、固定ヘッダー | 画面全体 | 下部操作、中央に主要状態 | `Button`, `IconButton`, `ProgressBar` | 説明文やカードを増やしすぎる | +| 詳細 / 参照 | 読む、判断材料を見る | 欠点豆詳細、開発秘話、規約、履歴詳細 | 読み物レイアウト | `FloatingNav` + タイトル | `max-w-3xl` 前後 | 必要な場合のみ本文末尾 | `Card`, `Badge`, `Accordion` | 操作ボタンを主役にする | +| モーダル / 確認 | 短い判断、設定、確認 | 削除確認、フィルター、OCR確認、詳細設定 | 中央ダイアログ、またはモバイル下寄せ | モーダル内タイトル | `max-w-sm` から `max-w-md` | 下部にキャンセル、実行 | `Modal`, `Dialog`, `Button` | 長い内容や複雑な設定を詰め込む | --- @@ -117,83 +117,83 @@ RoastPlus では、色を直接指定せず、意味を持つセマンティッ ### 5.2 テーマ概要 -| 項目 | 内容 | -|------|------| -| テーマ数 | 7テーマ(`default`, `christmas`, `dark-roast`, `light-roast`, `matcha`, `caramel`, `dark`) | -| テーマ切替方法 | `` でCSS変数が自動切替 | -| カラー方針 | セマンティックトークン必須。ハードコードカラーは禁止 | -| スタイリング | Tailwind CSS v4 + CSS変数 | +| 項目 | 内容 | +| -------------- | ------------------------------------------------------------------------------------------- | +| テーマ数 | 7テーマ(`default`, `christmas`, `dark-roast`, `light-roast`, `matcha`, `caramel`, `dark`) | +| テーマ切替方法 | `` でCSS変数が自動切替 | +| カラー方針 | セマンティックトークン必須。ハードコードカラーは禁止 | +| スタイリング | Tailwind CSS v4 + CSS変数 | ### 5.3 背景色 -| Tailwindクラス | CSS変数 | default値 | 用途 | -|--------------|---------|-----------|------| -| `bg-page` | `--page` | `#F7F7F5` | ページ全体背景 | -| `bg-surface` | `--surface` | `#FFFFFF` | カード・セクション背景 | -| `bg-overlay` | `--overlay` | `#FFFFFF` | モーダル・ダイアログ。不透明必須 | -| `bg-ground` | `--ground` | `#F5F5F5` | テーブルヘッダー・セクション背景 | -| `bg-field` | `--field` | `#FFFFFF` | 入力フィールド背景 | -| `bg-spot` | `--spot` | `#E48003` | アクセント背景 | -| `bg-spot-subtle` | `--spot-subtle` | `#f0f0f0` | アクセント薄背景 | -| `bg-spot-surface` | `--spot-surface` | `#f7f7f7` | アクセント極薄背景 | -| `bg-btn-primary` | `--btn-primary` | `#E48003` | プライマリボタン背景 | -| `bg-btn-primary-hover` | `--btn-primary-hover` | `#C56604` | プライマリボタンホバー | -| `bg-header-bg` | `--header-bg` | `#261a14` | ヘッダー背景 | +| Tailwindクラス | CSS変数 | default値 | 用途 | +| ---------------------- | --------------------- | --------- | -------------------------------- | +| `bg-page` | `--page` | `#F7F7F5` | ページ全体背景 | +| `bg-surface` | `--surface` | `#FFFFFF` | カード・セクション背景 | +| `bg-overlay` | `--overlay` | `#FFFFFF` | モーダル・ダイアログ。不透明必須 | +| `bg-ground` | `--ground` | `#F5F5F5` | テーブルヘッダー・セクション背景 | +| `bg-field` | `--field` | `#FFFFFF` | 入力フィールド背景 | +| `bg-spot` | `--spot` | `#E48003` | アクセント背景 | +| `bg-spot-subtle` | `--spot-subtle` | `#f0f0f0` | アクセント薄背景 | +| `bg-spot-surface` | `--spot-surface` | `#f7f7f7` | アクセント極薄背景 | +| `bg-btn-primary` | `--btn-primary` | `#E48003` | プライマリボタン背景 | +| `bg-btn-primary-hover` | `--btn-primary-hover` | `#C56604` | プライマリボタンホバー | +| `bg-header-bg` | `--header-bg` | `#261a14` | ヘッダー背景 | ### 5.4 テキスト色 -| Tailwindクラス | CSS変数 | default値 | 用途 | -|--------------|---------|-----------|------| -| `text-ink` | `--ink` | `#1f2937` | メインテキスト | -| `text-ink-sub` | `--ink-sub` | `#4b5563` | 補助テキスト・説明文 | -| `text-ink-muted` | `--ink-muted` | `#9ca3af` | プレースホルダー・薄いテキスト | -| `text-spot` | `--spot` | `#E48003` | アクセントテキスト | -| `text-spot-hover` | `--spot-hover` | `#C56604` | アクセントホバー | -| `text-header-text` | `--header-text` | `#FFFFFF` | ヘッダーテキスト | -| `text-header-accent` | `--header-accent` | `#EF8A00` | ヘッダーアクセント | -| `text-danger` | `--danger` | `#dc2626` | エラー・削除 | -| `text-success` | `--success` | `#16a34a` | 成功 | -| `text-warning` | `--warning` | `#eab308` | 警告 | -| `text-info` | `--info` | `#00b8d4` | 情報 | -| `text-error` | `--error` | `#ef4444` | エラーテキスト | +| Tailwindクラス | CSS変数 | default値 | 用途 | +| -------------------- | ----------------- | --------- | ------------------------------ | +| `text-ink` | `--ink` | `#1f2937` | メインテキスト | +| `text-ink-sub` | `--ink-sub` | `#4b5563` | 補助テキスト・説明文 | +| `text-ink-muted` | `--ink-muted` | `#9ca3af` | プレースホルダー・薄いテキスト | +| `text-spot` | `--spot` | `#E48003` | アクセントテキスト | +| `text-spot-hover` | `--spot-hover` | `#C56604` | アクセントホバー | +| `text-header-text` | `--header-text` | `#FFFFFF` | ヘッダーテキスト | +| `text-header-accent` | `--header-accent` | `#EF8A00` | ヘッダーアクセント | +| `text-danger` | `--danger` | `#dc2626` | エラー・削除 | +| `text-success` | `--success` | `#16a34a` | 成功 | +| `text-warning` | `--warning` | `#eab308` | 警告 | +| `text-info` | `--info` | `#00b8d4` | 情報 | +| `text-error` | `--error` | `#ef4444` | エラーテキスト | ### 5.5 ボーダー色 -| Tailwindクラス | CSS変数 | default値 | 用途 | -|--------------|---------|-----------|------| -| `border-edge` | `--edge` | `#e5e7eb` | 通常ボーダー | +| Tailwindクラス | CSS変数 | default値 | 用途 | +| -------------------- | --------------- | --------- | -------------------- | +| `border-edge` | `--edge` | `#e5e7eb` | 通常ボーダー | | `border-edge-strong` | `--edge-strong` | `#d1d5db` | 強調ボーダー・ホバー | -| `border-edge-subtle` | `--edge-subtle` | `#f3f4f6` | 薄いボーダー | -| `border-error` | `--error` | `#ef4444` | エラーボーダー | +| `border-edge-subtle` | `--edge-subtle` | `#f3f4f6` | 薄いボーダー | +| `border-error` | `--error` | `#ef4444` | エラーボーダー | ### 5.6 ステータス薄背景 -| Tailwindクラス | default値 | 用途 | -|--------------|-----------|------| -| `bg-danger-subtle` | `#fee2e2` | エラー薄背景 | -| `bg-success-subtle` | `#dcfce7` | 成功薄背景 | -| `bg-warning-subtle` | `#fef9c3` | 警告薄背景 | +| Tailwindクラス | default値 | 用途 | +| ------------------- | --------- | ------------ | +| `bg-danger-subtle` | `#fee2e2` | エラー薄背景 | +| `bg-success-subtle` | `#dcfce7` | 成功薄背景 | +| `bg-warning-subtle` | `#fef9c3` | 警告薄背景 | ### 5.7 シャドウ -| クラス | 用途 | -|--------|------| -| `shadow-card` | カード通常シャドウ | +| クラス | 用途 | +| ------------------- | -------------------- | +| `shadow-card` | カード通常シャドウ | | `shadow-card-hover` | カードホバーシャドウ | -| `shadow-card-glow` | 薄いシャドウ | +| `shadow-card-glow` | 薄いシャドウ | ### 5.8 ブランド固定色 ブランド固定色は、通常画面では乱用しません。ロゴ、ホーム、テーマプレビュー、コーヒーらしい強調に限定します。 -| Tailwindクラス | 値 | 用途 | -|--------------|-----|------| +| Tailwindクラス | 値 | 用途 | +| ----------------------------- | --------- | ---------------- | | `text-primary` / `bg-primary` | `#EF8A00` | ブランドオレンジ | -| `bg-primary-dark` | `#D67A00` | ダークオレンジ | -| `text-primary-light` | `#FF9A1A` | ライトオレンジ | -| `bg-dark` | `#211714` | ダークブラウン | -| `bg-dark-light` | `#3A2F2B` | ライトブラウン | -| `text-gold` | `#FFC107` | ゴールド | +| `bg-primary-dark` | `#D67A00` | ダークオレンジ | +| `text-primary-light` | `#FF9A1A` | ライトオレンジ | +| `bg-dark` | `#211714` | ダークブラウン | +| `bg-dark-light` | `#3A2F2B` | ライトブラウン | +| `text-gold` | `#FFC107` | ゴールド | ### 5.9 カードヘッダーグラデーション @@ -213,54 +213,82 @@ RoastPlus では、色を直接指定せず、意味を持つセマンティッ ### 6.1 用途別の基本形 -| 用途 | 推奨クラス | 使う場所 | -|------|------------|----------| -| ページタイトル | `text-xl sm:text-2xl font-bold text-ink` | 通常ページのタイトル | -| セクション見出し | `text-lg font-semibold text-ink` | カード内やフォーム区切り | -| 本文 | `text-base text-ink` | 説明、本文 | -| 補助文 | `text-sm text-ink-sub` | 説明、注記 | -| ラベル | `text-xs font-medium text-ink-muted` | バッジ、補足情報 | -| 大きな数値 | `text-3xl` から `text-4xl font-bold` | タイマー、進捗数値 | +| 用途 | 推奨クラス | 使う場所 | +| ---------------- | ---------------------------------------- | ------------------------ | +| ページタイトル | `text-xl sm:text-2xl font-bold text-ink` | 通常ページのタイトル | +| セクション見出し | `text-lg font-semibold text-ink` | カード内やフォーム区切り | +| 本文 | `text-base text-ink` | 説明、本文 | +| 補助文 | `text-sm text-ink-sub` | 説明、注記 | +| ラベル | `text-xs font-medium text-ink-muted` | バッジ、補足情報 | +| 大きな数値 | `text-3xl` から `text-4xl font-bold` | タイマー、進捗数値 | ### 6.2 フォントサイズ -| クラス | px換算 | 主な用途 | -|--------|--------|---------| -| `text-xs` | 12px | バッジ・ラベル・補足情報 | -| `text-sm` | 14px | 補助テキスト・フォームラベル | -| `text-base` | 16px | 本文 | -| `text-lg` | 18px | セクション見出し | -| `text-xl` | 20px | ページタイトル(モバイル) | -| `text-2xl` | 24px | ページタイトル(デスクトップ) | -| `text-3xl` | 30px | 大きな数値 | -| `text-4xl` | 36px | タイマーなどのヒーロー数値 | +| クラス | px換算 | 主な用途 | +| ----------- | ------ | ------------------------------ | +| `text-xs` | 12px | バッジ・ラベル・補足情報 | +| `text-sm` | 14px | 補助テキスト・フォームラベル | +| `text-base` | 16px | 本文 | +| `text-lg` | 18px | セクション見出し | +| `text-xl` | 20px | ページタイトル(モバイル) | +| `text-2xl` | 24px | ページタイトル(デスクトップ) | +| `text-3xl` | 30px | 大きな数値 | +| `text-4xl` | 36px | タイマーなどのヒーロー数値 | ### 6.3 フォントウェイト -| クラス | 用途 | -|--------|------| -| `font-bold` | 見出し・強調 | +| クラス | 用途 | +| --------------- | ------------------------ | +| `font-bold` | 見出し・強調 | | `font-semibold` | サブ見出し・ボタンラベル | -| `font-medium` | ラベル・タブ | -| `font-normal` | 本文 | +| `font-medium` | ラベル・タブ | +| `font-normal` | 本文 | -### 6.4 典型パターン +### 6.4 フォントファミリー -```tsx -{/* ページタイトル */} -

タイトル

+| クラス | フォント | 用途 | +| ------------ | -------- | --------------------------------------------------------------------- | +| (既定) | serif | 本文。`` の `font-serif` が効く | +| `font-sans` | Inter 系 | サンセリフにしたい箇所 | +| `font-brand` | Inter | ブランド表記(ホームのロゴ・スプラッシュ・ログイン/新規登録の見出し) | +| `font-num` | Outfit | 数値表示 | +| `font-mono` | 等幅 | コード・ID | + +ブランド表記は画面ごとに書体を変えず、`font-brand` に揃える。ロゴとタイトルで書体が違うと、同じアプリの画面に見えなくなる。 + +書体を指定するときは、必ず上記のユーティリティクラスを使う。`font-` に CSS 変数を任意値として直接渡す書き方(角括弧・丸括弧のどちらの形でも)は、Tailwind v4 では **font-weight として解釈されて効かない**。font-family として扱わせるには `family-name:` の型ヒントが必要になる。 -{/* セクション見出し */} -

セクション名

+新しい書体を足すときは、クラス側で指定せず `app/globals.css` の `@theme` に `--font-*` を定義してユーティリティ化する。 -{/* 説明文 */} -

補足説明

+> なお Tailwind v4 は Markdown を含むプロジェクト内のファイルを走査してクラス名を拾うため、**このドキュメントや CSS のコメントに使っていないクラス名を書くと、未使用のCSSが生成される**。説明のために書くときは実在しない形に崩す。過去の計画・作業ログ(`docs/`・`.superpowers/`)は `app/globals.css` の `@source not` で除外済み。 -{/* 数値表示 */} -00:00 +### 6.5 典型パターン -{/* バッジ・ラベル */} -ラベル +```tsx +{ + /* ページタイトル */ +} +

タイトル

; + +{ + /* セクション見出し */ +} +

セクション名

; + +{ + /* 説明文 */ +} +

補足説明

; + +{ + /* 数値表示 */ +} +00:00; + +{ + /* バッジ・ラベル */ +} +ラベル; ``` --- @@ -271,58 +299,58 @@ RoastPlus では、色を直接指定せず、意味を持つセマンティッ ### 7.1 基本スケール -| 用途 | 推奨 | -|------|------| -| モバイル横余白 | `px-4` | -| タブレット横余白 | `sm:px-6` | -| 標準ページ | `max-w-4xl` | -| フォーム | `max-w-2xl` または `max-w-lg` | -| 詳細読み物 | `max-w-3xl` | -| ホーム、広い一覧 | `max-w-6xl` から `max-w-7xl` | -| カード内余白 | `p-4` から `p-6` | -| セクション間 | `space-y-6` | -| カード角丸 | `rounded-2xl` | -| ボタン、入力 | `rounded-lg` | +| 用途 | 推奨 | +| ---------------- | ----------------------------- | +| モバイル横余白 | `px-4` | +| タブレット横余白 | `sm:px-6` | +| 標準ページ | `max-w-4xl` | +| フォーム | `max-w-2xl` または `max-w-lg` | +| 詳細読み物 | `max-w-3xl` | +| ホーム、広い一覧 | `max-w-6xl` から `max-w-7xl` | +| カード内余白 | `p-4` から `p-6` | +| セクション間 | `space-y-6` | +| カード角丸 | `rounded-2xl` | +| ボタン、入力 | `rounded-lg` | ### 7.2 垂直スペーシング -| クラス | px | 用途 | -|--------|----|------| -| `space-y-2` | 8px | 密なリスト | -| `space-y-4` | 16px | フォーム要素間 | +| クラス | px | 用途 | +| ----------- | ---- | -------------------- | +| `space-y-2` | 8px | 密なリスト | +| `space-y-4` | 16px | フォーム要素間 | | `space-y-6` | 24px | セクション内グループ | -| `space-y-8` | 32px | 主要セクション間 | +| `space-y-8` | 32px | 主要セクション間 | ### 7.3 グリッド・フレックスギャップ -| クラス | px | 用途 | -|--------|----|------| -| `gap-2` | 8px | アイコン+テキスト | -| `gap-3` | 12px | モバイルグリッド | +| クラス | px | 用途 | +| ------- | ---- | -------------------- | +| `gap-2` | 8px | アイコン+テキスト | +| `gap-3` | 12px | モバイルグリッド | | `gap-4` | 16px | デスクトップグリッド | -| `gap-6` | 24px | 大きなグリッド | +| `gap-6` | 24px | 大きなグリッド | ### 7.4 コンテナ余白 -| クラス | 値 | 用途 | -|--------|----|------| -| `px-4` | 16px | モバイル横余白 | -| `sm:px-6` | 24px | タブレット横余白 | -| `lg:px-8` | 32px | デスクトップ横余白 | -| `py-4` | 16px | モバイル縦余白 | -| `py-6` | 24px | タブレット縦余白 | -| `p-4` | 16px | カード内余白 | -| `p-6` | 24px | フォームカード内余白 | +| クラス | 値 | 用途 | +| --------- | ---- | -------------------- | +| `px-4` | 16px | モバイル横余白 | +| `sm:px-6` | 24px | タブレット横余白 | +| `lg:px-8` | 32px | デスクトップ横余白 | +| `py-4` | 16px | モバイル縦余白 | +| `py-6` | 24px | タブレット縦余白 | +| `p-4` | 16px | カード内余白 | +| `p-6` | 24px | フォームカード内余白 | ### 7.5 角丸 -| クラス | px | 主な用途 | -|--------|----|---------| -| `rounded-lg` | 8px | ボタン・入力・小要素 | -| `rounded-xl` | 12px | バッジ・中要素 | -| `rounded-2xl` | 16px | カード・モーダル | -| `rounded-3xl` | 24px | 大きな特殊要素 | -| `rounded-full` | 50% | アイコンボタン・アバター・ピル型バッジ | +| クラス | px | 主な用途 | +| -------------- | ---- | -------------------------------------- | +| `rounded-lg` | 8px | ボタン・入力・小要素 | +| `rounded-xl` | 12px | バッジ・中要素 | +| `rounded-2xl` | 16px | カード・モーダル | +| `rounded-3xl` | 24px | 大きな特殊要素 | +| `rounded-full` | 50% | アイコンボタン・アバター・ピル型バッジ | --- @@ -339,20 +367,20 @@ RoastPlus では、色を直接指定せず、意味を持つセマンティッ ### 8.2 使い分け -| コンポーネント | 主な用途 | 注意 | -|----------------|----------|------| -| `Button` | 主要、補助、危険操作 | 主操作は1画面1つを目立たせる | -| `IconButton` | 戻る、設定、閉じるなどの小操作 | 44px以上のタッチ領域を確保する | -| `FloatingNav` | 通常ページの戻る導線 | ホームと集中画面では例外あり | -| `Card` | 情報のまとまり | カードの入れ子は禁止 | -| `Input`, `Textarea`, `Select` | フォーム入力 | ラベルと補足文を近くに置く | -| `Checkbox`, `Switch` | ON/OFFや複数選択 | 生のinputを直接使わない | -| セグメントコントロール | 3択以内の状態切替(「十分・残少・欠品」など) | `Tabs` との違い:ページコンテンツの切替ではなく値の状態変更に使う。`StatusToggle` パターン参照 | -| `Modal` | 任意コンテンツのモーダル | `bg-overlay` 必須 | -| `Dialog` | 確認ダイアログ | 削除は `danger` | -| `Tabs` | 同階層の表示切替 | ページ遷移の代替にしすぎない | -| `Accordion` | 補足情報の開閉 | 主要情報を隠しすぎない | -| `EmptyState` | 空状態 | 次アクションを出す | +| コンポーネント | 主な用途 | 注意 | +| ----------------------------- | --------------------------------------------- | ---------------------------------------------------------------------------------------------- | +| `Button` | 主要、補助、危険操作 | 主操作は1画面1つを目立たせる | +| `IconButton` | 戻る、設定、閉じるなどの小操作 | 44px以上のタッチ領域を確保する | +| `FloatingNav` | 通常ページの戻る導線 | ホームと集中画面では例外あり | +| `Card` | 情報のまとまり | カードの入れ子は禁止 | +| `Input`, `Textarea`, `Select` | フォーム入力 | ラベルと補足文を近くに置く | +| `Checkbox`, `Switch` | ON/OFFや複数選択 | 生のinputを直接使わない | +| セグメントコントロール | 3択以内の状態切替(「十分・残少・欠品」など) | `Tabs` との違い:ページコンテンツの切替ではなく値の状態変更に使う。`StatusToggle` パターン参照 | +| `Modal` | 任意コンテンツのモーダル | `bg-overlay` 必須 | +| `Dialog` | 確認ダイアログ | 削除は `danger` | +| `Tabs` | 同階層の表示切替 | ページ遷移の代替にしすぎない | +| `Accordion` | 補足情報の開閉 | 主要情報を隠しすぎない | +| `EmptyState` | 空状態 | 次アクションを出す | ### 8.3 import例 @@ -389,18 +417,18 @@ import { ### 8.4 Button -| variant | 用途 | -|---------|------| -| `primary` | 主要アクション | -| `secondary` | 副次アクション | -| `danger` | 削除・危険操作 | -| `success` | 完了・承認 | -| `warning` | 注意喚起 | -| `info` | 情報系アクション | -| `outline` | 軽量アクション | -| `ghost` | ナビゲーション、控えめな操作 | -| `coffee` | ブランド強調 | -| `surface` | フィルター・補助 | +| variant | 用途 | +| ----------- | ---------------------------- | +| `primary` | 主要アクション | +| `secondary` | 副次アクション | +| `danger` | 削除・危険操作 | +| `success` | 完了・承認 | +| `warning` | 注意喚起 | +| `info` | 情報系アクション | +| `outline` | 軽量アクション | +| `ghost` | ナビゲーション、控えめな操作 | +| `coffee` | ブランド強調 | +| `surface` | フィルター・補助 | ```tsx @@ -410,14 +438,14 @@ import { ### 8.5 Card -| variant | 用途 | -|---------|------| -| `default` | 汎用カード | -| `hoverable` | クリッカブルカード | -| `action` | ホームグリッドカード | -| `coffee` | ブランド強調カード | -| `table` | テーブル外枠 | -| `guide` | ガイド表示、空状態 | +| variant | 用途 | +| ----------- | -------------------- | +| `default` | 汎用カード | +| `hoverable` | クリッカブルカード | +| `action` | ホームグリッドカード | +| `coffee` | ブランド強調カード | +| `table` | テーブル外枠 | +| `guide` | ガイド表示、空状態 | ### 8.6 Modal / Dialog @@ -494,7 +522,9 @@ import {
- +
@@ -509,7 +539,9 @@ import { ```tsx
{items.map((item) => ( - ... + + ... + ))}
``` @@ -517,22 +549,30 @@ import { ### 9.5 ヘッダーパターン ```tsx -{/* 通常ページ */} +{ + /* 通常ページ */ +}

タイトル

-
+; -{/* スティッキー */} +{ + /* スティッキー */ +}

タイトル

- +
-
+; -{/* 眉毛ラベル(eyebrow)付きタイトル — 機能名をアイコン+大文字英語で上段に添える */} +{ + /* 眉毛ラベル(eyebrow)付きタイトル — 機能名をアイコン+大文字英語で上段に添える */ +}
@@ -543,11 +583,15 @@ import {

ページタイトル

一行説明

- + -
+; -{/* セクション見出し + カウントバッジ — 件数を色変化(0件=グレー / 1件以上=赤)で示す */} +{ + /* セクション見出し + カウントバッジ — 件数を色変化(0件=グレー / 1件以上=赤)で示す */ +}

セクション名

{count} -
+; -{/* ホーム */} +{ + /* ホーム */ +}
RoastPlus
-
+; ``` ### 9.6 テーブルリスト @@ -574,7 +620,9 @@ import { 一覧データを行で表示する際の基本形。モバイルで横スクロールが発生するHTMLテーブルの代わりに使う。`Card variant="table"` で外枠を作り、`divide-y divide-edge-subtle` で行を区切る。 ```tsx -{/* 通常リスト */} +{ + /* 通常リスト */ +}
{items.map((item) => ( @@ -585,26 +633,28 @@ import {
補足情報
{/* 右: 操作系(shrink-0 で縮まない) */} -
- {/* IconButton など */} -
+
{/* IconButton など */}
))} -
+; -{/* ローディング中 */} +{ + /* ローディング中 */ +}
読み込み中...
-
+; -{/* 空状態(簡易メッセージ) */} +{ + /* 空状態(簡易メッセージ) */ +}
-
+; ``` 行内に `order-3 w-full sm:order-none sm:w-auto` を使うと、モバイルでは最下段に折り返し、タブレット以上では通常位置に戻るレスポンシブ配置ができる。 @@ -616,12 +666,10 @@ import { 3択以内の状態を切り替えるUI。`Tabs` がページ内コンテンツの切替に使うのに対し、こちらは「値の状態変更」に使う(例: 在庫の「十分 / 残少 / 欠品」)。 ```tsx -{/* セグメントコントロール外枠 */} -
+{ + /* セグメントコントロール外枠 */ +} +
{options.map((opt) => { const selected = opt.value === value; return ( @@ -635,12 +683,15 @@ import { selected ? `${opt.activeClass} shadow-sm` : 'bg-transparent text-ink-muted hover:text-ink-sub' }`} > -
+
; ``` 選択中ボタンの `activeClass` はセマンティック色(`bg-success-subtle text-success`、`bg-danger-subtle text-danger` など)を使い、未選択はすべてグレーに統一する。 @@ -664,42 +715,38 @@ lg : 1024px 大型デスクトップ アニメーションは、状態変化を理解しやすくするために使います。装飾だけの強い動きは避けます。 -| 用途 | 方針 | -|------|------| -| ホーム | カードの順次出現は使用可 | -| 集中操作画面 | タイマー、進捗、完了状態の演出は使用可 | -| 一覧、フォーム | 控えめな hover / focus / loading を優先 | -| モーダル | 短い fade / scale / slide に留める | -| エラー、成功 | Toast やインラインメッセージで次の行動を示す | +| 用途 | 方針 | +| -------------- | -------------------------------------------- | +| ホーム | カードの順次出現は使用可 | +| 集中操作画面 | タイマー、進捗、完了状態の演出は使用可 | +| 一覧、フォーム | 控えめな hover / focus / loading を優先 | +| モーダル | 短い fade / scale / slide に留める | +| エラー、成功 | Toast やインラインメッセージで次の行動を示す | `prefers-reduced-motion` を尊重し、動きを減らす設定のユーザーには不要なアニメーションを見せません。 ### 10.1 カスタムCSSアニメーション -| クラス | 効果 | 用途 | -|--------|------|------| -| `animate-pulse-scale` | 2秒ループ、scale 1→1.05→1 | Newラベル | -| `animate-home-page` | 左スライド + フェードイン | ホームページ入場 | -| `animate-home-card` | 下スライド + フェードイン | グリッドカード順次出現 | -| `new-label-gradient` | グラデーション流動 | ラベル装飾 | +| クラス | 効果 | 用途 | +| --------------------- | ------------------------- | ---------------------- | +| `animate-pulse-scale` | 2秒ループ、scale 1→1.05→1 | Newラベル | +| `animate-home-page` | 左スライド + フェードイン | ホームページ入場 | +| `animate-home-card` | 下スライド + フェードイン | グリッドカード順次出現 | +| `new-label-gradient` | グラデーション流動 | ラベル装飾 | ### 10.2 Tailwindトランジション -| 用途 | クラス | 時間 | -|------|--------|------| -| ホバー色変化 | `transition-colors duration-200` | 200ms | -| モーダル開閉 | `transition-all duration-300` | 300ms | -| カードリフト | `hover:-translate-y-2 hover:shadow-card-hover transition-all duration-300` | 300ms | -| テーマ変更 | `transition-colors duration-1000` | 1000ms | +| 用途 | クラス | 時間 | +| ------------ | -------------------------------------------------------------------------- | ------ | +| ホバー色変化 | `transition-colors duration-200` | 200ms | +| モーダル開閉 | `transition-all duration-300` | 300ms | +| カードリフト | `hover:-translate-y-2 hover:shadow-card-hover transition-all duration-300` | 300ms | +| テーマ変更 | `transition-colors duration-1000` | 1000ms | ### 10.3 Framer Motion ```tsx - + ... ``` @@ -790,13 +837,12 @@ UIを作る、または直す前に確認します。 ## 13. 参照先 -| ドキュメント / ファイル | 内容 | -|-------------------------|------| -| `docs/steering/PRODUCT.md` | プロダクトの目的、ユーザー、コアバリュー | -| `docs/steering/FEATURES.md` | 機能仕様、UI実装ルール、共通禁止事項 | -| `docs/steering/TECH_SPEC.md` | 技術制約、テーマシステム、ADR | -| `docs/steering/REPOSITORY.md` | ディレクトリ構成、依存方向 | -| `docs/steering/GUIDELINES.md` | 実装、テスト、Git運用 | -| `app/globals.css` | CSS変数、テーマ定義、カスタムアニメーション | -| `/dev/design-lab` | 開発者向けデザイン確認ページ | - +| ドキュメント / ファイル | 内容 | +| ----------------------------- | ------------------------------------------- | +| `docs/steering/PRODUCT.md` | プロダクトの目的、ユーザー、コアバリュー | +| `docs/steering/FEATURES.md` | 機能仕様、UI実装ルール、共通禁止事項 | +| `docs/steering/TECH_SPEC.md` | 技術制約、テーマシステム、ADR | +| `docs/steering/REPOSITORY.md` | ディレクトリ構成、依存方向 | +| `docs/steering/GUIDELINES.md` | 実装、テスト、Git運用 | +| `app/globals.css` | CSS変数、テーマ定義、カスタムアニメーション | +| `/dev/design-lab` | 開発者向けデザイン確認ページ | diff --git a/app/assignment/components/AssignmentSettingsModal.tsx b/app/assignment/components/AssignmentSettingsModal.tsx index b5a5e440..03a9a014 100644 --- a/app/assignment/components/AssignmentSettingsModal.tsx +++ b/app/assignment/components/AssignmentSettingsModal.tsx @@ -196,7 +196,7 @@ export function AssignmentSettingsModal({ options={memberOptions} placeholder="選択..." disabled={isLoading} - className="!text-sm !py-2" + className="text-sm! py-2!" /> setEditRightLabel(e.target.value)} placeholder={headerLabels.right} - className="flex-1 !p-2 !text-sm !min-h-0" + className="flex-1 !p-2 text-sm! min-h-0!" /> @@ -89,7 +89,7 @@ export const MobileListView: React.FC = ({ variant="danger" size="sm" onClick={() => handleDeleteTaskLabel(label.id)} - className="!p-2 !min-h-0 shrink-0" + className="!p-2 min-h-0! shrink-0" > @@ -144,15 +144,15 @@ export const MobileListView: React.FC = ({ onTouchEnd={handleCellTouchEnd} onTouchMove={handleCellTouchMove} onClick={() => handleCellClick(team.id, label.id)} - className={`!min-h-0 !rounded-md !px-2 !py-3 !shadow-none truncate select-none ${ + className={`min-h-0! rounded-md! !px-2 py-3! !shadow-none truncate select-none ${ member && isSelected ? '!border-spot !bg-spot !text-on-spot ring-2 ring-spot/20' : member - ? '!border-edge !bg-surface hover:!bg-spot-surface' + ? 'border-edge! bg-surface! hover:!bg-spot-surface' : '' } ${ - !member && isSelected ? '!bg-surface !border-spot' : '' - } ${!member && !isSelected ? '!border-dashed !border-edge-strong !bg-surface !text-ink-muted' : ''}`} + !member && isSelected ? 'bg-surface! !border-spot' : '' + } ${!member && !isSelected ? '!border-dashed border-edge-strong! bg-surface! !text-ink-muted' : ''}`} > {member ? member.name : '未割当'} diff --git a/app/assignment/components/assignment-table/modals/ContextMenuModal.tsx b/app/assignment/components/assignment-table/modals/ContextMenuModal.tsx index fc78f351..af69fae9 100644 --- a/app/assignment/components/assignment-table/modals/ContextMenuModal.tsx +++ b/app/assignment/components/assignment-table/modals/ContextMenuModal.tsx @@ -67,7 +67,7 @@ export function ContextMenuModal({ data, state, setMemberMenu, callbacks }: Cont setCurrent(null); } }} - className="!py-2" + className="py-2!" /> 削除 diff --git a/app/assignment/components/assignment-table/modals/MemberSelectionModal.tsx b/app/assignment/components/assignment-table/modals/MemberSelectionModal.tsx index e5527155..dc01bd84 100644 --- a/app/assignment/components/assignment-table/modals/MemberSelectionModal.tsx +++ b/app/assignment/components/assignment-table/modals/MemberSelectionModal.tsx @@ -45,7 +45,7 @@ export function MemberSelectionModal({ data, state, callbacks }: MemberSelection handleAddMember(current.taskLabelId, current.teamId); } }} - className="!py-2 !text-sm" + className="py-2! text-sm!" autoFocus /> @@ -71,7 +71,7 @@ export function MemberSelectionModal({ data, state, callbacks }: MemberSelection callbacks.onUpdateMember(createEmptyAssignment(current.teamId, current.taskLabelId), member.id); setCurrent(null); }} - className="flex-1 !justify-start !text-left !text-ink hover:!bg-ground" + className="flex-1 !justify-start text-left! !text-ink hover:bg-ground!" > {member.name} diff --git a/app/assignment/components/assignment-table/modals/TeamActionModal.tsx b/app/assignment/components/assignment-table/modals/TeamActionModal.tsx index a4f22783..e93ae669 100644 --- a/app/assignment/components/assignment-table/modals/TeamActionModal.tsx +++ b/app/assignment/components/assignment-table/modals/TeamActionModal.tsx @@ -151,7 +151,7 @@ function TeamActionModalContent({ size="sm" fullWidth onClick={handleDeleteTeamFromModal} - className="!flex !items-center !justify-center !gap-1" + className="flex! items-center! !justify-center gap-1!" > 削除 diff --git a/app/assignment/page.tsx b/app/assignment/page.tsx index 8785e1a8..8650938b 100644 --- a/app/assignment/page.tsx +++ b/app/assignment/page.tsx @@ -73,7 +73,7 @@ export default function AssignmentPage() { variant="outline" size="sm" onClick={() => setIsSettingsModalOpen(true)} - className="!rounded-full !px-3 !py-2 shadow-md !bg-surface !text-ink-sub hover:!bg-ground !border !border-edge-strong" + className="rounded-full! px-3! py-2! shadow-md bg-surface! text-ink-sub! hover:bg-ground! border! border-edge-strong!" title="詳細設定" > @@ -114,8 +114,8 @@ export default function AssignmentPage() { variant={data.manager ? 'outline' : 'primary'} size="md" onClick={() => setIsManagerDialogOpen(true)} - className={`!flex !items-center !gap-2 !px-4 !py-3 !rounded-lg shadow-lg ${ - data.manager ? '!bg-surface hover:!bg-ground !border-edge' : '' + className={`flex! items-center! gap-2! px-4! py-3! rounded-lg! shadow-lg ${ + data.manager ? 'bg-surface! hover:bg-ground! border-edge!' : '' }`} > {data.manager ? ( diff --git a/app/clock/page.tsx b/app/clock/page.tsx index a2dfba73..54ee8278 100644 --- a/app/clock/page.tsx +++ b/app/clock/page.tsx @@ -258,7 +258,7 @@ export default function ClockPage() { variant="primary" size="sm" onClick={enableAudio} - className="col-span-2 mt-1 w-full !min-h-11 !px-4 sm:col-span-1 sm:mt-0 sm:w-auto" + className="col-span-2 mt-1 w-full !min-h-11 px-4! sm:col-span-1 sm:mt-0 sm:w-auto" style={{ backgroundColor: colors.accent, color: '#FFFFFF', diff --git a/app/contact/page.tsx b/app/contact/page.tsx index e5496045..65d95ca7 100644 --- a/app/contact/page.tsx +++ b/app/contact/page.tsx @@ -121,7 +121,7 @@ export default function ContactPage() { {/* エラーメッセージ */} {status === 'error' && errorMessage && (
- +

エラーが発生しました

{errorMessage}

diff --git a/app/defect-beans/page.tsx b/app/defect-beans/page.tsx index 01ce03f6..cc30a79a 100644 --- a/app/defect-beans/page.tsx +++ b/app/defect-beans/page.tsx @@ -190,7 +190,7 @@ export default function DefectBeansPage() { size="sm" onClick={toggleCompareMode} title={compareMode ? '選択モード' : '比較モード'} - className="!px-3 !py-2 gap-1.5" + className="px-3! py-2! gap-1.5" > {compareMode ? '選択モード' : '比較'} @@ -201,7 +201,7 @@ export default function DefectBeansPage() { size="sm" onClick={handleShowCompare} title="比較を表示" - className="!px-3 !py-2 gap-1.5" + className="px-3! py-2! gap-1.5" > 比較 ({selectedIds.size}) @@ -212,7 +212,7 @@ export default function DefectBeansPage() { size="sm" onClick={() => setShowAddForm(true)} title="欠点豆を追加" - className="!px-3 !py-2 gap-1.5" + className="px-3! py-2! gap-1.5" > 追加 diff --git a/app/drip-guide/page.tsx b/app/drip-guide/page.tsx index 1bbedcfc..a8426407 100644 --- a/app/drip-guide/page.tsx +++ b/app/drip-guide/page.tsx @@ -21,7 +21,7 @@ export default function DripGuidePage() { right={ 新規レシピ diff --git a/app/error.tsx b/app/error.tsx index c5ee7928..478c1ff0 100644 --- a/app/error.tsx +++ b/app/error.tsx @@ -16,7 +16,7 @@ export default function Error({ reset }: { error: Error & { digest?: string }; r ホームへ diff --git a/app/globals.css b/app/globals.css index f07db0e1..a7ec5259 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,5 +1,10 @@ @import 'tailwindcss'; +/* 過去の仕様・計画・作業ログはクラス名の検出対象から外す。 + 古いクラス名を拾って未使用CSSが生成されるのを防ぐ */ +@source not '../docs'; +@source not '../.superpowers'; + :root { --background: #fdf8f0; --foreground: #171717; @@ -480,6 +485,11 @@ --font-mono: var(--font-geist-mono); --font-nunito: var(--font-nunito); --font-num: var(--font-outfit); + /* ブランド表記(ロゴ・スプラッシュ・ログイン/新規登録の見出し)用。 + 書体をクラス側の任意値で直接指定すると Tailwind v4 では font-weight として + 解釈され効かないため、ここでユーティリティ化する + (コメント内にクラス名を書くと Tailwind が拾ってしまうので書かない) */ + --font-brand: var(--font-inter); } /* stylelint-enable at-rule-no-unknown */ diff --git a/app/inventory/page.tsx b/app/inventory/page.tsx index 7075fccb..b789dfe3 100644 --- a/app/inventory/page.tsx +++ b/app/inventory/page.tsx @@ -131,7 +131,7 @@ export default function InventoryPage() { setEditing(null); setModalOpen(true); }} - className="!min-h-0 shrink-0 gap-1.5 !rounded-[10px] !px-4 !py-2 !text-sm" + className="min-h-0! shrink-0 gap-1.5 !rounded-[10px] px-4! py-2! text-sm!" >