OmniRoute — Design System & Visual Identity (日本語)
マーケティングサイト(viral.omniroute.online、why.omniroute.online、omniroute.online)と製品ダッシュボードは、1つの製品に見えるべきです。サイトはすでにダッシュボードのパレットを取り入れており、css/tokens.cssにも「パレットはOmniRouteダッシュボード(src/app/globals.css)を反映している」と記載されています。したがって、カラーの観点では、両者はすでに約80%統一されています。ダッシュボードに不足しているものは以下のとおりです:
- サイトがすべてのページで使用している方眼紙風グリッド壁紙。
- サイトにはあるものの、ダッシュボードにはない一部の共有デザイントークン(角丸スケール、ブランドグラデーション、
surface-2、等幅フォント)。 - コンポーネントレベルの一貫性 — 多くのダッシュボードコンポーネントが、ハードコードされたhex/rgbaを使用してテーマトークンを迂回しています。
本ドキュメントでは、分析と計画を示します。
- 信頼できる唯一の情報源 =
src/app/globals.css。 サイトがダッシュボードを反映するのであり、その逆ではありません。新しいトークンは、まずglobals.cssに追加します。 - リテラルではなく、常にトークンを使用する。 コンポーネントでは、生の
#hexではなく、セマンティックトークン(bg-surface、text-primary、border-border)を使用します。 - 目立たせず、控えめにする。 グリッドはコンテンツの背後に配置される淡い壁紙です。テキストのコントラストを低下させたり、UIと視覚的に競合したりしてはいけません。
- テーマ対応。 すべてが
.dark(製品を象徴する外観)とライトテーマの両方で機能します。 - 段階的かつ的確に展開する。 まずグリッドとトークン(低リスクで視認性の高い変更)をリリースし、その後、コンポーネントのクリーンアップを段階的に進めます。
3. 現状 — すでに統一されているものと、されていないもの
Section titled “3. 現状 — すでに統一されているものと、されていないもの”3.1 カラー — 統一済み ✅
Section titled “3.1 カラー — 統一済み ✅”すべてのブランドカラーとサーフェスは、すでにサイトと値が一致しています(異なるのは名前のみで、ダッシュボードでは--color-プレフィックスが付きます)。src/app/globals.css:30-128で確認済みです:
| 概念 | サイトのトークン(tokens.css) |
ダッシュボードのトークン(globals.css) |
一致 |
|---|---|---|---|
| プライマリ | --primary #e54d5e |
--color-primary #e54d5e |
✅ |
| プライマリホバー | --primary-hover #c93d4e |
--color-primary-hover #c93d4e |
✅ |
| アクセント | --accent #6366f1 |
--color-accent #6366f1 |
✅ |
| アクセント2 | --accent-2 #8b5cf6 |
--color-accent-hover #8b5cf6 |
✅(改名) |
| アクセント3 | --accent-3 #a855f7 |
--color-accent-light #a855f7 |
✅(改名) |
| 成功 / 警告 / エラー | #22c55e / #f59e0b / #ef4444 |
同一 | ✅ |
| トラフィックライト | #ff5f56 / #ffbd2e / #27c93f |
同一 | ✅ |
| ダーク背景 / サーフェス / ボーダー | #0b0e14 / #161b22 / rgba(255,255,255,.08) |
同一 | ✅ |
| ライト背景 / サーフェス / テキスト | #f9f9fb / #fff / #1a1a2e |
同一 | ✅ |
結論: カラー移行は不要です。ビジュアルアイデンティティはすでに共有されています。これは再構築ではなく、_仕上げ_です。
3.2 ギャップ — ダッシュボードに不足しているもの
Section titled “3.2 ギャップ — ダッシュボードに不足しているもの”| ギャップ | サイト側 | ダッシュボード | 対応 |
|---|---|---|---|
| グリッド壁紙 | body::before の方眼紙、--grid-line、--grid-size 32px、--section-alt |
✅ 追加済み(フェーズ1) | パートA |
| 角丸スケール | --radius 14px、--radius-sm 9px |
--radius 14px を追加済み;-sm とコンポーネントの再割り当ては保留中 |
パートB / フェーズ2 |
| ブランドグラデーション | --grad-brand 135deg primary→accent-3 |
✅ トークン追加済み(フェーズ1);フェーズ2で使用 | パートB |
| ネストされたサーフェス | --surface-2 #1c2230 |
✅ 追加済み(フェーズ1) | パートB |
| 等幅フォント | --font-mono(ui-monospace スタック) |
保留中(フェーズ4、使用箇所と同時に対応) | パートB |
text-muted(ダーク) |
#8b8b9e |
#a1a1aa(zinc-400) |
調整 — パートB |
3.3 テーマ設定の仕組み(既存機能を壊さないために)
Section titled “3.3 テーマ設定の仕組み(既存機能を壊さないために)”- Tailwind v4、CSS-first(
tailwind.config.*なし)。トークンは:root/.darkで定義され、@theme inlineを介してユーティリティに公開されます(globals.css:130-179)。 - ダークモードは
<html>の.darkクラスで適用され(globals.css:22の@custom-variant dark)、カスタム Zustand ストア(src/store/themeStore.ts)によって切り替えられます。デフォルトテーマ =system(src/shared/constants/appConfig.ts:11)。一方、サイトではhtml[data-theme="light"]を使用していますが、両者の仕組みは異なり、交わることはありません(オリジンが別々のため)。そのため、ダッシュボードの.darkの仕組みを維持します。 - 実行時のプライマリカラー上書きが存在します(
themeStore.ts:85-97、プリセットはCOLOR_THEMES)。ユーザーは--color-primaryを変更できます。--color-primaryを参照する新しいトークン(グラデーションなど)も、追加対応なしでこれらの上書きを継承します。✅ - Tailwind v4 の予約済み角丸名:
--radius-sm/md/lg/...はrounded-*ユーティリティの基盤です。これらを再定義すると、既存のすべてのrounded-*に遡及的な変更が加わります(例:rounded-smは12ファイルで使用されています)。そのため、小さい角丸値の変更とコンポーネントの再割り当ては、使用箇所を同時に変更するフェーズ2まで意図的に延期します。
4. パートA — 方眼紙グリッド背景(主要要望)— 実装済み(フェーズ1)
Section titled “4. パートA — 方眼紙グリッド背景(主要要望)— 実装済み(フェーズ1)”4.1 概要
Section titled “4.1 概要”サイト(_mono_repo/omnirouteSite/css/base.css)とまったく同じ実装です。ビューポート全体に固定された疑似要素で2つの1pxラインのグラデーションを描画し、すべてのコンテンツの背後に z-index:-1 で配置します。
body::before { content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none; background-image: linear-gradient(to right, var(--grid-line) 1px, transparent 1px), linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px); background-size: var(--grid-size) var(--grid-size);}body に不透明な background-color が設定されていても機能する理由: z-index:-1 を持つ ::before は、要素自体の背景よりも_上_、通常フロー内のコンテンツよりも_下_に描画されます。そのため、--color-bg がベースの塗りつぶしとなり、その上にグリッドが重なり、さらにその上にアプリがレンダリングされます。
4.2 コードベース内の既存実装
Section titled “4.2 コードベース内の既存実装”src/app/landing/page.tsx:16-26 では、ページ単位ですでに同じグリッドが実装されています。ただし、赤色の線(#E54D5E、不透明度 0.06)を 50px 間隔で使用し、アニメーションするオーブも追加されています。したがって、このパターンはプロダクト内で実証済みです。今回の作業では、これをグローバルかつテーマ対応の壁紙へと昇格させます。
4.3 追加したトークン(globals.css 内)
Section titled “4.3 追加したトークン(globals.css 内)”:root { /* ライト — 密度の高いダッシュボード上でも壁紙が実際に見えるように、 サイトの0.045からグリッドの不透明度を上げて調整 (カードやクロームがビューポートの大部分を覆うため) */ --grid-line: rgba(0, 0, 0, 0.07); --grid-size: 32px; --section-alt: rgba(0, 0, 0, 0.022);}.dark { /* ダーク — 同じ理由で0.035から上げて調整 */ --grid-line: rgba(255, 255, 255, 0.06); --section-alt: rgba(255, 255, 255, 0.018);}4.4 唯一のブロッカー — 解消済み
Section titled “4.4 唯一のブロッカー — 解消済み”グリッドは構造上グローバルです(パネル、auth/login、エラーページなど、すべてのルートを一度にカバーします)。パネル内でグリッドを隠していた要素は、厳密に1つだけでした。
-
src/shared/components/layouts/DashboardLayout.tsx— 外側のラッパーが不透明なbg-bgを描画していました。その下にある要素(<main>、スクロールコンテナ、max-w-7xlの内側要素)はすべてすでに透明です。そのため、bg-bgを削除することで、コンテンツ領域にbodyのグリッドが透けて見えるようになります(bodyの--color-bgは引き続きベースの塗りつぶしとして残ります)。<div className="flex h-dvh min-h-0 w-full overflow-hidden bg-bg"><div className="flex h-dvh min-h-0 w-full overflow-hidden">
4.5 クロームとの相互作用(サイドバー/ヘッダー)
Section titled “4.5 クロームとの相互作用(サイドバー/ヘッダー)”Header(Header.tsx:207、bg-bg)とSidebar(Sidebar.tsx:430、bg-sidebar)は不透明なままです。つまり、グリッドはコンテンツ領域にのみ表示され、その周囲を単色のクロームが囲みます。落ち着いたデフォルト表示であり、サイトがクロームとキャンバスを分離する方法とも一致します(決定D3 = 単色)。
4.6 ログイン/認証/エラーページ
Section titled “4.6 ログイン/認証/エラーページ”これらは <body> の直下にレンダリングされるため(パネルクロームなし)、グローバルグリッドが自動的に背後へ表示されます。フェーズ5 — 完了: 独立したフルスクリーンラッパーは実際には不透明(min-h-screen … bg-bg。ここで bg-bg は <body> と同じ単色の塗りつぶし)であり、ログイン画面だけでなく、ダッシュボード以外のすべての画面でグリッドを隠していました。共有壁紙が透けて見えるように、現在はすべて透明になっています。対象は login、forgot-password、callback、maintenance、offline、status、terms、privacy、onboarding、および ErrorPageScaffold(400/401 をカバー)です。これにより、D4 が完了しました(ログイン画面のみから、すべての独立画面へ対象を拡張)。tests/unit/design-grid-background.test.ts で保護されています。
4.7 ランディングページ
Section titled “4.7 ランディングページ”landing/page.tsx では、より表現豊かなアニメーション背景(オーブ+ビネット)を維持します。これは独自のマーケティング用スプラッシュ画面です(決定D5 = 現状維持)。
5. パートB — トークンの統一
Section titled “5. パートB — トークンの統一”フェーズ1では、不活性で衝突のない識別用トークン(--surface-2/--color-surface-2、--grad-brand、--radius)を追加します。フェーズ2では角丸スケールをTailwindに接続してコンポーネントの参照先を変更し、フェーズ4では--font-monoとその利用箇所を追加します。
| トークン | 理由 | フェーズ |
|---|---|---|
--radius / --radius-sm |
個別指定の6/8/12ではなく、単一の角丸スケール(14/9) | 1(値)/ 2(接続+参照先変更) |
--grad-brand |
サイトに合わせた、プライマリCTA用のブランドグラデーション(赤→紫) | 1(トークン)/ 2(Button) |
--surface-2 |
ネストされたパネル / テーブルヘッダー / インセット行 | 1 |
--font-mono |
コードブロック、ターミナル、ID、エンドポイント | 4 |
--text-muted の調整 |
サイト↔パネル間で1つの値を選択(#a1a1aaを推奨) |
2 |
D2(text-muted): サイトは#8b8b9e、ダッシュボードは#a1a1aa。**ダッシュボードの#a1a1aa**を維持し、合わせるために_サイト_側を更新することを推奨します。見た目のみの変更です。
6. パートC — コンポーネントの標準化(フェーズ2~4)
Section titled “6. パートC — コンポーネントの標準化(フェーズ2~4)”カスタムコンポーネント(shadcn/Radix不使用)、Tailwind v4、セマンティックトークンはほぼ導入済みです(195ファイルが共有バレルをインポート)。作業内容は迂回実装の除去です。配置先:src/shared/components/。
| # | 項目 | ファイル | 問題 → 目標 | フェーズ |
|---|---|---|---|---|
| C1 | 角丸の整合 | Button.tsx:14-18、Card.tsx:39、Modal.tsx、Input.tsx、Select.tsx |
6/8/12pxが混在 → --radius/--radius-sm(14/9) |
2 |
| C2 | Buttonのグラデーション+accentバリアント |
Button.tsx:5-12 |
プライマリが単色の赤→赤。--grad-brandに合わせ、不足しているaccentバリアントを追加。約195箇所でインポート — 視認性が最も高い |
2 |
| C3 | テーブル | DataTable.tsx:122-176、logTableStyles.ts、globals.css:405-414 |
100%インライン指定されたハードコードのrgba+存在しない変数。トークンへ移行し、分岐したスタイルを廃止 | 3 |
| C4 | ステータスカラーの一元化 | flow/edgeStyles.ts、TokenHealthBadge.tsx、DegradationBadge.tsx、ProviderCascadeNode.tsx、Badge.tsx+5個のヘルパー |
同じ16進数カラーが6箇所以上に重複 → --color-success/warning/errorを基にした単一モジュール |
3 |
| C5 | Cardのボーダー | Card.tsx:39 |
border-white/5 → ブランドカラーの/8 |
2 |
| C6 | フォーカスリングの調整 ✅ 完了 | globals.cssの--focus-ring(accent)とフォームコントロールのring-primary/30 |
グローバルリングに合わせ、赤いエラーリングと区別するため、**accent(紫)**に統一。エラーは赤のまま | 4 |
| C7 | Checkbox+Textareaの追加 |
インラインのaccentColor:#6366f1を持つ生の<input>/<textarea> |
トークン駆動のプリミティブ | 4 |
| C8 | ハードコードされた16進数カラーの一括除去 | ConsoleLogViewer.tsx:240、ComboLiveStudio.tsx:306、Modalのドット、約14個のチャートファイル |
リテラル → トークン | 4 |
| C9 | cn() → clsx+tailwind-merge |
src/shared/utils/cn.ts |
競合するクラスが積み重なる。C1のオーバーライドに必要 | 2 |
すでにブランド準拠(トークン駆動で、必要なのは角丸のみ): Badge、Toggle、SegmentedControl、Input、Select。
7. ロールアウト計画
Section titled “7. ロールアウト計画”- フェーズ1 — グリッド + アイデンティティトークン(このPR)。
globals.cssのグリッド +--surface-2/--grad-brand/--radiusトークン、body::beforeの壁紙、妨げとなっていたbg-bgの削除、静的ガードテスト。低リスクで、1コミットで元に戻せます。 - フェーズ2 — プリミティブ(C1、C2、C5)— このPRで完了。 セマンティックな角丸ユーティリティ
rounded-card(14px)/rounded-control(9px)を@theme経由で追加(カスタム名のため、デフォルトのrounded-sm/md/lg/xlは変更されず、400ファイル規模の影響はありません)。Card/Modal → 14px、Button/Input/Select → 9px、Button の primary →--grad-brand(赤→バイオレット)+ 新しいaccentバリアント、Card のボーダー →border-borderトークン(0.08)。延期:cn()→tailwind-merge(C9)には新しい依存関係が必要です。場当たり的なrounded-lgの一括変更(326ファイル)は、プリミティブがサーフェスの大部分を担っているため、現状のままとします。 - フェーズ3 — ステータスカラー + テーブル(C3、C4)— このPRで完了。 ✅ C4(
src/shared/constants/statusColors.ts—STATUS_HEXを単一の情報源に統一。flow/edgeStyles.ts+TokenHealthBadgeの参照先を変更し、同一の忠実な hex を維持)。✅--font-monoトークン。✅ C3(DataTable) — すべてのインライン rgba と、機能していなかったvar(--bg-table-header)/var(--text-secondary)のフォールバックを、--table-*トークンセット(--table-header-bg/-row-zebra/-row-hover/-cell-border/-row-selected)に置き換えました。dark の値は従来のハードコードされた rgba と完全に同一(dark はバイト単位で同一)で、light の値により、従来は常に暗くなっていたライトテーマを修正しています。ヘッダーのボーダー →--color-border、セカンダリテキスト →--color-text-muted。マージ前にビジュアル確認が必要です。(未変更:logTableStyles.tsとレガシーな Ant の.ant-tableルール。これらは別件で、優先度は低めです。) - フェーズ4 — クリーンアップ(C6、C7、C9は完了、C8は保留中)。 ✅ C9
cn()→twMerge(clsx(...))(clsx + tailwind-merge を依存関係として追加)— 呼び出し元のclassNameが、競合するプリミティブのクラスと重複するのではなく、正しく_置き換える_ようになりました。✅ C7 新しいCheckbox+Textareaプリミティブ(トークン駆動で、barrel からエクスポート。追加のみの変更であり、32個の生の checkbox / 41個の生の textarea は段階的に移行できます)。✅ C6 フォーカスリングの整合 — フォームコントロール(Input/Select/Textarea/Toggle/Checkbox)は、グローバルな--focus-ringと一致し、赤いエラーリングとの競合を避けるため、フォーカス時に accent(バイオレット) のリングを使用するようになりました。赤いエラー状態は変更されていません。⏳ C8のhex一括置換は、無差別な検索・置換ではありません — _意図的_で維持すべき箇所として確認済みのもの:ConsoleLogViewer.tsx:240(常にdarkのターミナル)、TokenHealthBadgeのポップオーバー、ReactFlow のSVGストローク。テーマ対応を意図したhexのみを移行します。
各フェーズ: npm run lint + npm run typecheck:core + ビジュアル確認。
8. 未決定事項(推奨案)
Section titled “8. 未決定事項(推奨案)”- D1 — Button の primary: 赤→赤を維持するか、赤→バイオレットの
--grad-brandに切り替えるか? 推奨: 赤→バイオレット(フェーズ2)。 - D2 — グリッド線の色: ブランドの赤ではなく、neutral(サイトのスタイル)を選択。サイズは 32px(オーナーのフィードバックを受け、元の46pxから約30%縮小。46pxのセルはダッシュボードレイアウトでは大きすぎる印象でした)。
- D3 — Chromeの鮮やかさ: サイドバー/ヘッダーは solid を選択。
- D4 — 認証/ログインのグリッド: ✅ 完了(フェーズ5) — ログインだけでなく、独立したすべてのフルスクリーンラッパーから不透明な
bg-bgを削除し、すべての画面でグリッドが表示されるようにしました。§4.6を参照してください。 - D5 — ランディングページ: アニメーション付きスプラッシュは現状のまま維持。選択済み。
- D6 — 製品全体で角丸を14/9に統一: 推奨: はい(フェーズ2)。
- D7 — フェーズ1を先にリリース: 選択済み。
- D8 — レイアウト幅(フェーズ5): ダッシュボードのコンテンツシェルは
max-w-7xl(1280px)に制限されていたため、大型モニターでは中央寄せになり、左右に広い空白が生じていました。✅ 完了 — 流動的なmax-w-[3840px](真の4K)に引き上げました。コンテンツは約4Kまでビューポートに追従し、それを超えた場合にのみ中央寄せされます(DashboardLayout.tsx)。意図的に幅を狭くしているページは、設計どおり狭いままです(ProviderOnboardingWizardは max-w-5xl、Rtk/CavemanContextPageClientは max-w-6xl)。 - D9 — 不透明なデータテーブル(フェーズ6): ダッシュボードのコンテンツ領域が透明になり(フェーズ5でグリッド壁紙が透けて見えるようになったため)、コンテナが不透明なサーフェスではないデータテーブルでは、透明な偶数行 / 低アルファのゼブラ行からグリッドが透けていました。✅ 完了 — Cardなしのすべてのテーブルが
bg-surfaceを描画するようになりました(<DataTable>プリミティブでは、スクロールコンテナにbackground: var(--color-surface)を指定)。修正対象:DataTable(プリミティブ)、ProxyLogger/RequestLoggerV2(それらの<Card>に指定されたbg-black/5 dark:bg-black/20の色合いが、tailwind-mergeによってCardのbg-surfaceより優先され、約95%透明になっていました)、BatchListTab/FilesListTab/CacheEntriesTab/ReasoningCacheTab/cache page/FreePoolTab/ModelMappingTable/HeaderTable、およびcacheビュー内のCSSグリッド製「テーブル」2つ(bg-surface/35→bg-surface)。すでに<Card>/Modal 内にあるテーブルは不透明であることを確認し、意図的に変更していません(そこでの bg-surface は冗長で効果のない指定です)。グリッド自体は変更不要でした。ダッシュボードのbody::beforeはサイトとバイト単位で同一です(--grid-size: 32px)。実行中のインスタンスで「より大きなグリッド」が見える場合、それはコードによるものではなく、#4143より前の古いビルドです。tests/unit/design-grid-background.test.ts(フェーズ6のブロック)でガードされています。
9. スコープ外 / リスク
Section titled “9. スコープ外 / リスク”- パレット変更なし — 色はすでに一致しており、不足しているトークンのみを追加します。製品の配色が変わるリスクはありません。
- テーマエンジン変更なし —
.dark+ Zustand ストアを維持します。 - 角丸の変更(フェーズ2)は広範囲 — すべてのカード、ボタン、入力に影響するため、マージ前に要素の多い画面(テーブル、モーダル)を目視確認します。
- テーブル(C3) はハードコードされたスタイルが最も多く、回帰の影響範囲も最大です。専用のPRに分離します。
10. リファレンス一覧
Section titled “10. リファレンス一覧”| 領域 | パス |
|---|---|
| ダッシュボードのトークン | src/app/globals.css(:root、.dark、@theme inline、body、body::before) |
| テーマストア | src/store/themeStore.ts、src/shared/components/ThemeProvider.tsx、src/shared/constants/appConfig.ts:9-11 |
| パネルシェル(ここでグリッドを有効化) | src/shared/components/layouts/DashboardLayout.tsx |
| Chrome | src/shared/components/Header.tsx:207、src/shared/components/Sidebar.tsx:430 |
| グリッドの先行実装 | src/app/landing/page.tsx:16-26 |
| プリミティブ | src/shared/components/{Button,Card,Input,Select,Badge,Modal,Toggle,SegmentedControl,Loading,Tooltip,DataTable}.tsx |
| ステータスカラーの定義元 | flow/edgeStyles.ts、TokenHealthBadge.tsx、DegradationBadge.tsx、logTableStyles.ts |
cn ユーティリティ |
src/shared/utils/cn.ts |
| フェーズ1のガードテスト | tests/unit/design-grid-background.test.ts |
| サイトの参照元 | _mono_repo/omnirouteSite/css/tokens.css、css/base.css |
HagiCode
HagiCode は構造化ワークフロー、マルチエージェント実行、Hero Dungeon ビューを備えたエージェント型コーディングワークスペースです。
よりスマートで速く、楽しいエージェント型ワークフローで、使いやすいソフトウェアを形にします。

- Smart構造化ワークフローは意図をアイデアから変更のリリースまで実行可能な道筋にします。
- Efficientマルチエージェントのワークフローで調査、実装、レビューを並行して進めます。
- FunHero Dungeon により長時間のコーディングを視覚的で協力的な体験にします。