InfraGuard

ライト / ダークテーマ

コンソールをライトとダークで切り替えます — ルート要素の data-theme 属性ひとつ、localStorage(infr-theme)への保存、ヘッダーのトグル、そしてすべての色を --infr-* CSS 変数トークンで表現します。

概要 — 何をする機能か

InfraGuard コンソールには ダーク(既定) と ライト の2つのテーマが用意されています。テーマはドキュメントのルート要素(<html>)に付く単一の属性 data-theme で切り替わり、その値が SCSS で定義された --infr-* CSS 変数トークン のセット全体を入れ替えます。すべてのコンポーネントはハードコードした16進数ではなく var(--infr-*) トークンを使うため、単語をひとつ(dark ↔ light)変えるだけで UI 全体が即座に塗り直されます。

既定は ダーク です — NOC(ネットワーク運用センター)のコンソールとして、深いブルーブラックの背景にティールのシグナルアクセントを合わせ、深刻度の色(crit / warn / good)が暗い画面上でくっきり読み取れるようにしています。

<html data-theme="dark">   ← 既定。NOC 向けダーク
<html data-theme="light">  ← ライト(明るいオフィス環境向け)

テーマは 純粋なフロントエンドの設定 です。サーバーに保存されることは一切なく、アカウントやデータベースとも無関係で、ブラウザーの localStorage の中だけに存在します。ログアウトしても保持され、同じアカウントで別の端末からサインインした場合、その端末はその端末自身の設定に従います。


こんなときに使う

一度選べばそのブラウザーに保持されるため、通常は最初に一度設定するだけです。


画面構成

ヘッダーのトグルボタン

コンソールのシェル(layouts/app.blade.php)とログイン画面(layouts/simple.blade.php)のどちらも、トップバーの右側に テーマ切替ボタン を配置しています。

項目 値
マークアップのフック <button data-theme-toggle>
アイコン mdi-theme-light-dark(半月)
aria-label msg.action.theme(ローカライズ済み)
動作 クリックするとダーク ↔ ライトが入れ替わる
位置 トップバーのアクション領域(言語スイッチャーの隣、ユーザーメニューの左)

ログイン前(ゲスト)の画面にも同じトグルがあるため、認証しなくてもテーマを変更できます。

カラートークンのグループ

resources/scss/_variables.scss は、同じトークン名を異なる値で2つのブロック — :root[data-theme="dark"] と :root[data-theme="light"] — に定義しています。代表的なトークンは次のとおりです。

トークン 用途 dark light
--infr-bg ページ背景 #0b1220 #f6f8fb
--infr-surface パネル / カードの面 #111b2c #ffffff
--infr-fg 本文テキスト #e9eff8 #111a28
--infr-fg-muted 補助テキスト #8493ac #63728b
--infr-border 罫線 #1e2c43 #dbe2ec
--infr-accent アクセント(ティール) #2dd4bf #0d9488
--infr-crit 深刻度 critical #fb7185 #e11d48
--infr-warn 深刻度 warning #fbbf24 #b45309
--infr-good 深刻度 healthy #34d399 #0f9d6a
--infr-info 情報 #38bdf8 #0369a1

これら以外にも、各テーマは --infr-surface-2/hi、--infr-border-2、--infr-accent-soft/ink、--infr-on-accent(アクセント上のボタン文字色)、TCP 状態の色(--infr-state-*)、チャートの色(--infr-chart-2)、影 / グロー(--infr-shadow / --infr-glow)、トップバーのガラス表現(--infr-topbar-*)を定義しています。各ブロックは color-scheme: dark|light も宣言しているため、ネイティブのフォームコントロールやスクロールバーもテーマに揃います。

SSH ターミナルのパレットは例外です。 --infr-term-* トークンは data-theme に かかわらず 深く没入感のあるダークのままです。ライトテーマでも SSH コンソール のターミナルはダークを保ちます。


使い方

切り替える

  1. トップバー右側の 半月アイコン(テーマ切替) をクリックします。
  2. 即座にダーク ↔ ライトが入れ替わり、選択は自動的に保存されます。
  3. 次回のアクセス時やページの再読み込み時には、最後の選択が復元されます。

内部の仕組み(開発者向けリファレンス)

フロントエンドの配線は resources/js/app.js にあります。中心となるロジックは次のとおりです。

