Panda CSS 設計書
最終更新: 2026-11-06(既知の基準未達に、OG のカードの文字の実効の比を追加、MorningStatusApp#1805)
1. 概要
フォールダブル端末・広画面対応(MorningStatusApp#1648)を契機に導入した Panda CSS のセットアップ内容と、既存スタック(Tailwind CSS v4・CSS Modules・app/globals.css)との共存方式を扱う設計書(MorningStatusApp#1655)。
Panda CSS は Zero-Runtime(ビルド時にCSSを静的生成する)かつ TypeScript の型補完が効くスタイリングライブラリ。フォールダブル端末の展開判定(~580px付近)のようなカスタムブレークポイントを型安全に扱える点、および Next.js App Router との親和性を理由に採用した。
実際にコンポーネント・画面へ Panda CSS を適用していく段階移行の範囲は本書の対象外で、MorningStatusApp#1656 側で決定する。本書は、その前提となる「導入設定」と「既存スタックとの共存方式」の確定内容に限定する。長期的にはTailwind CSSを撤去しPanda CSS単独の構成へ移行する方針であり、その位置づけは§5を参照。
Panda CSS の活用方針と配色トークンの設計は§8を参照。
2. セットアップ内容
- 依存関係:
@pandacss/devを devDependency として追加 - 設定ファイル: リポジトリルートの
panda.config.tsinclude:./app/**/*.{js,jsx,ts,tsx}と./components/**/*.{js,jsx,ts,tsx}(Next.js App Router のディレクトリ構成に合わせる。panda initの初期値であるsrc/・pages/はこのプロジェクトでは使わない)preflight: false(§3-1参照)outdir: "styled-system"(生成物。.gitignoreに追加し、コミット対象外とする。bunx panda codegenまたは後述のPostCSSプラグインがビルド時に自動生成する)- プリセット:
presets: ["@pandacss/preset-base", "@pandacss/preset-panda"]を明示し、両パッケージを devDependency として追加する。Panda CSS v2 ではプリセットが暗黙に追加されないため、明示しないとmd・foldなどのブレークポイントが条件として認識されず、css()のmd: { ... }指定が一切適用されない
- PostCSS統合:
postcss.config.mjsのpluginsに@tailwindcss/postcssと並べて@pandacss/dev/postcssを追加。panda init --postcssは初期状態でpostcss.config.cjsを別ファイルとして生成するため、既存のpostcss.config.mjsに統合し、重複するPostCSS設定ファイルを残さないこと app/globals.cssの@import "tailwindcss";の直後に@layer reset, base, tokens, recipes, utilities;を追加。@pandacss/dev/postcssはビルド時にこの宣言の位置へ生成CSSを注入する
3. Tailwind CSS v4 との共存方式
3-1. カスケードレイヤーの優先順位
Tailwind CSS v4 は @import "tailwindcss" の展開により @layer theme, base, components, utilities; を、Panda CSS は @layer reset, base, tokens, recipes, utilities; をそれぞれ宣言する。CSSの @layer は同名レイヤーであれば宣言位置に関わらず1つに統合され、初出のレイヤー名だけがその位置に新規追加される仕様のため、実際のレイヤー優先順位(低→高)は次のようになる。
theme < base(Tailwind+Panda共有) < components < utilities(Tailwind+Panda共有) < reset < tokens < recipes
base と utilities は Tailwind・Panda 両方が同名レイヤーを使うため統合され、レイヤー内では後から追加されたCSSほど優先される(globals.css 内で Tailwind の @import より Panda の @layer 宣言が後にあるため、同一プロパティが競合した場合は Panda 側の指定が勝つ)。実機検証(Playwright、class="bg-red-500" と css({ bg: "blue.500" }) を同一要素に適用)でも Panda側が優先されることを確認済。
備考: Panda の
preflight(ブラウザデフォルトスタイルのリセット)はfalseに設定している。Tailwind v4 が@import "tailwindcss"により自前の preflight をbaseレイヤーへ既に注入しており、二重適用を避けるため。
3-2. レイヤー外(unlayered)CSSは常に最優先
app/globals.css の :root 変数定義や *, html, body 等、@layer で囲まれていないCSSは、CSS仕様上どの @layer 内のCSSよりも常に優先される。既存のグラスモーフィズム等のカスタムスタイルはこの位置にあり、Panda・Tailwindいずれのユーティリティクラスとも衝突しない。
3-3. .container → .app-container への改名と、Panda化の経緯(重要な注意点)
備考(バグとして顕在化した問題と対策): 共通レイアウトの最大幅(1200px)を実現していた独自クラス
.container(app/globals.css、app/layout.tsx等)を Panda 化する過程で、2段階の技術的な非互換が技術検証中に判明した。問題1(クラス名の衝突):
.containerという名前のまま Panda のglobalCssに移行したところ、幅1920pxで通常画面のmax-widthが意図しない1536pxになった。原因は、Tailwind CSS v4 が@import "tailwindcss"により、ソース内でcontainerというクラス名トークンが使用されていると、組み込みのレスポンシブ.containerユーティリティ(@layer utilities、ブレークポイントごとにmax-widthが変わる)を自動生成するため。移行前は独自の.containerが@layerの外(unlayered)にあり §3-2 の理由で常に最優先されていたため問題にならなかったが、Panda のglobalCss(baseレイヤー)に移した時点で、より優先度が高いutilitiesレイヤーにある Tailwind組み込み.containerに負けるようになった。→ 対策として、クラス名を
.app-containerに改名し、Tailwindの組み込み.containerと名前の衝突を避けた(ソース上のトークンcontainerが無くなることで、TailwindのJITスキャンが組み込みユーティリティを生成しなくなる効果もある)。問題2(プロジェクト自身のレイヤー外リセットとの衝突。改名だけでは解決しない):
.app-containerに改名した後も、padding/marginが0になる不具合が残った。原因は、app/globals.cssの* { box-sizing: border-box; padding: 0; margin: 0; }という、このプロジェクト自身が持つレイヤー外のリセットCSS。§3-2の通りレイヤー外CSSは常に最優先されるため、Panda のglobalCss(レイヤー内)に置いた.app-containerのpadding/margin指定は、詳細度に関わらずこのリセットに負ける。Tailwindとは無関係に、「レイヤー外CSSを前提にした既存のglobals.cssの構造」と「Panda の globalCss(レイヤー内)」がそもそも噛み合わないという、より根本的な非互換であることが分かった。当初の対応(#1655時点):
.app-containerのクラス名改名は維持しつつ、CSS定義自体はPandaのglobalCssに移さず、従来通りapp/globals.cssへレイヤー外の生CSSとして書く方針とした。globals.css側のレイヤー外リセット構造ごと見直す(全廃してPanda/Tailwindのレイヤー体系に揃える)選択肢も検討したが、影響が全画面に及ぶ大改修になるため#1655の範囲外とした。
解決(#1667): Tailwind撤去(#1656)により
@layer reset, base, tokens, recipes, utilities;の宣言順がPanda単独で完全に確定した後、問題2の根本原因だったapp/globals.cssの* {...}リセットを、レイヤー外の生CSSから明示的に@layer reset { * {...} }へ移した。宣言順(resetが最初=最も低優先度、baseがその次)により、PandaのglobalCss(baseレイヤーに出力される)がresetレイヤーより優先されるようになったため、.app-containerのCSS定義をPandaのglobalCss(panda.config.ts)へ安全に移行できた。PlaywrightでgetComputedStyle・getBoundingClientRectを計測し、デスクトップ幅(padding: 0 2rem・中央寄せ)・モバイル幅(padding: 0 1rem)・世代マトリックス画面のワイドキャンバス例外(max-width: none)のいずれも意図通り動作することを実機検証済。
.app-container の実体は次の通り(panda.config.ts の globalCss。#1667でレイヤー外の生CSSから移行済)。
globalCss: {
".app-container": {
maxWidth: "1200px",
marginX: "auto",
padding: "0 1rem",
md: {
padding: "0 2rem",
},
},
"main.app-container:has(> [data-wide-canvas])": {
maxWidth: "none",
},
},
app/globals.css の * {...} リセットは @layer reset { ... } へ移行済(レイヤー外の生CSSとしては残っていない)。
ワイドキャンバス例外(世代マトリックス画面のみ最大幅を外す仕組み)の考え方自体は変更していない。世代マトリックス 画面設計書 §4-8を参照。data-wide-canvas 属性をページ直下に付与する実装(app/generational-matrix/page.tsx)も変更なし。
影響を受けた参照元(className="container" → className="app-container" に改名): app/layout.tsx(header・main・footer)、app/ameba/page.tsx、app/instagram/page.tsx、app/instagram/[accountId]/page.tsx、app/tiktok/page.tsx、app/tiktok/official/[accountId]/page.tsx、app/tiktok/og/[memberId]/page.tsx、app/youtube/page.tsx、app/youtube/official/page.tsx、app/youtube/og/[memberId]/page.tsx。
4. カスタムブレークポイント(fold)
フォールダブル端末の展開時(~580px付近)を判定するため、panda.config.ts の theme.extend.breakpoints に fold: "36.5rem"(584px 相当)を追加した。Panda のブレークポイントは min-width ベース(モバイルファースト)で解釈されるため、CLAUDE.mdのモバイルファースト規約と自然に合致する。
theme: {
extend: {
breakpoints: {
fold: "36.5rem",
},
},
},
デフォルトのブレークポイント(sm・md・lg・xl・2xl)は extend により維持される。36.5rem(= 584px)という値は、Samsung Galaxy Fold系の展開時インナーディスプレイ幅を目安とした一般的な業界慣行値。単位は他のブレークポイントに合わせて rem とした。Panda CSS v2 は単位の混在を警告する。
このブレークポイントを一覧画面のグリッド実装で採用するかどうかの検証結果は§6-2を参照(結論としては列数変更には使用していない)。
5. 段階移行の方針と将来方針
本書§1〜4のセットアップと .app-container(ワイドキャンバス機構。§3-3の理由によりCSS定義自体は globals.css に残す)は #1655 の対応範囲。それ以外のコンポーネント・画面をPanda化する範囲・優先順位は、本書で確立した共存方式をもとに MorningStatusApp#1656(一覧画面のグリッド実装。§6参照)で対応する。
将来方針: Tailwind CSS の撤去とPanda CSS単独化
§3-3で判明した2つの非互換(Tailwind組み込みユーティリティとの命名衝突、globals.css のレイヤー外リセットとの構造的な非互換)は、いずれも「TailwindとPandaが同居し、かつ globals.css にレイヤー外CSSが残っている」という過渡的な状態に起因する。共存を維持し続けるコストを避けるため、Tailwind CSS v4 を撤去し、Panda CSS単独の構成へ移行する方針とする。
備考(#1656実装時に判明した記載の誤り): 当初、この撤去作業の対象は「#1655時点の調査で
app/・components/配下223ファイル中25ファイルがTailwindのユーティリティクラスを使用」としていたが、#1656実装着手時にclassName・テンプレートリテラル・clsx等あらゆるパターンで網羅的に再調査した結果、実際にTailwindユーティリティクラスを使用していたのはcomponents/PageLoadingSkeleton.tsxのanimate-pulse1箇所のみだった。「25ファイル」の根拠となる調査方法の記録は残っておらず、過度に広い検索パターンによる誤検出だった可能性がある。撤去作業自体はanimate-pulseの置き換えと依存関係・設定の削除で完了しており、実害はない。
なお、Tailwind撤去そのものはglobals.cssのレイヤー外リセットとの構造的な非互換(§3-3の問題2)を自動的には解消しないため、.app-containerのPanda化は本Issueの範囲外としてMorningStatusApp#1667 へ切り出した。#1667では、リセット自体を@layer resetへ移すことで問題2を解消し、.app-containerのPanda化を完了している(詳細は§3-3参照)。
6. 一覧画面のレスポンシブグリッド実装パターン(#1656)
対象画面は、既に style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(Npx, 1fr))" }} というインラインstyleでグリッドを実装していたが、auto-fill は画面幅に応じて列数が連続的に変化するため、CLAUDE.mdのモバイルファースト規約(「CSS Grid はモバイルファーストで実装する」節)が求める「デフォルト1列、768px以上で複数列」という明確な切り替え点を持たない。Panda CSSのcss()に移行するタイミングで、この切り替え点を明示する。
6-1. 対象画面
- Instagram一覧画面(
app/instagram/page.tsx) - Instagram公式アカウント管理(デスクトップモード、Instagram一覧画面内)(
components/InstagramOfficialAccountsEditor.tsx) - Instagram公式アカウント詳細画面(
app/instagram/[accountId]/page.tsx・components/OfficialInstagramSection.tsx) - TikTok一覧画面(
app/tiktok/page.tsx) - TikTok公式アカウント管理(デスクトップモード、TikTok一覧画面内)(
components/TikTokOfficialAccountsEditor.tsx) - TikTok公式アカウント詳細画面(
app/tiktok/official/[accountId]/page.tsx) - TikTok OGメンバー投稿画面(
app/tiktok/og/[memberId]/page.tsx) - YouTube一覧画面(
app/youtube/page.tsx) - YouTube公式チャンネル一覧画面(
app/youtube/official/page.tsx) - YouTube OGメンバー投稿画面(
app/youtube/og/[memberId]/page.tsx) - メンバー一覧画面(
components/MembersListView.tsx) - ユニット一覧画面(
app/units/page.tsx) - メンバー詳細画面のInstagram/TikTok/YouTubeセクション(
components/member-detail/InstagramSection.tsx・TikTokSection.tsx・YoutubeSection.tsx) - トップ画面の新着投稿セクション(
components/NewPostsSection.tsx) - 対比詳細画面の楽曲グリッド(
app/comparisons/[id]/page.tsx)
既存にグリッドパターンが無く新規のカードレイアウト設計が必要な画面(ライブ一覧・Amebaブログ一覧)は対象外とし、MorningStatusApp#1666 として別途切り出した。
6-2. 実装パターン
import { css } from "@/styled-system/css";
<div
className={css({
display: "grid",
gridTemplateColumns: "1fr",
gap: "1.5rem",
md: {
gridTemplateColumns: "repeat(auto-fill, minmax(280px, 1fr))",
},
})}
>
- デフォルト(モバイル幅)は
1frの1列固定。md(768px、Pandaのデフォルトブレークポイント)以上で、従来と同じauto-fill, minmax()に切り替える(768px以上では画面幅に応じた自然な列数調整を維持する) minmax()の最小幅(カード1枚あたりの幅)は画面ごとに異なるため、既存のインラインstyleに指定されていた値をそのまま踏襲する(例: SNS投稿一覧は140px〜200px、公式アカウント一覧・メンバー一覧・ユニット一覧は280px、対比曲グリッドは360px等)fold(36.5rem = 584px)ブレークポイントは、md(768px)に達する前の中間段階での列数変更には使わない。参考実装(app/timeline/page.module.css)も単一のブレークポイント(768px)のみで1列⇔複数列を切り替えており、この慣例に合わせる。フォールダブル端末の展開時(~580px〜768px)は引き続き1列で表示され、レイアウトが崩れないことを実機・シミュレータで検証する
7. 新規カードグリッド設計(ライブ一覧・Amebaブログ一覧、#1666)
§6の対象画面は既存のグリッドパターンをPanda化するだけだったが、以下の画面は元々グリッド自体が存在しない縦積みリストだったため、カードレイアウトを新規に設計した。
7-1. Amebaブログ一覧(app/ameba/page.tsx)
各行が既に.glassクラス(角丸・背景あり)でカード状のスタイルを持っていたため、新規デザインは行わず、flex-direction: column(縦1列固定)を§6-2と同じパターン(デフォルト1列、mdでauto-fill, minmax(280px, 1fr))に置き換えるのみとした。
7-2. ライブ一覧(年別 app/lives/year/[year]/page.tsx・都道府県別 components/PrefectureLiveEventsSection.tsx)
各公演は罫線区切りの1行(日付・時刻・会場名リンク・都道府県/ツアー名)で、カード化されていなかった。表示項目は変更せず、各行に.glassクラス(角丸・背景)を付与して軽量カード化した上で、グリッド化した。
import { css } from "@/styled-system/css";
<ul
className={css({
display: "grid",
gridTemplateColumns: "1fr",
gap: "0.75rem",
md: {
gridTemplateColumns: "1fr 1fr",
},
})}
>
<li className="glass" style={{ /* 既存のborderBottom区切りをやめ、padding・borderRadiusのみに変更 */ }}>
{/* 日付・時刻・会場名リンク・都道府県/ツアー名は変更なし */}
</li>
</ul>
auto-fill, minmax()ではなく、1fr 1frの固定2列とした。個々の公演行が短い1行情報(日付・会場名・都道府県)のため、app/timeline/page.module.cssの.eventGrid(grid-template-columns: 1fr 1fr)と同じ考え方を踏襲するgapは.eventGridの1.5remより詰めた0.75remとした。踏襲するのは列数の切り替え方針のみで、カード自体が軽量・低情報量なため間隔は独自に調整している- Playwrightで実機検証(モバイル375px: 1列、デスクトップ1280px: 2列)し、レイアウト崩れがないことを確認済
対象外のapp/lives/page.tsx(年ごとの一覧リンクへの入口)・app/lives/prefecture/[code]/page.tsx(都道府県名・出身メンバーバッジのみ、実データ表示はPrefectureLiveEventsSectionに委譲)は、リスト自体が短い(年数・都道府県コード程度)ため対象外。
8. 配色トークンの設計(#1745)
配色を Panda CSS のトークンで管理し、ダーク/ライトモード(MorningStatusApp#1735)を実現するための設計。
8-1. 方針
- 配色は
panda.config.tsのtheme.extend.semanticTokens.colorsに定義する - すべてのトークンにダークの値を定義する。ダークの値が標準の配色で、ライトの値は別に定義する。ダークの値だけで、ライトの値がなくても色が決まる。ライトとダークで同じ値の色(ブランドカラー等)には、ライトの値を定義しない
- ダーク/ライトの切り替え方式は §8-6、ライトの配色は §8-8 に定める
- インライン style の
css()への移行は、配色トークンとは別に扱う。CSS Modules を含めた移行と、カード・チップのレシピ化は、配色トークンを定義したあとに検討する
8-2. 既存の変数の別名
app/globals.css の :root にある色の変数 12 個は、次のトークンが出力する変数への別名にする。別名は :root { --text-muted: var(--colors-text-muted); } の形で、レイヤー外の生 CSS として書く。既存の使用箇所は書き換えない。フォントの変数 2 個は対象外とする。
| 既存の変数 | トークン | Panda が出す変数 |
|---|---|---|
--background |
background |
--colors-background |
--primary-color |
primary |
--colors-primary |
--secondary-color |
secondary |
--colors-secondary |
--bg-dark |
surface |
--colors-surface |
--bg-darker |
surface-deep |
--colors-surface-deep |
--card-bg |
card.bg |
--colors-card-bg |
--card-border |
card.border |
--colors-card-border |
--card-glow |
card.glow |
--colors-card-glow |
--text-main |
text.main |
--colors-text-main |
--text-muted |
text.muted |
--colors-text-muted |
--badge-active-bg |
badge.active.bg |
--colors-badge-active-bg |
--badge-active-text |
badge.active.text |
--colors-badge-active-text |
8-3. ライトモードの要件
- 色は、すべてトークン経由(
var(--colors-…))で指定する - カテゴリ色分け辞書(4 つ)の色は、ライトの背景で読めるコントラストを確保する
- 入力系コンポーネント(
<input>・<textarea>・<select>)に、背景色と文字色を明示する(開発ノート「UI/UX設計」知見 4) - ダーク/ライトの切り替えは、
<html>のクラスとcolor-schemeで行う(§8-6)
カテゴリ色分け辞書のトークン
カテゴリ色分け辞書 4 つの色は、辞書ごとのトークンで持つ(計 25 個)。すべてにダークの値を定義する。辞書をまたいで同じ色になるトークンも、辞書ごとに別のトークンとして持つ(辞書は別々の場面で使われる独立した体系のため)。名前は、Panda が出す変数名(トークン名の . を - にしたもの)と一致するよう kebab-case にする。
| 辞書(定義場所) | トークン | 変数 | ダーク |
|---|---|---|---|
EVENT_TYPE_COLORS(lib/event-colors.ts) |
event-type.live |
--colors-event-type-live |
#a78bfa |
event-type.festival |
--colors-event-type-festival |
#fb923c |
|
event-type.topic |
--colors-event-type-topic |
#94a3b8 |
|
event-type.media |
--colors-event-type-media |
#38bdf8 |
|
event-type.join |
--colors-event-type-join |
#4ade80 |
|
event-type.graduate |
--colors-event-type-graduate |
#f87171 |
|
event-type.leader |
--colors-event-type-leader |
#ffd700 |
|
RADIO_SHOW_COLORS(components/EventCard.tsx) |
radio-show.morning-gakuin(モーニング女学院) |
--colors-radio-show-morning-gakuin |
#fb923c |
radio-show.youngtown-saturday(ヤングタウン土曜日) |
--colors-radio-show-youngtown-saturday |
#38bdf8 |
|
radio-show.may-bonsoir(メイボンソワ) |
--colors-radio-show-may-bonsoir |
#a78bfa |
|
radio-show.harusanchi(はるさんち) |
--colors-radio-show-harusanchi |
#34d399 |
|
RELEASE_FORMAT_COLORS(components/EventCard.tsx) |
release-format.single |
--colors-release-format-single |
#f472b6 |
release-format.album |
--colors-release-format-album |
#60a5fa |
|
release-format.ep |
--colors-release-format-ep |
#a78bfa |
|
release-format.live |
--colors-release-format-live |
#34d399 |
|
release-format.soundtrack |
--colors-release-format-soundtrack |
#fbbf24 |
|
release-format.compilation |
--colors-release-format-compilation |
#fb923c |
|
release-format.other |
--colors-release-format-other |
#94a3b8 |
|
TAG_CHIP_COLORS(components/EventCard.tsx) |
tag-chip.birthday |
--colors-tag-chip-birthday |
#f472b6 |
tag-chip.solo |
--colors-tag-chip-solo |
#60a5fa |
|
tag-chip.unit |
--colors-tag-chip-unit |
#a78bfa |
|
tag-chip.og |
--colors-tag-chip-og |
#fb923c |
|
tag-chip.special |
--colors-tag-chip-special |
#fbbf24 |
|
tag-chip.collaboration |
--colors-tag-chip-collaboration |
#34d399 |
|
未登録・フォールバック(各所に直書きの #94a3b8) |
category.fallback |
--colors-category-fallback |
#94a3b8 |
辞書の値は、var(--colors-event-type-live) のような変数の参照を、文字列として直接書く。辞書はクライアント側のコードからも使われるため、トークン表を丸ごと読み込む token.var()(styled-system/tokens)ではなく、文字列を書く。辞書にないキーの色は var(--colors-category-fallback) とする。参照先の打ち間違いは、test/color-tokens.test.ts で、panda.config.ts に定義されたトークンと突き合わせて検出する。
背景の透明色
辞書の色の背景色(`${色}22` のように 16 進数の透明度 22 を連結する作り方)は、color-mix(in srgb, ${色} 13.33%, transparent) で作る。22 は 34/255(約 13.33%)の不透明度で、16 進数のメンバーカラーと、var() で参照する辞書の色のどちらにも同じ書き方で使える。
透かす不透明度は、用途ごとに決める。withOpacity(色, 不透明度)(lib/color-utils.ts)が color-mix(in srgb, ${色} <不透明度>, transparent) を返し、背景の透かし(tintBackground())は、不透明度 13.33% の withOpacity() である。年表のクロニクル表示では、ツアーの枠を 30%、節目(加入・卒業・リーダー)の背景を 15% にする。`${色}4d` のように 16 進数の透明度を連結する作り方は、var() の色に使えないため、withOpacity() で作る。
辞書以外の追加トークン
辞書の色以外のトークンは、次のとおり。すべてにダークの値を定義する。
| トークン | 変数 | ダーク | 用途 |
|---|---|---|---|
card.text-art-bg |
--colors-card-text-art-bg |
rgba(255, 255, 255, 0.05) |
画像のないイベントカードで、アクセント色がない場合のテキストアートの背景 |
共通のトークン(白の透過・黒の透過・白)
画面をまたいで使う色のトークン。すべてにダークの値を定義する。変数名は --colors- に、トークンのパスを - でつないだ名前を続ける(例: overlay.85 は --colors-overlay-85)。ライトの値は §8-8 に定める。
| トークン | ダーク | 役割 |
|---|---|---|
overlay.4 5 6 7 8 10 12 14 15 18 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 |
rgba(255, 255, 255, <数値>%) |
背景・枠線・文字に使う、白の透過。数値が不透明度(%) |
scrim.10 15 20 30 50 55 60 80 |
rgba(0, 0, 0, <数値>%) |
影・縁取りに使う、黒の透過 |
white |
#fff |
色付きの背景の上の、固定の白の文字(メンバーカードの名前など)。ライトモードでも切り替えない |
白い文字のトークンは、背景で選ぶ。overlay.* の面(パネル、ボタンの背景など)の上で、ライトモードでは黒系に反転させる文字には、overlay.100(不透明な白)を使う。メンバーカラーやバッジの色など、色付きの背景の上で、テーマに依存せず白のままにする文字には、white を使う。
メンバー関係性マップ・レーダーチャートの色のトークン
メンバー関係性マップ(/member-map)とメンバー関係性レーダーチャート(/member-map/radar)に固有の色は、次のトークンで持つ。すべてにダークの値を定義する。2 つの対応表では、共通のトークンと合わせて使う。
| トークン | ダーク | 役割 |
|---|---|---|
relationship.surface |
#0f0f0f |
2 画面の背景(読み込み中・エラー表示を含む) |
relationship.surface-raised |
#1e1e2e |
選択ボックスの選択肢、拡大・縮小ボタンの背景 |
relationship.surface-raised-hover |
#2a2a3e |
拡大・縮小ボタンのホバー時の背景 |
relationship.accent |
#f97316 |
橙。選択中・実行系のボタンの背景、順位が変わったメンバーの名前 |
relationship.accent-soft |
#fb923c |
橙のボタンのホバー時の背景 |
relationship.accent-bg |
rgba(249, 115, 22, 0.25) |
「期グループ」などの選択中の背景 |
relationship.accent-border |
rgba(249, 115, 22, 0.6) |
同じ選択中の枠 |
relationship.on-accent |
#0f0f0f |
橙の背景の上の文字 |
relationship.selected-bg |
rgba(99, 102, 241, 0.3) |
関係性マップ画面のモード切替ボタンの選択中の背景(藍) |
relationship.selected-border |
rgba(99, 102, 241, 0.7) |
同じ選択中の枠 |
relationship.danger |
rgba(255, 100, 100, 0.9) |
エラー文言、削除操作のホバー時の文字 |
relationship.danger-border |
rgba(255, 100, 100, 0.4) |
グループの削除ボタンのホバー時の枠 |
relationship.danger-soft |
#fca5a5 |
警告帯の文字 |
relationship.info |
rgba(180, 220, 255, 0.8) |
イベント一覧の参加メンバー数バッジの文字(水色) |
relationship.info-bg |
rgba(100, 160, 255, 0.12) |
同じバッジの背景(青) |
edge-label.bg |
rgba(255, 255, 255, 0.82) |
関係線の中央の白いラベルの背景 |
edge-label.text |
#333 |
同じラベルの文字 |
メンバー関係性マップ画面の部品と色
| 画面の部品 | 色 |
|---|---|
| 画面の背景 | relationship.surface |
| ヘッダーの帯(背景・下線) | overlay.4・overlay.8 |
| 見出し | overlay.85 |
| 「↗ レーダーチャートで見る」リンク(通常・ホバー) | overlay.60・overlay.85 |
| 「保存」ボタン(文字・背景・ホバー時の背景・枠) | overlay.85・overlay.10・overlay.18・overlay.20 |
| 保存エラーの文言 | relationship.danger |
| 上のコントロール帯(背景・下線・区切り線) | overlay.4・overlay.8・overlay.10 |
| モード切替ボタン(通常の文字・ホバー時の文字・枠・ホバー時の背景) | overlay.55・overlay.85・overlay.15・overlay.8 |
| モード切替ボタンの選択中(背景・枠・文字) | relationship.selected-bg・relationship.selected-border・overlay.95 |
| 軸ボタン(通常の文字・ホバー時の文字・枠・ホバー時の背景) | overlay.55・overlay.80・overlay.12・overlay.6 |
| 軸ボタンの選択中(背景・枠・文字) | overlay.12・overlay.35・overlay.95 |
| 値の選択ボックス(文字・背景・枠) | overlay.85・overlay.8・overlay.20 |
| 選択ボックスの選択肢(背景・文字) | relationship.surface-raised・overlay.90 |
| 「クリア」ボタン(文字・ホバー時の文字・枠・ホバー時の背景) | overlay.45・overlay.70・overlay.10・overlay.6 |
| 左のイベント一覧パネル(背景・右線) | overlay.4・overlay.10 |
| パネルの見出しの下線 | overlay.10 |
| 「タイムラインで見る」リンク(通常・ホバー) | overlay.60・overlay.90 |
| 閉じたパネルのタブ(文字・ホバー時の文字・ホバー時の背景) | overlay.45・overlay.75・overlay.4 |
| イベント項目(通常の文字・ホバー時の背景) | overlay.75・overlay.8 |
| イベント項目の選択中(背景・文字) | overlay.14・overlay.100 |
| イベントの日付(通常・選択中) | overlay.45・overlay.70 |
| イベントの種別ラベル(文字・背景) | overlay.40・overlay.8 |
| 参加メンバー数のバッジ(文字・背景) | relationship.info・relationship.info-bg |
| 一覧が空のときの文言 | overlay.35 |
| 一覧のスクロールバー | overlay.20 |
| 拡大・縮小ボタン(背景・ホバー時の背景・文字・枠・無効時の文字) | relationship.surface-raised・relationship.surface-raised-hover・overlay.80・overlay.15・overlay.25 |
| メンバーのカード(枠・影・名前・名前の影・小さい文字・小さい文字の影) | overlay.40・scrim.30・white・scrim.60・overlay.85・scrim.50 |
| カードの接続点(背景・枠) | overlay.60・scrim.20 |
| グループ枠のラベル(文字・影) | overlay.65・scrim.80 |
| 関係線のラベル(背景・文字・枠・影) | edge-label.bg・edge-label.text・scrim.10・scrim.15 |
メンバー関係性レーダーチャート画面の部品と色
| 画面の部品 | 色 |
|---|---|
| 画面の背景、ヘッダーの帯、見出し | 関係性マップ画面と同じ |
| 「← メンバー関係性マップに戻る」リンク(通常・ホバー) | overlay.60・overlay.85 |
| 見出しの説明文、小見出し | overlay.50 |
| 読み込み中・エラーの文言 | overlay.50 |
| 設定ボタン(文字・背景・ホバー時の背景・枠) | overlay.60・overlay.6・overlay.12・overlay.15 |
| 設定パネル(背景・枠)、ラベルの文字 | overlay.4・overlay.10、overlay.60 |
| 設定パネルの日付入力(文字・背景・枠) | overlay.85・overlay.8・overlay.20 |
| 設定パネルの「保存」ボタン(文字・背景・ホバー時の背景・枠) | relationship.on-accent・relationship.accent・relationship.accent-soft・relationship.accent |
| 設定のエラー文言、警告帯 | relationship.danger、relationship.danger-soft |
| 「比較グループ」「関係性ランキング(自動)」切替の通常(文字・背景・ホバー時の背景・枠) | overlay.60・overlay.6・overlay.12・overlay.15 |
| 同じ切替の選択中(文字・背景・枠) | relationship.on-accent・relationship.accent・relationship.accent |
| 「期グループ」「グループ全体」「手動選択グループ」の通常(文字・背景・ホバー時の背景・枠) | overlay.55・overlay.4・overlay.10・overlay.12 |
| 同じ3つの選択中(文字・背景・枠) | overlay.90・relationship.accent-bg・relationship.accent-border |
| 「グループを追加」ボタン(文字・背景・ホバー時の背景・枠) | overlay.85・overlay.10・overlay.18・overlay.20 |
| グループがないときの文言 | overlay.40 |
| グループのカード、ランキングのカード(背景・枠) | overlay.4・overlay.10 |
| グループ名、メンバー名 | overlay.85 |
| 順位が変わったメンバーの名前 | relationship.accent |
| ランキングの列見出し、点数 | overlay.70、overlay.50 |
| グループの削除ボタン(文字・枠・ホバー時の文字・ホバー時の枠) | overlay.50・overlay.15・relationship.danger・relationship.danger-border |
| メンバーのチップ(文字・背景) | overlay.80・overlay.8 |
| チップの削除「×」(通常・ホバー) | overlay.50・relationship.danger |
| メンバー追加の選択ボックス(文字・背景・枠) | overlay.85・overlay.8・overlay.20 |
| 凡例の文字 | overlay.70 |
| レーダーチャート本体(外枠線・軸線・軸ラベル) | overlay.12・overlay.18・overlay.65 |
| 下のタイムラインバー(背景・枠・日付ラベル) | overlay.4・overlay.10・overlay.70 |
| 再生ボタン(文字・背景・枠・ホバー時の背景) | relationship.on-accent・relationship.accent・relationship.accent・relationship.accent-soft |
| スライダーの目盛り | overlay.35 |
その他の画面の色のトークン
リンク編集・メンバーカード・ライブのツアー表示・イベントカード・世代マトリクス・新着投稿などの CSS Modules と app/globals.css の色(MorningStatusApp#1788)は、次のトークンで持つ。すべてにダークの値を定義する。共通のトークン(overlay.*・scrim.*・white)と、既存のトークン(card.bg・event-type.leader・primary)も使う。色の名前(white)で指定する色も、#fff と同じく white を使う。ライトの値は §8-8 に定める。
| トークン | ダーク | 役割 |
|---|---|---|
input.bg |
#fff |
白い入力欄の背景(リンク編集の選択ボックス・投稿検索欄・URL 入力欄) |
input.text |
#111 |
同じ入力欄の文字 |
feedback.success |
#27ae60 |
操作の成功を伝える文言 |
feedback.error |
#c0392b |
操作の失敗を伝える文言 |
status.success |
#4ade80 |
状態バッジの文字(現役、SNS バッジの成功) |
status.success-bg |
rgba(34, 197, 94, 0.2) |
同じバッジの背景 |
status.neutral-bg |
rgba(148, 163, 184, 0.2) |
状態バッジの背景(OG、SNS バッジの中立)。文字は text.muted |
status.error |
#f87171 |
SNS バッジの失敗の文字 |
status.error-bg |
rgba(239, 68, 68, 0.2) |
同じバッジの背景 |
status.warning |
#fbbf24 |
SNS バッジの不明の文字 |
status.warning-bg |
rgba(245, 158, 11, 0.2) |
同じバッジの背景 |
live-tour.join-bg |
rgba(52, 211, 153, 0.06) |
ツアー内の加入の行の背景 |
live-tour.join-text |
#34d399 |
同じ行の注記の文字 |
live-tour.graduate-bg |
rgba(251, 191, 36, 0.06) |
ツアー内の卒業の行の背景 |
live-tour.graduate-text |
#fbbf24 |
同じ行の注記の文字 |
live-tour.birthday-bg |
rgba(244, 114, 182, 0.06) |
ツアー内の誕生日の行の背景 |
live-tour.birthday-text |
#f472b6 |
同じ行の注記の文字 |
leader-badge.bg |
rgba(255, 215, 0, 0.13) |
イベントカードのリーダー退任バッジの背景(枠は event-type.leader) |
leader-badge.text |
#b8860b |
同じバッジの文字 |
venue-map-link.text |
rgba(180, 220, 255, 0.7) |
イベントカードの会場の地図リンク(通常) |
venue-map-link.text-hover |
rgba(180, 220, 255, 1) |
同じリンクのホバー時 |
generation-matrix.line |
rgba(248, 250, 252, 0.3) |
世代マトリクスの年齢の線(凡例を含む) |
generation-matrix.line-active |
rgba(248, 250, 252, 0.7) |
同じマトリクスの選択中の線(凡例を含む) |
tiktok.brand |
#69c9d0 |
新着投稿の TikTok リンクの枠・フォーカスの枠(TikTok のブランドの色) |
tiktok.brand-bg |
rgba(105, 201, 208, 0.1) |
同じリンクのホバー時の背景 |
primary-glow |
rgba(230, 0, 18, 0.2) |
主色の光(カードのホバー時の影、入力欄のフォーカス枠) |
その他の画面の部品と色
| 画面の部品 | 色 |
|---|---|
| リンク編集: 選択ボックス・投稿検索欄・URL 入力欄(背景・文字) | input.bg・input.text |
| リンク編集: エディタ枠の背景、タブと投稿ラベルのホバー時の背景 | overlay.4 |
| リンク編集: 選択中のタブの背景、投稿検索ボタンと追加ボタンのホバー時の背景 | overlay.6 |
| リンク編集: 成功の文言、エラーの文言 | feedback.success、feedback.error |
| リンク編集: 「保存」ボタンの文字 | white |
| メンバーカード: 現役の状態、SNS バッジの成功(背景・文字) | status.success-bg・status.success |
| メンバーカード: OG の状態、SNS バッジの中立(背景) | status.neutral-bg |
| メンバーカード: SNS バッジの失敗(背景・文字) | status.error-bg・status.error |
| メンバーカード: SNS バッジの不明(背景・文字) | status.warning-bg・status.warning |
| ライブのツアー表示: 簡易リストの背景 | card.bg |
| ライブのツアー表示: 加入の行(背景・注記の文字) | live-tour.join-bg・live-tour.join-text |
| ライブのツアー表示: 卒業の行(背景・注記の文字) | live-tour.graduate-bg・live-tour.graduate-text |
| ライブのツアー表示: 誕生日の行(背景・注記の文字) | live-tour.birthday-bg・live-tour.birthday-text |
| イベントカード: カードの影 | scrim.30 |
| イベントカード: リーダー退任バッジ(枠・背景・文字) | event-type.leader・leader-badge.bg・leader-badge.text |
| イベントカード: 会場の地図リンク(通常・ホバー) | venue-map-link.text・venue-map-link.text-hover |
| 世代フィルタ: ボタンのホバー時の文字 | overlay.100 |
| 世代フィルタ: ホバー時の枠、選択中の文字・枠 | var(--primary-color)(代替値を外す) |
| 世代フィルタ: 選択中の背景 | color-mix(in srgb, var(--primary-color) 15%, transparent)(代替値を外す) |
| 世代マトリクス: 年齢の線・選択中の線(凡例を含む) | generation-matrix.line・generation-matrix.line-active |
| 新着投稿: メディア種別タグの文字 | white |
| 新着投稿: TikTok リンクの枠・フォーカスの枠・ホバー時の背景 | tiktok.brand・tiktok.brand・tiktok.brand-bg |
| 検索画面: 入力欄の背景 | overlay.8 |
| 検索画面: 検索ボタン・形式バッジの文字 | white |
| 年スライダー: 前後ボタンのホバー時の背景 | overlay.7 |
| 年スライダー: 「移動」ボタンの文字 | white |
| 表示切替: ボタンのホバー時の背景、選択中の文字 | overlay.7、white |
| タイムライン画面: 年タブのホバー時の背景、選択中の年タブの文字 | overlay.7、white |
| 日付移動のボタン: ホバー時の背景 | overlay.7 |
| 比較ビューの列見出し、年表の年ラベル: 背景 | color-mix(in srgb, var(--bg-darker) 95%, transparent) |
| 比較ビュー: 比較ボタンの文字 | white |
| フィルタチップ: ホバー時の背景 | overlay.7 |
| フィルタチップ: 選択中の背景 | color-mix(in srgb, var(--primary-color) 12%, transparent) |
| ページ先頭へ戻るボタン: 文字・影 | white・scrim.30 |
| 全体のスタイル: デスクトップ表示のスクロールバー(通常・ホバー時) | overlay.25・overlay.40 |
| 全体のスタイル: カードの影、カードのホバー時(背景・枠・光) | scrim.30、overlay.6・overlay.20・primary-glow |
| 全体のスタイル: タイトルのグラデーション(始点・終点) | overlay.100・primary |
| 全体のスタイル: 暗い入力欄(背景・フォーカス時の背景・フォーカス枠・プレースホルダー) | overlay.5・overlay.8・primary-glow・overlay.30 |
| 全体のスタイル: 主ボタンの文字、Markdown のコードの背景 | white、overlay.10 |
カード・バッジ・詳細表示の色のトークン
メンバー詳細・ライブとフェスの詳細・新着投稿・「今日」「この日の出来事」・年表などの .tsx の色(MorningStatusApp#1789)は、次のトークンで持つ。すべてにダークの値を定義する。共通のトークン(overlay.*・scrim.*・white)と、既存のトークン(card.bg・category.fallback・event-type.live・feedback.error・status.*・tiktok.brand)も使う。色の名前(white)で指定する色も、#fff と同じく white を使う。ライトの値は §8-8 に定める。
| トークン | ダーク | 役割 |
|---|---|---|
status.error-solid |
#ef4444 |
編集画面の「削除」ボタンの背景(文字は white) |
status.error-soft |
#fca5a5 |
メンバー詳細の保存エラーの帯の文字 |
status.error-border |
rgba(239, 68, 68, 0.4) |
同じ帯の枠(背景は status.error-bg) |
leader-period.border |
rgba(234, 179, 8, 0.6) |
メンバー詳細のリーダー期間バッジの枠 |
leader-period.text |
#fbbf24 |
同じバッジの文字 |
leader-period.bg |
rgba(234, 179, 8, 0.1) |
同じバッジの背景 |
instagram.brand |
#e1306c |
Instagram の投稿カード・バッジ・見出し・リンク(Instagram のブランドの色) |
youtube.brand |
#ff0000 |
YouTube 動画カードのバッジ(YouTube のブランドの色) |
ameba.brand |
#2dad21 |
新着投稿の Ameba 欄の見出し(Ameba のブランドの色) |
today-card.bg |
rgba(242, 247, 251, 0.06) |
「今日」「この日の出来事」のカードと、新着投稿のセクションの外枠の背景 |
today-card.border |
rgba(100, 150, 200, 0.12) |
同じ要素の枠 |
today-card.icon |
#8aa3c2 |
「今日」「この日の出来事」の一覧の先頭の記号 |
timeline-type.join |
#4ade80 |
年表の加入の色 |
timeline-type.graduate |
#f87171 |
年表の卒業の色 |
timeline-type.release |
#60a5fa |
年表のリリースの色 |
timeline-type.live |
#fbbf24 |
年表のライブの色 |
timeline-type.festival |
#f472b6 |
年表のフェスの色 |
timeline-type.media |
#94a3b8 |
年表のメディアの色 |
timeline-type.leader |
#ffd700 |
年表のリーダーの色 |
timeline-type.topic |
#94a3b8 |
年表のトピックの色 |
備考: 年表の種別の色(timeline-type.*)は、イベントカードの種別の色(event-type.*)と値が異なる(ライブ・フェス・メディア)。別のトークンとして持つ。両者を 1 つにそろえる検討は、別の課題とする。
カード・バッジ・詳細表示の部品と色
| 画面の部品 | 色 |
|---|---|
| 各種のカード・枠の背景(メンバー詳細の近況・公式 SNS・Instagram・TikTok・YouTube、ライブとフェスの詳細、Instagram・TikTok・公式 Instagram のカード、動画の埋め込み枠) | overlay.5 |
| 読み込み中の骨組みの背景 | overlay.4 |
| 近況履歴の薄い面、プレイリスト行(通常)の背景 | card.bg |
| 新着投稿: Ameba のブログのリンクカード(背景・枠) | card.bg・overlay.6 |
| プレイリスト行(選択中)の背景 | overlay.8 |
| TikTok 投稿カードの枠 | overlay.10 |
| 「この日の出来事」の区切り線 | overlay.15 |
| メンバー詳細: メンバーカラーの丸印の縁 | overlay.20 |
| 枠付きの見出しラベル(グラデーションのとき)の枠 | overlay.30 |
| 新着投稿のサムネイルの影(メンバーカラーがないとき) | scrim.20 |
| TikTok 投稿カードの動画上の帯の背景 | scrim.55 |
色付きの背景の上の文字(バッジ・ボタン・ラベル。#fff・#ffffff・white の指定) |
white |
半透明の背景(overlay.*)の上の文字(追加ボタン) |
overlay.100 |
| ライブとフェスの詳細: エラーの文言 | feedback.error |
| ライブとフェスの詳細: 「セットリスト」見出しの色 | event-type.live |
| メンバー詳細: 現役の状態バッジ、公式 SNS の有効(背景・文字) | status.success-bg・status.success |
| メンバー詳細: OG の状態バッジ、公式 SNS の無効(背景) | status.neutral-bg。文字は text.muted |
| メンバー詳細: 保存エラーの帯(背景・枠・文字) | status.error-bg・status.error-border・status.error-soft |
| メンバー詳細: リーダー期間バッジ(枠・文字・背景) | leader-period.border・leader-period.text・leader-period.bg |
| 編集画面の「削除」ボタンの背景 | status.error-solid |
| Instagram のバッジ・見出し・リンク・カードのラベル | instagram.brand |
| YouTube 動画カードのバッジ | youtube.brand |
| TikTok のバッジ・リンクの文字・カード上のラベル | tiktok.brand |
| 新着投稿: Ameba 欄の見出し | ameba.brand |
| 「今日」「この日の出来事」のカード、新着投稿のセクションの外枠(背景・枠) | today-card.bg・today-card.border |
| 「今日」「この日の出来事」の一覧の先頭の記号 | today-card.icon |
| 年表: 種別の色(加入・卒業・リリース・ライブ・フェス・メディア・リーダー・トピック) | timeline-type.join・timeline-type.graduate・timeline-type.release・timeline-type.live・timeline-type.festival・timeline-type.media・timeline-type.leader・timeline-type.topic |
年表: 種別が未登録のときの色(TimelineChronicle・TimelineCompare のフォールバック) |
category.fallback |
画面ページ・編集画面・グラフ・地図の色のトークン
画面ページ・編集画面・グラフ・地図・選択部品の .tsx と、lib/ の色(MorningStatusApp#1790)は、次のトークンで持つ。すべてにダークの値を定義する。共通のトークン(overlay.*・scrim.*・white)と、既存のトークン(input.*・feedback.error・status.*・event-type.leader・youtube.brand・ameba.brand)も使う。constants/colors.ts の INSTAGRAM_COLOR・TIKTOK_COLOR・YOUTUBE_COLOR・NEW_POSTS_BLOCK_COLORS の値は、カテゴリ色分け辞書と同じく、var(--colors-…) の文字列で持つ。ライトの値は §8-8 に定める。
| トークン | ダーク | 役割 |
|---|---|---|
section-label.member |
#60a5fa |
見出しのラベルの色(所属メンバー・出演メンバー・関連メンバー) |
section-label.release |
#fb923c |
見出しのラベルの色(関連リリース・収録ライブアルバム) |
section-label.venue |
#94a3b8 |
見出しのラベルの色(同一会場の公演)。category.fallback と同じ値だが、役割が異なる |
sync-status.status |
#60a5fa |
同期状況の「近況同期」の見出し |
sync-status.genius |
#a78bfa |
同期状況の「Genius リンク同期」の見出し・数字・棒、取得進捗チャートの取得済みの棒 |
sync-status.discography |
#4ade80 |
同期状況の「ディスコグラフィー同期」の見出し・数字・棒、取得進捗チャートの取得済みの棒 |
chart.tooltip-bg |
rgba(20, 20, 40, 0.9) |
チャートのツールチップの背景 |
map-marker.bg |
rgba(59, 130, 246, 0.85) |
都道府県のマーカーの背景 |
today-card.accent |
rgba(100, 150, 200, 0.25) |
トップの日付の下の階層を示す左の縦線 |
new-posts-block.official |
#38bdf8 |
新着投稿の公式のブロックの見出し |
new-posts-block.active |
#34d399 |
新着投稿の現役のブロックの見出し |
new-posts-block.og |
#fb923c |
新着投稿の OG のブロックの見出し |
generation-matrix.self-birth |
#38bdf8 |
世代マトリクスの本人の誕生 |
generation-matrix.child-birth |
#f472b6 |
世代マトリクスの子の誕生 |
generation-matrix.band |
#a78bfa |
世代マトリクスのバンドの期間 |
generation-matrix.stage-preschool |
#34d399 |
世代マトリクスの未就学の年代 |
generation-matrix.stage-elementary |
#22d3ee |
世代マトリクスの小学の年代 |
generation-matrix.stage-junior-high |
#facc15 |
世代マトリクスの中学の年代 |
generation-matrix.stage-high-school |
#fb923c |
世代マトリクスの高校の年代 |
release-badge.single |
#2563eb |
リリースのバッジの背景(シングル)。文字は white |
release-badge.album |
#15803d |
同(アルバム) |
release-badge.ep |
#7c3aed |
同(EP) |
release-badge.live |
#c2410c |
同(ライブ) |
release-badge.soundtrack |
#a16207 |
同(サウンドトラック) |
release-badge.compilation |
#0e7490 |
同(コンピレーション) |
release-badge.other |
#6b7280 |
同(その他) |
radar-group.1 |
#f97316 |
関係性レーダーチャートの 1 番目のグループの色 |
radar-group.2 |
#60a5fa |
同(2 番目) |
radar-group.3 |
#4ade80 |
同(3 番目) |
radar-group.4 |
#f472b6 |
同(4 番目) |
radar-group.5 |
#c084fc |
同(5 番目) |
radar-group.6 |
#38bdf8 |
同(6 番目) |
radar-group.7 |
#facc15 |
同(7 番目) |
radar-group.8 |
#fb7185 |
同(8 番目) |
画面ページ・編集画面・グラフ・地図の部品と色
| 画面の部品 | 色 |
|---|---|
| 編集画面: 入力欄・選択肢の一覧の背景(YouTube リンク・セットリスト・対比グループ)、会場選択の背景 | overlay.5 |
| 編集画面: 「削除」の文字ボタン、エラーの文言 | feedback.error |
| 編集画面: YouTube リンクの「削除」ボタン(背景・文字) | status.error-solid・white |
| 編集画面: 「保存」「追加」ボタンの文字(主色の背景の上) | white |
| 公式アカウント編集(Instagram・TikTok): 入力欄(背景・枠) | overlay.6・overlay.20 |
| 公式アカウント編集: フォームの枠(背景・枠) | overlay.4・overlay.10 |
| 公式アカウント編集: 「保存」ボタンの文字(主色の背景の上) | white |
| 公式アカウント編集: 「キャンセル」ボタンの枠 | overlay.20 |
| 公式アカウント編集: 「+ アカウントを追加」ボタンの背景・枠 | overlay.6・overlay.20 |
| 公式アカウント編集: エラーの文言 | status.error-soft |
| メンバー選択: 背景・枠 | overlay.10・overlay.20 |
| メンバー選択・関係性レーダーチャートの選択ボックス: 選択肢の背景・文字 | input.bg・input.text |
| 関係性マップ: ミニマップの枠・外側の覆い | overlay.12・scrim.55 |
| 関係性マップ: 世代以外の軸のグループの箱(背景・枠) | overlay.5・overlay.18 |
| 関係性レーダーチャート: グループの色 | radar-group.1〜radar-group.8 |
| チャート(Genius・ディスコグラフィー・平均年齢): 格子線 | overlay.10 |
| チャート: ツールチップ(背景・枠) | chart.tooltip-bg・overlay.15 |
| Genius の取得進捗チャート: 取得済み・未取得の棒 | sync-status.genius・overlay.20 |
| ディスコグラフィーの取得進捗チャート: 取得済み・未取得の棒 | sync-status.discography・overlay.20 |
| 活動期間チャート: リーダーの印 | event-type.leader |
| 世代マトリクス: 本人の誕生・子の誕生・バンド | generation-matrix.self-birth・generation-matrix.child-birth・generation-matrix.band |
| 世代マトリクス: 年代(未就学・小学・中学・高校) | generation-matrix.stage-preschool・generation-matrix.stage-elementary・generation-matrix.stage-junior-high・generation-matrix.stage-high-school |
地図: 会場の円(VenueMap) |
var(--primary-color)(代替値を外す) |
| 地図: 都道府県のマーカー(背景・文字) | map-marker.bg・white |
| ライブの地方別・都道府県別の一覧: 主色の背景の上の文字 | white |
| 同期状況: 成功・エラーの件数、セッションの有効・失効の文字 | status.success・status.error |
| 同期状況: Instagram・TikTok の取得率の数字と棒 | status.success |
| 同期状況: 取得率の棒の背景 | overlay.10 |
| 同期状況: 見出しのラベル(近況同期・Genius リンク同期・ディスコグラフィー同期) | sync-status.status・sync-status.genius・sync-status.discography |
| 同期状況: Genius・ディスコグラフィーの数字と棒 | sync-status.genius・sync-status.discography |
| ページの見出しのラベル(所属メンバー・出演メンバー・関連メンバー) | section-label.member |
| ページの見出しのラベル(関連リリース・収録ライブアルバム) | section-label.release |
| ページの見出しのラベル(同一会場の公演) | section-label.venue |
| 曲・ユニット・ソロ・リリース・ラジオ放送回のページ: 主色の背景の上のバッジの文字 | white |
| 曲の詳細: 「YouTube Music で聴く」ボタンの背景 | youtube.brand |
| リリース詳細: トラックの YouTube の再生記号 | youtube.brand |
| リリースのバッジ(背景・文字) | release-badge.*・white |
| トップ: 日付の下の階層を示す左の縦線 | today-card.accent |
各ページの Instagram・TikTok・YouTube の見出しのラベル・リンク・件数の文字(constants/colors.ts の INSTAGRAM_COLOR・TIKTOK_COLOR・YOUTUBE_COLOR) |
instagram.brand・tiktok.brand・youtube.brand |
新着投稿: 公式・現役・OG のブロックの見出し(constants/colors.ts の NEW_POSTS_BLOCK_COLORS) |
new-posts-block.official・new-posts-block.active・new-posts-block.og |
| Ameba 一覧: 見出しとリンクの色 | ameba.brand |
備考: 曲の詳細の「YouTube Music で聴く」ボタンの背景は、Spotify の緑(#1DB954)で作られていた。ボタンの対象に合わせて、YouTube のブランドの色(youtube.brand)を使う。
変数の代替値の扱い
var(--x, 色) の代替値に色が書かれている場合は、変数が定義されているかで扱いを決める。
| 変数の状態 | 例 | 扱い |
|---|---|---|
:root で定義済みで、代替値が使われない |
--primary-color・--bg-darker |
代替値を外し、var(--primary-color) とだけ書く |
| 未定義で、代替値が常に効いている | --text-primary(#fff) |
効いている色のトークンにする(overlay.100) |
| 未定義で、代替値が他の指定と食い違っている | --primary-rgb(紫) |
他の指定にそろえる。フィルタチップの選択中の背景は、color-mix(in srgb, var(--primary-color) 12%, transparent) で主色(赤)から作る |
備考: フィルタチップの選択中の背景は、未定義の --primary-rgb の代替値(紫 139, 92, 246)が常に効き、文字と枠の赤と合っていなかった。主色から作る方式にして、同じ色合いにそろえる。
トークンにしない色
次の色は、トークンにしない。
| 色 | 理由 |
|---|---|
メンバーカラー(メンバーデータの color) |
実行時にデータから決まる。16 進数のまま getMemberBadgeStyle などが解析する。ライトで読める色にする方法は、§8-8「メンバーカラー」に定める |
lib/color-utils.ts が解析・計算する色の入出力 |
16 進数として文字列を解析するため、var() を渡せない |
外部リンクのバッジの色(ExternalLinkBadge の LINK_COLOR、9 サービス) |
サービスごとの固定のブランドの色の辞書で、値が 16 進数であることをテストが確かめている |
Instagram の見出しのグラデーション(NewPostsSection) |
ブランドの固定のグラデーションで、複数の色を 1 つの値として渡している |
世代の色(constants/colors.ts の GENERATION_COLORS)と、メンバーカラーがないときの代替の色(#94a3b8・#888888) |
メンバーカラーと同じ経路で使われ、16 進数のまま hexToRgba() や getMemberBadgeStyle が解析する |
関係性マップのスコアの色の補間(member-map-utils.ts の SCORE_COLOR_LOW・SCORE_COLOR_HIGH) |
数値の組から計算して 16 進数を作る |
ラジオ番組のバッジの色(radio-helpers.ts の badgeColor、4 件) |
番組ごとの固定のブランドの色 |
「React Flow」の帰属リンクの色(@xyflow/react が出力) |
ライブラリが固定の色(#999999)で出す。色の指定をこちらで持たない |
SVG の fill・stroke 属性の色にも、var() と color-mix() を入れる(Chromium で描画を確認済み。Firefox・Safari は未確認)。グラフ描画の色のうち、var() を指定すると描画されない色は、理由を添えてこの表に載せる。
CSS Modules の色
CSS Modules の色は、var(--colors-<トークン名>) で参照する。CSS Modules はレイヤー外の CSS のまま、値だけが変数の参照になるため、スタイルの優先度は変わらない(開発ノート「実装」知見 144・147)。対応するトークンがない色は、トークンを追加する。追加するトークンにもダークの値を定義する。
8-4. 補足: 活用方針の検討経緯(案A〜D)
MorningStatusApp#1745 の検討結果。判断軸は、①ダーク/ライトモードの実現しやすさ、②色の一元管理による保守性。2026-10-22 時点の実測(main)に基づく。
| 案 | 内容 | 採否と理由 |
|---|---|---|
| A | バージョン更新のみ(現状維持) | 採用しない。色の一元管理が進まない |
| B | 配色を semantic tokens にする | 採用。§8-1〜8-2 |
| C | インライン style を css() や patterns へ段階的に移す |
配色の移行とは切り離す。ホバー(:hover 36)とメディアクエリ(@media 9)はすべて CSS ファイルに書かれ、インライン style(1189 箇所)は条件を必要としていない |
| D | 繰り返しのカード・チップをレシピにする | B の後に再評価する。候補はカテゴリ色分け辞書 4 つと .glass(82 行) |
8-5. 補足: 別名方式の検証結果
Panda CSS 2.3.0 とブラウザ(Chromium、Playwright)で検証した。
| 確認した内容 | 結果 |
|---|---|
| Panda が出す変数名 | トークン名の . を - に置き換えた --colors-<名前>(例: --colors-text-muted)。既存の変数名とは重ならない |
| 出力先 | @layer tokens。ダークの値は :root、ライトの値は .light の中 |
| 別名の解決 | <html> のクラスの切り替え(なし・dark・light)に追従して値が切り替わる。--text-muted を使う文字色も同じく切り替わる |
| ダークの値の要否 | クラスごとの値だけを定義したトークンは、クラスなしの状態で値が定義されない。クラスなしの状態でも決まる、ダークの値の定義が必要 |
8-6. テーマ切替の仕組み
ダーク/ライトの切り替えは、<html> のクラスと CSS 変数だけを前提にする。CSS エンジン(Panda CSS・Tailwind CSS など)の API には依存しない。
境界
切り替えの仕組みと CSS エンジンの境界は、次の 3 つ。
| 境界 | 内容 |
|---|---|
<html> のクラス |
dark または light。ダークの値は :root に、ライトの値は .light に出力される |
| 色の CSS 変数 | 画面の部品は、色を var(--colors-…) の参照だけで指定する |
color-scheme |
<html> に color-scheme: dark または color-scheme: light を付ける。入力欄・スクロールバーなど、ブラウザ標準の部品の色が、エンジンと無関係に追従する |
切替ボタン・先頭スクリプト・localStorage の保存は、この 3 つだけを前提にする。Panda CSS の生成物(styled-system)は、これらから import しない。
エンジンを替えるときに移すのは、.dark・.light の下に色の変数を出す部分(panda.config.ts のトークン定義)である。変数名 --colors-* は Panda CSS の命名規則で、Tailwind CSS v4 は --color-* を使う。エンジンを替えるときは、変数名の移行が要る。
選択肢と保存
- 選択肢は「システム」「ダーク」「ライト」の 3 つ。初期値は「システム」
- 選択は
localStorageのキーthemeに、system・dark・lightのいずれかで保存する。保存された値がないとき、または 3 つ以外の値のときは「システム」とする - 「システム」のときは、
matchMedia('(prefers-color-scheme: dark)')の結果でdarkとlightのどちらかを決め、<html>に付ける。OS の設定が変わったときも、同じmatchMediaの変更イベントで付け替える
初回描画の前の適用
<head> の先頭に、同期で実行するインラインスクリプトを置く。スクリプトは、<body> の描画より前に、保存された選択から <html> のクラスと color-scheme を決める。ダークの値が :root(クラスなしの状態)に出力されるため、クラスが付く前はダークで描画される。スクリプトを描画より前に実行することで、ライトの利用者にダークの表示が一瞬出ることを防ぐ。
先頭スクリプトと切替ボタンの担当
- 先頭スクリプト: 初回描画の前に、保存された選択から
<html>のクラスとcolor-schemeを決める。「システム」のときは、OS の設定の変更をmatchMediaの変更イベントで監視し、クラスを付け替える - 切替ボタン: 選択が変わったときに、
localStorageへ保存し、<html>のクラスとcolor-schemeを更新する - 両者は、保存のキー(
theme)と、選択からクラスへの対応(systemはmatchMediaの結果、darkとlightはそのまま)に、同じ決まりを使う
8-7. グローバルヘッダーの配置
全画面共通のグローバルヘッダー(app/layout.tsx)は、タイトルを左端に置き、右側に 👉(タイムライン)・🔍(曲検索)・テーマの切替ボタンを、一定の間隔(gap)で並べる。
- 右側の並びは、👉・🔍・切替ボタンの順。切替ボタンが右端
- 切替ボタンは、押すたびに「システム → ダーク → ライト → システム」の順に巡回する。現在の選択を表すアイコン(システムは 🖥️、ダークは 🌙、ライトは ☀️)を表示し、
aria-labelで現在の選択(例: 「テーマ: システム」)を伝える - 各アイコンのタップ領域は、44px 前後にする
- 画面幅 320px 以上で、タイトルは全文が表示され、アイコンと重ならない。タイトルの文字サイズは、画面幅に合わせて 0.9rem〜1.25rem(md 以上は 1.5rem)にし、それでも収まらない幅では、末尾を省略記号にする
- 切替ボタンは、移動ではなく設定のため、ページ間の移動の
<nav>(aria-labelは「ページ移動」)の外に置く
8-8. ライトの配色
ライトの値は、トークンごとに、ダークの値とは別に定義する。ダークと同じ値のトークンには、ライトの値を定義しない。
区分
背景を持つトークンと、その上に載る文字・線のトークンは、同じ区分で定義する。overlay.* は、ライトでは暗い色の透過になるため、暗い色の背景の上では読めなくなるためである。
| 区分 | 対象 |
|---|---|
| 基本 | 画面の背景・面・文字・枠線・オーバーレイ、関係性マップの背景、チャートのツールチップ。切り替えると画面全体の印象が変わる色 |
| 残り | カテゴリ色分け辞書、状態・ブランド・関係性の色、レーダーチャート、世代マトリクスなど、用途ごとの色 |
| ダークと同じ値 | white、scrim.*、secondary、card.glow、primary-glow、input.*、edge-label.*、badge.active.*、background、release-badge.*、map-marker.bg、ほか透過の背景・枠線(「残りのトークンのライトの値」の末尾の一覧) |
基本トークンのライトの値
overlay.* のライトの値は、純黒ではなく、text.main のライトの値と同じ色相(#0f172a、slate-900)の透過にする。
| トークン | ダーク | ライト |
|---|---|---|
surface |
#0f172a |
#f8fafc |
surface-deep |
#020617 |
#e2e8f0 |
text.main |
#f8fafc |
#0f172a |
text.muted |
#94a3b8 |
#475569 |
overlay.4 5 6 7 8 10 12 14 15 18 20 25 30 |
rgba(255, 255, 255, <数値>%) |
rgba(15, 23, 42, <数値>%) |
overlay.35 40 45 50 55 60 65 70 75 80 85 90 95 |
rgba(255, 255, 255, <数値>%) |
rgba(15, 23, 42, <ライトの透明度>%)(下の表) |
overlay.100 |
rgba(255, 255, 255, 1) |
#0f172a |
card.bg |
rgba(255, 255, 255, 0.03) |
rgba(15, 23, 42, 0.03) |
card.border |
rgba(255, 255, 255, 0.1) |
rgba(15, 23, 42, 0.1) |
card.text-art-bg |
rgba(255, 255, 255, 0.05) |
rgba(15, 23, 42, 0.05) |
relationship.surface |
#0f0f0f |
#f8fafc |
relationship.surface-raised |
#1e1e2e |
#ffffff |
relationship.surface-raised-hover |
#2a2a3e |
#f1f5f9 |
chart.tooltip-bg |
rgba(20, 20, 40, 0.9) |
rgba(255, 255, 255, 0.95) |
overlay.35〜95 のライトの透明度(%)は、次のとおり。
| 段階 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ライトの透明度(%) | 62 | 64 | 66 | 68 | 70 | 72 | 75 | 79 | 83 | 86 | 89 | 93 | 96 |
overlay.* は、塗りや線のほかに、文字にも使う。白の透過(ダーク)と暗色の透過(ライト)は、同じ透明度でも文字のコントラストが対称にならない(透明度 45% の文字は、ダークが約 4.5:1、ライトが約 2.9:1 になる。相対輝度からの概算)。そのため、文字にも使う 35〜95 の段階は、ライトの透明度を引き上げる。body の背景は、surface から surface-deep へのグラデーションのため、下限は両端の背景の上で決める。下限の 62% は、surface のライト(#f8fafc)と surface-deep のライト(#e2e8f0)のどちらの上でも、4.5:1 以上(概算)になる。4〜30 の段階は、塗りと線に使うため、ダークと同じ透明度にする。
コントラストは、通常のテキストで 4.5:1 以上を目安にする。text.muted と overlay.* の文字は、画面ごとに確認し、必要なら調整する。
残りのトークンのライトの値
残りのトークンのライトの値は、次の基準で決める。
| 種類 | 基準 | 値の決め方 |
|---|---|---|
| 文字の色 | surface のライト(#f8fafc)、surface-deep のライト(#e2e8f0)、surface-deep のライトの上に overlay.4 のライトを重ねたカードの背景(#dae0e8)の 3 つの上で、4.5:1 以上 |
ダークと同じ色相の Tailwind CSS のシェード(500〜900)から、基準を満たす最も明るいもの |
| チップの色(同じ色の薄い背景を重ねる) | 上の 3 つの背景と、surface と surface-deep のライトの上に、同じ色の 18% を重ねた背景の上で、4.5:1 以上 |
同上 |
| 図・塗りの色 | surface と surface-deep のライトの上で、3:1 以上 |
同上 |
| 暗い面に白を重ねていた透過の色 | ライトの背景の上で読み取れる | rgba(15, 23, 42, <透明度>) に反転する(overlay.* と同じ基調色) |
| ブランドの固定色 | 文字に使う色は、文字の色の基準 | 基準を満たすよう、ブランドの色相の濃い色にする。youtube.brand は、白い文字の背景にも使うため、白の上で 4.5:1 以上も満たす |
主色(primary) |
リンクの文字色と、ボタンの背景の両方に使うため、文字の色の基準と、白い文字の背景の基準(白の上で 4.5:1 以上)の両方 | 主色の赤(#e60012)の、濃い赤 |
| 上のどれにも当たらないもの | — | ダークと同じ値(末尾の一覧) |
文字の色とチップの色は、ダークの -400 前後のシェードを、白い背景で読める濃さまで暗くするため、ダークより濃い色(-600〜-900)になる。チップの薄い背景は、tintBackground() の 13.33% と、イベントカードの文字だけのカードのラベルの約 18% を含めるため、18% で確かめる。
カテゴリ色分け辞書
| トークン | ダーク | ライト |
|---|---|---|
event-type.live |
#a78bfa |
#5b21b6 |
event-type.festival |
#fb923c |
#7c2d12 |
event-type.topic |
#94a3b8 |
#475569 |
event-type.media |
#38bdf8 |
#075985 |
event-type.join |
#4ade80 |
#14532d |
event-type.graduate |
#f87171 |
#991b1b |
event-type.leader |
#ffd700 |
#713f12 |
radio-show.morning-gakuin |
#fb923c |
#7c2d12 |
radio-show.youngtown-saturday |
#38bdf8 |
#075985 |
radio-show.may-bonsoir |
#a78bfa |
#5b21b6 |
radio-show.harusanchi |
#34d399 |
#065f46 |
release-format.single |
#f472b6 |
#9d174d |
release-format.album |
#60a5fa |
#1e40af |
release-format.ep |
#a78bfa |
#5b21b6 |
release-format.live |
#34d399 |
#065f46 |
release-format.soundtrack |
#fbbf24 |
#78350f |
release-format.compilation |
#fb923c |
#7c2d12 |
release-format.other |
#94a3b8 |
#475569 |
tag-chip.birthday |
#f472b6 |
#9d174d |
tag-chip.solo |
#60a5fa |
#1e40af |
tag-chip.unit |
#a78bfa |
#5b21b6 |
tag-chip.og |
#fb923c |
#7c2d12 |
tag-chip.special |
#fbbf24 |
#78350f |
tag-chip.collaboration |
#34d399 |
#065f46 |
category.fallback |
#94a3b8 |
#475569 |
状態・結果・ブランドの色
| トークン | ダーク | ライト |
|---|---|---|
status.success |
#4ade80 |
#166534 |
status.error |
#f87171 |
#b91c1c |
status.warning |
#fbbf24 |
#92400e |
status.error-soft |
#fca5a5 |
#b91c1c |
feedback.success |
#27ae60 |
#166534 |
feedback.error |
#c0392b |
#b91c1c |
live-tour.join-text |
#34d399 |
#065f46 |
live-tour.graduate-text |
#fbbf24 |
#92400e |
live-tour.birthday-text |
#f472b6 |
#9d174d |
leader-period.text |
#fbbf24 |
#854d0e |
leader-badge.text |
#b8860b |
#854d0e |
instagram.brand |
#e1306c |
#be185d |
youtube.brand |
#ff0000 |
#b91c1c |
ameba.brand |
#2dad21 |
#166534 |
tiktok.brand |
#69c9d0 |
#155e75 |
primary |
#e60012 |
#b91c1c |
年表・見出し・同期状況・新着投稿の色
| トークン | ダーク | ライト |
|---|---|---|
timeline-type.join |
#4ade80 |
#166534 |
timeline-type.graduate |
#f87171 |
#b91c1c |
timeline-type.release |
#60a5fa |
#1d4ed8 |
timeline-type.live |
#fbbf24 |
#92400e |
timeline-type.festival |
#f472b6 |
#be185d |
timeline-type.media |
#94a3b8 |
#475569 |
timeline-type.leader |
#ffd700 |
#854d0e |
timeline-type.topic |
#94a3b8 |
#475569 |
section-label.member |
#60a5fa |
#1d4ed8 |
section-label.release |
#fb923c |
#9a3412 |
section-label.venue |
#94a3b8 |
#475569 |
sync-status.status |
#60a5fa |
#1d4ed8 |
sync-status.genius |
#a78bfa |
#6d28d9 |
sync-status.discography |
#4ade80 |
#166534 |
new-posts-block.official |
#38bdf8 |
#075985 |
new-posts-block.active |
#34d399 |
#065f46 |
new-posts-block.og |
#fb923c |
#9a3412 |
today-card.bg |
rgba(242, 247, 251, 0.06) |
rgba(15, 23, 42, 0.04) |
today-card.icon |
#8aa3c2 |
#475569 |
venue-map-link.text |
rgba(180, 220, 255, 0.7) |
#1d4ed8 |
venue-map-link.text-hover |
rgba(180, 220, 255, 1) |
#1e3a8a |
世代マトリクス・レーダーチャートの色
| トークン | ダーク | ライト |
|---|---|---|
generation-matrix.line |
rgba(248, 250, 252, 0.3) |
rgba(15, 23, 42, 0.3) |
generation-matrix.line-active |
rgba(248, 250, 252, 0.7) |
rgba(15, 23, 42, 0.7) |
generation-matrix.self-birth |
#38bdf8 |
#0284c7 |
generation-matrix.child-birth |
#f472b6 |
#db2777 |
generation-matrix.band |
#a78bfa |
#8b5cf6 |
generation-matrix.stage-preschool |
#34d399 |
#059669 |
generation-matrix.stage-elementary |
#22d3ee |
#0e7490 |
generation-matrix.stage-junior-high |
#facc15 |
#a16207 |
generation-matrix.stage-high-school |
#fb923c |
#c2410c |
radar-group.1 |
#f97316 |
#c2410c |
radar-group.2 |
#60a5fa |
#2563eb |
radar-group.3 |
#4ade80 |
#15803d |
radar-group.4 |
#f472b6 |
#db2777 |
radar-group.5 |
#c084fc |
#a855f7 |
radar-group.6 |
#38bdf8 |
#0284c7 |
radar-group.7 |
#facc15 |
#a16207 |
radar-group.8 |
#fb7185 |
#e11d48 |
メンバー関係性マップ・レーダーチャートの色
| トークン | ダーク | ライト | 理由 |
|---|---|---|---|
relationship.accent |
#f97316 |
#9a3412 |
橙のボタンの背景と、順位が変わったメンバーの名前の文字の両方に使う。白い文字の上でも、surface-deep の上でも、4.5:1 以上 |
relationship.accent-soft |
#fb923c |
#7c2d12 |
橙のボタンのホバー時の背景。relationship.accent より濃くする |
relationship.on-accent |
#0f0f0f |
#ffffff |
橙の背景の上の文字。ライトの relationship.accent が濃いため、白にする |
relationship.danger |
rgba(255, 100, 100, 0.9) |
#b91c1c |
エラー文言・削除操作のホバー時の文字 |
relationship.danger-soft |
#fca5a5 |
#b91c1c |
警告帯の文字 |
relationship.info |
rgba(180, 220, 255, 0.8) |
#1d4ed8 |
参加メンバー数バッジの文字 |
メンバーカラー
メンバーカラー(§8-3 でトークンにしない色)は、データから決まる色のため、値の表を持たない。文字の色や背景の色に使う箇所は、次のとおり、ライトで読める色にする。
| 使い方 | ダーク | ライト |
|---|---|---|
| 文字の色(世代バッジ・メンバータグなど。同じメンバーカラーの薄い背景や枠線と組み合わせる) | メンバーカラーのまま | メンバーカラーの色相と彩度を保ち、明度だけを下げて、基準を満たす最も明るい色にする |
| メンバーカラーの背景の上の文字(メンバー関係性マップのカードの名前・期のラベル) | 白と黒(#000000)のうち、メンバーカラーの背景の上でコントラストが高い方 |
同左 |
- ライトの文字の色の基準は、チップの色(上の表)と同じ。
surfaceのライト・surface-deepのライト・カードの背景(#dae0e8)の 3 つの上と、それぞれの上に同じメンバーカラーの 13.33%・18% を重ねた背景の上で、4.5:1 以上 - カードの文字色は、白と黒のうち高い方を選ぶ。メンバーカラーがどの明るさでも、最悪で約 4.58:1(相対輝度からの概算)になり、4.5:1 以上を満たす。名前と期のラベルは、不透明な色で描く。卒業メンバー(OG)のカードは、
opacity: 0.65で下地に透けるため、実効の比を「既知の基準未達」に定める - メンバーカラーを背景にする箇所は、ダークとライトで背景の色が変わらないため、文字色の選び方もダークとライトで同じ
ダークと同じ値のトークン(残り)
次のトークンは、ライトでも、ダークと同じ値を使い、ライトの値を定義しない。ブランドの固定色の薄い背景・白い文字の背景・半透明の背景や枠線で、ライトの背景の上でも読み取れる、または、白い文字との組み合わせで使うため。
- 状態・結果:
status.success-bg、status.neutral-bg、status.error-bg、status.warning-bg、status.error-solid、status.error-border、live-tour.join-bg、live-tour.graduate-bg、live-tour.birthday-bg、leader-badge.bg、leader-period.border、leader-period.bg、tiktok.brand-bg - 画面の装飾:
primary-glow、today-card.border、today-card.accent、map-marker.bg、release-badge.single・album・ep・live・soundtrack・compilation・other - 関係性:
relationship.accent-bg、relationship.accent-border、relationship.selected-bg、relationship.selected-border、relationship.danger-border、relationship.info-bg、edge-label.bg、edge-label.text
リリースのバッジの背景(release-badge.*)は、白い文字の背景のため、ダーク・ライトとも、白の上で 4.5:1 以上になる色にする。
既知の基準未達
2026-11-06 の実測(MorningStatusApp#1805)で、基準の 4.5:1 に届いていない箇所。測り方は、開発ノートの「テスト手法」知見 64・65 に従う。
| 箇所 | 実測 | 内容 |
|---|---|---|
| ダークの世代バッジ・メンバータグの文字(メンバーカラーのまま) | #e0115f が 4.04:1、#4169e1 が 3.96:1(#0a0e1e の上) |
「メンバーカラー」のライトの基準を、ダークには適用していない |
ダークの主色(primary)のリンクの文字 |
#e60012 が 4.0:1(#0a0e1e の上)、4.2:1(#020617 の上) |
主色は、ダークでは、ブランドの赤のまま |
| 「React Flow」の帰属リンク | ライトが 2.79:1(#999999 の文字、#fcfdfe の上)、ダークが 1.25:1(#999999 の文字、#878787 の上) |
ライブラリが固定の色で出す(§8-3) |
世代バッジ(opacity: 0.8)の実効の比 |
ライトで 3.36〜3.76:1(#176788・#21623e・#8a4c00 など) |
文字と背景を、opacity で下地に重ねた実効の値。重ねる前の比は、すべて 4.5:1 以上 |
メンバー関係性マップの卒業メンバー(OG)のカード(opacity: 0.65)の文字の実効の比 |
ライトで最小 2.28:1(#000000 の文字、#ff0000 の背景、#f8fafc の下地)、ダークで最小 2.67:1(同じ文字と背景、#0f0f0f の下地)。OG の 40 枚のうち、ライトで 17 枚、ダークで 13 枚が未達 |
文字と背景を、opacity で下地に重ねた実効の値。重ねる前の比は、すべて 4.5:1 以上(最小 4.76:1)。文字の色は、重ねる前の背景で、白と黒のうち高い方を選んでいる |
トークンにしない色(§8-3)は、ライトでも 16 進数のまま使う。
改訂履歴(バージョン降順に記載)
| 版 | 更新日 | 変更内容 |
|---|---|---|
| 2.4 | 2026-11-06 | 【v12.0.1(MorningStatusApp#1805)】§8-8の「既知の基準未達」に、メンバー関係性マップの卒業メンバー(OG)のカード(opacity: 0.65)の文字の実効の比を追加。§8-8「メンバーカラー」に、OG のカードの実効の比は「既知の基準未達」に定めることを追加 |
| 2.3 | 2026-11-06 | 【v12.0.1(MorningStatusApp#1805)】§8-8に、メンバーカラーを文字の色・背景の色に使う箇所のライトの色(文字の色の補正、メンバー関係性マップのカードの文字色の選び方)を追加。リリースのバッジの背景(release-badge.album・live・soundtrack・compilation)を、白い文字が 4.5:1 以上になる色に変更。トークンの値の列と説明を「ダーク」「ライト」の表記に統一。§8-8に、既知の基準未達(ダークのメンバーカラーの文字・主色のリンク・React Flow の帰属リンク・世代バッジの opacity)を追加。§8-3の「トークンにしない色」に、React Flow の帰属リンクを追加 |
| 2.2 | 2026-11-04 | 【v12.0.0(MorningStatusApp#1801)】§8-8に、残りのトークン(カテゴリ色分け辞書・状態・結果・ブランド・年表・見出し・同期状況・新着投稿・世代マトリクス・レーダーチャート・関係性マップ)のライトの値と、値を決める基準(文字の色・チップの色・図の色)を追加。主色(primary)のライトの値も追加 |
| 2.1 | 2026-11-04 | 【v12.0.0(MorningStatusApp#1800)】§8-8で、文字にも使う overlay.35〜95 のライトの透明度を 62%〜96% に引き上げ、surface と surface-deep の両方の上で 4.5:1 以上に。§8-7で、ヘッダーのタイトルの表示(画面幅に合わせた文字サイズ・省略記号)と、切替ボタンを <nav> の外に置くことを追加(MorningStatusApp#1802) |
| 2.0 | 2026-11-03 | 【v12.0.0(MorningStatusApp#1800)】§8-6〜8-8として、ダーク/ライトの切替の仕組み(<html> のクラス・color-scheme・CSS エンジンに依存しない境界・選択肢と保存・初回描画の前の適用)、グローバルヘッダーの切替ボタンの配置、基本トークンのライトの値と区分(文字にも使う overlay.* の段階は、ライトの透明度を引き上げる)を追加。§8-1・§8-3 の切り替え方式の記述を確定(MorningStatusApp#1735、morning-status-blume#240) |
| 1.12 | 2026-11-02 | 【v11.10.1(MorningStatusApp#1790)】§8-3に、画面ページ・編集画面・グラフ・地図・選択部品の色のトークン(34個)と、画面の部品ごとの色の対応表を追加。背景の透明色に、用途ごとの不透明度(withOpacity()、年表の枠 30%・節目の背景 15%)を追加し、部品の表に、半透明の背景の上の文字は overlay.100 の行を追加。トークンにしない色に、世代の色と代替の色・スコアの補間・番組バッジの色を追加。ブランドの色の定数と新着投稿のブロックの色(constants/colors.ts)も、対象に含めた。編集画面の削除ボタンの背景・選択肢の文字・公式アカウント編集の保存ボタンの文字・Ameba 一覧の色・YouTube Music のボタンの背景を、トークンの色にそろえた(morning-status-blume#234) |
| 1.11 | 2026-11-02 | §8 の書き方を整理(内容は変えない)。「現行の色を置く」「そろえる」「置き換える」などの時制・差分の言い方と、実装の進み具合に依存する件数を、目標の設計をそのまま書く形に改めた。§8-3 の表題を「ライトモードの要件」に改めた |
| 1.10 | 2026-11-02 | 【v11.10.1(MorningStatusApp#1789)】§8-3に、カード・バッジ・詳細表示の色のトークン(20個)と、画面の部品ごとの色の対応表を追加。共通の段階に scrim.55 を追加し、トークンにしない色に外部リンクのバッジの色と Instagram のグラデーションを追加。メンバー詳細の状態バッジと保存エラーの帯の背景を status.* の濃さ(0.2)に、Instagram・TikTok のカードのラベルの色をブランドの色にそろえた(morning-status-blume#234) |
| 1.9 | 2026-11-01 | 【v11.10.1(MorningStatusApp#1788)】§8-3に、その他の画面(リンク編集・メンバーカード・ライブのツアー表示・イベントカードほか)の色のトークン(26個)と、画面の部品ごとの色の対応表を追加。共通の段階に overlay.5・overlay.7・overlay.30 を追加し、変数の代替値の扱いを追加。フィルタチップの選択中の背景を、主色(赤)の 12% に改めた(morning-status-blume#234) |
| 1.8 | 2026-11-01 | 【v11.10.1(MorningStatusApp#1787)】§8-3の関係性マップ・レーダーチャート用トークンの接頭辞を map から relationship に改称(map は地図と紛らわしいため)。white の役割を「色付きの背景の上の、固定の白の文字」に整理し、overlay.100 を追加(morning-status-blume#234) |
| 1.7 | 2026-10-31 | 【v11.10.1(MorningStatusApp#1787)】§8-3に、メンバー関係性マップ・レーダーチャートの色のトークン(白の透過・黒の透過・関係性マップ・レーダーチャート用の面・橙・藍・警告・情報・関係線のラベル)と、画面の部品ごとの色の対応表を追加(morning-status-blume#234) |
| 1.6 | 2026-10-31 | 【v11.10.1(MorningStatusApp#1774)】§8-3に、カテゴリ色分け辞書のトークン(25個)、背景の透明色の作り方、トークンにしない色、CSS Modulesの色の置き換え方針を追加(morning-status-blume#234) |
| 1.5 | 2026-10-22 | 【v11.8.1(MorningStatusApp#1773)】§8として配色トークンの設計と、活用方針の検討経緯・別名方式の検証結果を追加(MorningStatusApp#1745、morning-status-blume#223) |
| 1.4 | 2026-10-22 | 【v11.8.0(MorningStatusApp#1672)】§2にプリセットの明示を追加、§4の fold の単位を rem に変更。Panda CSS v2への更新に伴う |
| 1.3 | 2026-09-26 | §7としてライブ一覧・Amebaブログ一覧の新規カードグリッド設計(.glassカード化・固定2列パターン)を追加(#1666) |
| 1.2 | 2026-09-25 | §3-3を更新し、app/globals.cssの* {...}リセットを@layer resetへ移すことで.app-containerのPanda globalCss移行が完了したことを反映。§5の.app-containerに関する記述もあわせて更新(#1667) |
| 1.1 | 2026-09-25 | §5の「223ファイル中25ファイル」記載を実態(1ファイル)に訂正し、§6として一覧画面のレスポンシブグリッド実装パターン(対象画面・css()パターン)を追加。新規UI設計が必要な画面を#1666、.app-containerのPanda化検討を#1667として切り出したことを反映(#1656) |
| 1.0 | 2026-09-25 | 新規作成(#1655) |