const THEME_KEY = 'infr-theme';                 // localStorage のキー
const get_theme = () => localStorage.getItem(THEME_KEY) || 'dark';   // 既定はダーク
const set_theme = (t) => {
    document.documentElement.setAttribute('data-theme', t);   // ルート要素の属性
    localStorage.setItem(THEME_KEY, t);                        // 永続化する
    window.dispatchEvent(new CustomEvent('infr:theme', { detail: t })); // チャートを再着色する
};
// トグルボタンを配線する
document.querySelectorAll('[data-theme-toggle]')
    .forEach(btn => btn.addEventListener('click',
        () => set_theme(get_theme() === 'dark' ? 'light' : 'dark')));

動作のまとめ:

ステップ 内容
保存キー localStorage['infr-theme'] = "dark" | "light"
適用先 document.documentElement(<html>)の data-theme 属性
既定値 dark(localStorage が空、または読み取れない場合)
イベント 切り替えのたびに window 上で infr:theme CustomEvent を発火(detail = 現在のテーマ)
タブ間の同期 storage イベントを購読 → 同じブラウザーの 他のタブ が自動的に同期する

スタイル未適用のちらつき(FOUC)の防止 — 描画前スクリプト

<head> の最上部に置いた小さなインラインスクリプト(app.blade.php と simple.blade.php で共通、CSS の @vite 読み込み より前)が、どのスタイルシートよりも先に data-theme を設定します。これにより再読み込み時の「ダーク→ライトのちらつき」がなくなります。

<script>
  (function () {
    try { document.documentElement.setAttribute('data-theme',
            localStorage.getItem('infr-theme') || 'dark'); }
    catch (e) { document.documentElement.setAttribute('data-theme', 'dark'); }
  })();
</script>

localStorage がブロックされている環境(シークレットウィンドウ、サードパーティストレージのブロックなど)でも、catch が安全に ダーク へフォールバックします。

チャートとエディターもテーマに追従する

<cm-editor v-model="script.body" lang="bash" :dark="is_dark_mode"></cm-editor>

データソース

テーマには DB もサーバー側の保存も一切ありません。 使うのは次のものだけです。

場所 内容
localStorage['infr-theme'] ブラウザーごとのユーザーの選択(dark/light)
<html data-theme> 実行時に適用されている状態
resources/scss/_variables.scss --infr-* トークンのテーマ別の実際の値(CSS にビルドされる)
resources/js/app.js トグル / 永続化 / イベントの配線

パレット設計の正本は CLAUDE.md の 付録 C(ライト / ダークテーマトークン) です。


アクセス権限

テーマは 認証や認可とは無関係の UI 設定 です。


トラブルシューティングと FAQ

Q. 再読み込みするとテーマが元に戻ります。 ブラウザーが localStorage をブロックしている場合(シークレットウィンドウ、厳格なプライバシー設定、サードパーティストレージのブロック)、選択を保存できないため毎回既定の ダーク に戻ります。そのサイトにストレージへのアクセスを許可してください。

Q. 片方のタブで変更したのに、もう片方のタブが更新されません。 切り替えは storage イベントを通じて 同じブラウザーの他のタブ に伝わります。すぐに反映されない場合、そのタブはまだリスナーの配線(app.js)を読み込んでいない可能性があります — 再読み込みしてください。端末やブラウザーが異なる 場合はストレージが別なので同期しません(これは仕様です)。

Q. ライトに切り替えたのに SSH ターミナルはダークのままです。 想定どおりの動作です。ターミナルは、アプリのテーマにかかわらず深いダークを保つ専用の --infr-term-* パレットを使用します(可読性 / 没入感のため)。

Q. あるコンポーネントだけ表示がおかしい(テーマが適用されない)。 そのコンポーネントがトークンではなく16進数をハードコードしています。規約上、コンポーネントは var(--infr-*) トークンだけを使わなければなりません。回帰チェック用の grep で resources/scss/pages に直接の16進数がないか確認してください。

rg -n "#[0-9a-fA-F]{3,6}" resources/scss/pages

Q. OS のダークモードに追従させたいです。 現在の実装は OS の設定(prefers-color-scheme)に 追従しません。初期値は常に dark で、ユーザーがトグルで明示的に選んだものだけを記憶します。OS 連携はロードマップの項目です。


関連項目

상단바 오른쪽의 테마 · 언어 전환
상단바 오른쪽의 테마 · 언어 전환