@cakejp/design-system 0.21.1 → 0.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/CLAUDE.md +2 -0
- package/UPDATING.md +2 -0
- package/bin/check-tokens.mjs +116 -0
- package/bin/init.js +9 -0
- package/contracts/components.json +3 -3
- package/contracts/composition.json +4 -4
- package/contracts/rules.json +1 -1
- package/contracts/screen-patterns.json +1 -1
- package/dist/components/ec/anniversary-card.js +24 -24
- package/dist/components/foundations/button.js +6 -6
- package/dist/components/foundations/chip-variants.js +1 -1
- package/dist/components/foundations/pagination.js +1 -2
- package/dist/components/foundations/radio-group.js +3 -3
- package/dist/components/foundations/toggle-group.js +10 -10
- package/dist/components/primitives/tag.js +1 -1
- package/dist/index.css +1 -1
- package/dist/index.js +16 -17
- package/package.json +1 -1
- package/src/preset-standalone.css +34 -34
- package/src/styles/primitive.css +1 -1
- package/src/styles/semantic.css +31 -29
- package/tokens.json +35 -35
package/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
+
## [0.22.1] - 2026-10-26
|
|
15
|
+
|
|
16
|
+
### ✨ Added
|
|
17
|
+
|
|
18
|
+
- **`npx cakejp-ds check-tokens [DIR]`**: consumer の色が「DS を上げるだけで変わる」状態かを検査する CLI。v0.22.0 のブランドカラー変更で、DS を上げてもオレンジのまま残った原因 4 つを検出し、検出時 exit 1 にする
|
|
19
|
+
- `brand-hex`: ブランド色の値の直書き(`#` / SVG data URL の `%23` / `rgb()`)。色の一覧は `src/styles/primitive.css` の `--Primitive-Orange-*` / `--Primitive-Berry-*` から毎回読むので、DS 側でパレットを変えても検査の更新は要らない
|
|
20
|
+
- `brand-override`: DS のブランド系トークン(`--Brand-*` / `--*-Accent-*` / Primary・Secondary ボタンの hover 等)の上書き
|
|
21
|
+
- `undefined-token`: DS にもプロジェクトにも無い変数の参照(`var(--X, #ffecd9)` のフォールバックが出続ける)
|
|
22
|
+
- `brand-primitive`: `--Primitive-Orange-*` / `--Primitive-Berry-*` の直接参照
|
|
23
|
+
- 例外は同じ行か直前の行に `design-tokens-allow: <理由>`(理由必須)。テスト・docs・ビルド成果物・node_modules は走査しない
|
|
24
|
+
- 原材料・人材・ケーキ屋さん.jp に個別に入れていた同等のスクリプトを置き換える想定
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## [0.22.0] - 2026-10-26
|
|
29
|
+
|
|
30
|
+
### 🎨 Changed
|
|
31
|
+
|
|
32
|
+
- **ブランドカラーをオレンジ(`#E04B00`)からベリー(`#E5175C`)へ変更**: `--Brand-Cake-Orange` 系・`--Surface/Text/Object/Border-Accent-Primary` 系・Primary/Secondary ボタンの hover/active など、ブランド色を参照する semantic トークンを `--Primitive-Berry-*` 参照に切り替えた(light/dark、`preset-standalone.css`、`tokens.json`)
|
|
33
|
+
- 変数名(`--Brand-Cake-Orange` など)は据え置き。利用側のコード変更は不要で、バージョンを上げると色が変わる
|
|
34
|
+
- 旧カラー(オレンジ)は `--Primitive-Orange-*` に元の値のまま残している。`bg-orange-*` などの Tailwind ユーティリティもオレンジのまま
|
|
35
|
+
- accent-primary の文字・地のコントラストが 4.5:1 を満たすようになったため、コントラスト検査の例外 3 件を削除
|
|
36
|
+
- 薄いアクセント地(`--Surface-Accent-Primary-Light`)の上の文字を `--Brand-Cake-Orange` から `--Text-Accent-Primary` に変更(Button `secondary`・Pagination の選択中・Chip / Tag の accent・RadioGroup の chip・ToggleGroup・AnniversaryCard)。light は Berry-800(薄地で 4.81:1・白地で 6.48:1)、dark は Berry-600(4.61:1)。`--Text-Accent-Primary` を使う価格などの文字も light では一段濃い赤になる。コントラスト検査の例外は不要になり削除
|
|
37
|
+
|
|
38
|
+
### 🐛 Fixed
|
|
39
|
+
|
|
40
|
+
- **Button `secondary` の hover / active の線が太すぎた**([#300](https://github.com/flashpark/cake-design-system/issues/300)): 1px の枠線と 2px の outline が同色で重なり約 3px に見えていた。hover / active は 1px の枠線の色替えだけにした(Pagination の選択中も同じ)。フォーカス表示は従来どおり共通のリング
|
|
41
|
+
- **PaginationEllipsis の「その他のページ」が読み上げられなかった**([#300](https://github.com/flashpark/cake-design-system/issues/300)): 外側の `aria-hidden` を外し、アイコンだけを読み上げから外した。見た目は変わらない
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
14
45
|
## [0.21.1] - 2026-10-21
|
|
15
46
|
|
|
16
47
|
### 🐛 Fixed
|
package/CLAUDE.md
CHANGED
|
@@ -65,6 +65,8 @@ PdM や社長が AI(Claude 等)で HTML モックを作る際、このパッ
|
|
|
65
65
|
|
|
66
66
|
**意図的にローカル実装を残すとき(check-duplicates の抑制)**: 対象 export の直前のコメント行(または行末コメント)に `// cakejp-ds-allow-duplicate: <理由>` を書くと、その 1 件だけ検出から外れる。**理由が空なら抑制されない**(形骸化防止)。抑制した件数と理由はサマリに出る。
|
|
67
67
|
|
|
68
|
+
**色は DS のトークンで書き、`npx cakejp-ds check-tokens` を lint / build に組み込む。** DS のバージョンを上げても色が追従しない書き方(ブランド色の値の直書き・DS のブランド系トークンの上書き・DS に無い変数の参照・`--Primitive-Orange-*` / `--Primitive-Berry-*` の直接参照)を検出して exit 1 にする(実例: v0.22.0 のブランドカラー変更で、これらが原因で DS を上げてもオレンジのまま残る画面が各プロダクトにあった)。例外は同じ行か直前の行に `design-tokens-allow: <理由>`(理由必須。例: CSS 変数を使えない `themeColor`)。
|
|
69
|
+
|
|
68
70
|
---
|
|
69
71
|
|
|
70
72
|
## 見た目のフィードバックを受けたときのゲート(DS 起因か consumer 起因かを先に切り分ける)
|
package/UPDATING.md
CHANGED
|
@@ -169,6 +169,8 @@ npm run test # あれば
|
|
|
169
169
|
- **マイナー更新では CHANGELOG の「✨ Added」を読み、ローカルに持っている同等実装の削除候補を確認する**。
|
|
170
170
|
DS に新しく追加された部品(例: 0.10.0 の `ImageUploader` / `ResponsiveDialog` / `DataTable`)と同名のローカル実装が残っていないか、`npx cakejp-ds check-duplicates ./src` を流すと機械検出できる(`--strict` で検出時 exit 1)。
|
|
171
171
|
検出されたローカル実装は DS の import に置き換え、不要になったファイルを削除する。
|
|
172
|
+
- **`npx cakejp-ds check-tokens` を流し、DS を上げても色が追従しない箇所が無いか確認する**(ブランド色の直書き・DS のブランド系トークンの上書き・DS に無い変数・ブランド原色の直接参照を検出、検出時 exit 1)。
|
|
173
|
+
lint / build のスクリプトに組み込んでおくと、色の変更が告知されたときに DS を上げるだけで済む。
|
|
172
174
|
|
|
173
175
|
### 5. PR 作成・マージ
|
|
174
176
|
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* npx cakejp-ds check-tokens [DIR]
|
|
4
|
+
*
|
|
5
|
+
* consumer の色が「DS のバージョンを上げるだけで変わる」状態かを検査する。
|
|
6
|
+
* 2026-10 のブランドカラー変更(オレンジ → ベリー、v0.22.0)で、DS を上げても色が変わらない箇所が
|
|
7
|
+
* 各プロダクトに残った。原因は次の 4 つだったので、それぞれを検出して exit 1 にする。
|
|
8
|
+
*
|
|
9
|
+
* brand-hex ブランド色の値の直書き(--Primitive-Orange-* / --Primitive-Berry-* の値。# / %23 / rgb() 表記)
|
|
10
|
+
* brand-override DS のブランド系トークン(--Brand-* / --*-Accent-* / Primary・Secondary ボタンの hover 等)の上書き定義
|
|
11
|
+
* undefined-token DS の命名(大文字始まり)で、DS にも consumer にも定義が無い変数の参照
|
|
12
|
+
* (var(--X, #ffecd9) のフォールバックが表示され続ける)
|
|
13
|
+
* brand-primitive ブランドの原色(--Primitive-Orange-* / --Primitive-Berry-*)の直接参照
|
|
14
|
+
*
|
|
15
|
+
* ブランド色の一覧は、この package の src/styles/primitive.css から毎回読み直す。
|
|
16
|
+
* そのため DS 側でパレットを変えても、この検査の更新は要らない。
|
|
17
|
+
*
|
|
18
|
+
* 例外: 同じ行か直前の行に「design-tokens-allow: <理由>」を書く(理由が空なら例外にならない)。
|
|
19
|
+
*/
|
|
20
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs"
|
|
21
|
+
import { dirname, extname, join, relative, resolve } from "node:path"
|
|
22
|
+
import { fileURLToPath } from "node:url"
|
|
23
|
+
|
|
24
|
+
const pkgRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..")
|
|
25
|
+
const args = process.argv.slice(2)
|
|
26
|
+
|
|
27
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
28
|
+
console.log(`使い方: npx cakejp-ds check-tokens [DIR]
|
|
29
|
+
|
|
30
|
+
DIR(既定: カレントディレクトリ)以下の .css / .scss / .ts / .tsx / .js / .jsx / .mjs を走査し、
|
|
31
|
+
DS のバージョンを上げても色が追従しない書き方を検出する(検出時 exit 1)。
|
|
32
|
+
|
|
33
|
+
brand-hex ブランド色の値の直書き → var(--Brand-Cake-Orange) / var(--Text-Accent-Primary) などを使う
|
|
34
|
+
brand-override DS のブランド系トークンの上書き → 上書きせず DS の値を使う
|
|
35
|
+
undefined-token DS にも DIR にも無い変数の参照 → DS にある名前を使う
|
|
36
|
+
brand-primitive --Primitive-Orange-* / --Primitive-Berry-* の直接参照 → 意味のあるトークンを使う
|
|
37
|
+
|
|
38
|
+
除外: node_modules / .next / out / dist / build / coverage / __tests__ / tests / docs / public / scripts と、
|
|
39
|
+
*.test.* / *.spec.* / *.stories.* / *.d.ts
|
|
40
|
+
例外: 同じ行か直前の行に「design-tokens-allow: <理由>」(理由必須)`)
|
|
41
|
+
process.exit(0)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const target = resolve(args.find((a) => !a.startsWith("-")) ?? process.cwd())
|
|
45
|
+
const EXTS = new Set([".css", ".scss", ".ts", ".tsx", ".js", ".jsx", ".mjs"])
|
|
46
|
+
const IGNORE_DIRS = new Set(["node_modules", ".next", "out", "dist", "build", "coverage", ".turbo", "__tests__", "tests", "docs", "public", "scripts"])
|
|
47
|
+
const IGNORE_FILE = /\.(test|spec|stories)\.[cm]?[jt]sx?$|\.d\.ts$/
|
|
48
|
+
const ALLOW_RE = /design-tokens-allow:\s*\S/
|
|
49
|
+
const BRAND_TOKEN_RE = /^(Brand-|Primitive-(Orange|Berry)-|(Surface|Text|Object|Border)-Accent-|(Hover|Active)-(Primary|Secondary)-Button$|Object-Favorite$|Border-Favorite$)/
|
|
50
|
+
// CSS の宣言(--X:)に加え、JS/TS のオブジェクトのキー('--X': / "--X":)も宣言として扱う
|
|
51
|
+
const DECL_RE = /(?:^|[\s;{,("'`])--([A-Za-z][\w-]*)["'`]?\s*:/g
|
|
52
|
+
const VAR_RE = /var\(\s*--([A-Z][\w-]*)/g
|
|
53
|
+
|
|
54
|
+
function walk(dir, filter, skip, out = []) {
|
|
55
|
+
for (const name of readdirSync(dir)) {
|
|
56
|
+
if (skip && (skip.has(name) || name.startsWith("."))) continue
|
|
57
|
+
const p = join(dir, name)
|
|
58
|
+
if (statSync(p).isDirectory()) walk(p, filter, skip, out)
|
|
59
|
+
else if (filter(name)) out.push(p)
|
|
60
|
+
}
|
|
61
|
+
return out
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// DS が定義するトークン名(src/styles と dist の CSS)
|
|
65
|
+
const dsNames = new Set()
|
|
66
|
+
for (const sub of ["src/styles", "src", "dist"]) {
|
|
67
|
+
const d = join(pkgRoot, sub)
|
|
68
|
+
if (!existsSync(d)) continue
|
|
69
|
+
for (const f of walk(d, (n) => n.endsWith(".css"), null)) {
|
|
70
|
+
for (const m of readFileSync(f, "utf8").matchAll(DECL_RE)) dsNames.add(m[1])
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ブランドのパレット(旧オレンジ・現行ベリー)を primitive.css から取り出す
|
|
75
|
+
const palette = []
|
|
76
|
+
const primitive = readFileSync(join(pkgRoot, "src/styles/primitive.css"), "utf8")
|
|
77
|
+
for (const m of primitive.matchAll(/--Primitive-(?:Orange|Berry)-\d+\s*:\s*#([0-9a-f]{6})(?:[0-9a-f]{2})?/gi)) palette.push(m[1].toUpperCase())
|
|
78
|
+
if (palette.length === 0) {
|
|
79
|
+
console.error("DS の src/styles/primitive.css からブランドのパレットを読めませんでした")
|
|
80
|
+
process.exit(2)
|
|
81
|
+
}
|
|
82
|
+
const HEX_RE = new RegExp(`(?:#|%23)(${palette.join("|")})(?:[0-9a-f]{2})?(?![0-9a-f])`, "i")
|
|
83
|
+
// rgb(224, 75, 0) / rgba(224,75,0,.5) に加え、空白区切り・スラッシュ区切りの透明度 rgb(224 75 0 / 0.5) も見る
|
|
84
|
+
const rgbAlts = palette.map((h) => [0, 2, 4].map((i) => parseInt(h.slice(i, i + 2), 16)).join("(?:\\s*,\\s*|\\s+)"))
|
|
85
|
+
const RGB_RE = new RegExp(`rgba?\\(\\s*(${rgbAlts.join("|")})\\s*[,)/]`, "i")
|
|
86
|
+
|
|
87
|
+
const files = walk(target, (n) => EXTS.has(extname(n)) && !IGNORE_FILE.test(n), IGNORE_DIRS)
|
|
88
|
+
const texts = files.map((f) => [f, readFileSync(f, "utf8")])
|
|
89
|
+
const localNames = new Set()
|
|
90
|
+
for (const [, text] of texts) for (const m of text.matchAll(DECL_RE)) localNames.add(m[1])
|
|
91
|
+
|
|
92
|
+
const problems = []
|
|
93
|
+
for (const [file, text] of texts) {
|
|
94
|
+
const lines = text.split("\n")
|
|
95
|
+
lines.forEach((line, i) => {
|
|
96
|
+
if (ALLOW_RE.test(line) || (i > 0 && ALLOW_RE.test(lines[i - 1]))) return
|
|
97
|
+
const where = `${relative(target, file)}:${i + 1}`
|
|
98
|
+
const hex = line.match(HEX_RE) || line.match(RGB_RE)
|
|
99
|
+
if (hex) problems.push([where, "brand-hex", `ブランド色の直書き ${hex[0]} → var(--Brand-Cake-Orange) / var(--Text-Accent-Primary) などの DS トークンを使う`])
|
|
100
|
+
for (const m of line.matchAll(DECL_RE)) {
|
|
101
|
+
if (dsNames.has(m[1]) && BRAND_TOKEN_RE.test(m[1])) problems.push([where, "brand-override", `DS のブランド系トークン --${m[1]} を上書きしている → 上書きせず DS の値を使う`])
|
|
102
|
+
}
|
|
103
|
+
for (const m of line.matchAll(VAR_RE)) {
|
|
104
|
+
if (!dsNames.has(m[1]) && !localNames.has(m[1])) problems.push([where, "undefined-token", `--${m[1]} は DS にもこのプロジェクトにも無い → DS にある名前を使う`])
|
|
105
|
+
else if (/^Primitive-(Orange|Berry)-\d+$/.test(m[1])) problems.push([where, "brand-primitive", `ブランドの原色 --${m[1]} を直接参照している → --Brand-Cake-Orange / --Brand-Cake-Orange-Light / --Hover-Primary-Button などを使う`])
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (problems.length) {
|
|
111
|
+
console.error(`check-tokens: ${problems.length} 件`)
|
|
112
|
+
for (const [where, rule, msg] of problems) console.error(` ${where} [${rule}] ${msg}`)
|
|
113
|
+
console.error("例外にする行には「design-tokens-allow: <理由>」を同じ行か直前の行に書く")
|
|
114
|
+
process.exit(1)
|
|
115
|
+
}
|
|
116
|
+
console.log(`check-tokens: OK(${files.length} ファイル、DS トークン ${dsNames.size} 件、ブランドの色 ${palette.length} 件)`)
|
package/bin/init.js
CHANGED
|
@@ -51,6 +51,9 @@ if (cmd === "help" || cmd === "--help" || cmd === "-h") {
|
|
|
51
51
|
意図的に残すローカル実装は、対象 export の直前行に
|
|
52
52
|
「// cakejp-ds-allow-duplicate: <理由>」を書くと抑制できる(理由必須)
|
|
53
53
|
詳細: npx cakejp-ds check-duplicates --help
|
|
54
|
+
npx cakejp-ds check-tokens [DIR] DS を上げても色が追従しない書き方(ブランド色の直書き・DS トークンの
|
|
55
|
+
上書き・DS に無い変数・ブランド原色の直接参照)を検出(検出時 exit 1)
|
|
56
|
+
例外は行に「design-tokens-allow: <理由>」。詳細: npx cakejp-ds check-tokens --help
|
|
54
57
|
`)
|
|
55
58
|
process.exit(0)
|
|
56
59
|
}
|
|
@@ -87,6 +90,12 @@ if (cmd === "check-duplicates") {
|
|
|
87
90
|
process.exit(0)
|
|
88
91
|
}
|
|
89
92
|
|
|
93
|
+
if (cmd === "check-tokens") {
|
|
94
|
+
process.argv = [process.argv[0], process.argv[1], ...args.slice(1)]
|
|
95
|
+
await import(join(pkgRoot, "bin/check-tokens.mjs"))
|
|
96
|
+
process.exit(0)
|
|
97
|
+
}
|
|
98
|
+
|
|
90
99
|
if (cmd !== "init" && cmd !== "postinstall") {
|
|
91
100
|
console.error(`未知のコマンド: ${cmd}`)
|
|
92
101
|
console.error(`npx cakejp-ds help を参照してください`)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"meta": {
|
|
3
3
|
"name": "Cake.jp Design System — Component Contracts",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.22.1",
|
|
5
5
|
"description": "全コンポーネントの構造化定義。バリアント・アクセシビリティ要件・使用ルールを機械可読形式で管理。",
|
|
6
6
|
"kind": "kind:\"shell\" は複数ページで再利用されるレイアウト枠(AdminShell / WorkspaceShell / MypageShell 等)。無印は部品コンポーネント。固有ページを組むときは該当 shell から始める。src/components/pages/ 配下のストーリーは特定ページ専用・非配布のため contracts の対象外。",
|
|
7
7
|
"naming": "コンポーネント名は**用途ではなく機能**で付ける。用途名(QuantitySelector = カート数量)にすると、同じ機能を別の文脈で探した人が見つけられず二重実装が生まれる(実例: 用途名だったため NumberInput が別途作られ、意匠の違うステッパーが 2 つになった)。「〜Selector」「〜Picker」等の用途接尾辞を付ける前に、その部品が何をするものかで名前が付けられないかを先に検討する。既存名を機能名へ変える場合は deprecatedAliases に旧名を残す。",
|
|
@@ -528,7 +528,7 @@
|
|
|
528
528
|
"variant='tile'(既定)=ラジオ丸+ラベル+補足説明+展開コンテンツのタイル型",
|
|
529
529
|
"⚠️ タイルの枠(border/角丸/余白/選択状態の意匠)は RadioGroupItem 自身が描画する。consumer 側で <div className='border rounded-lg ...'> 等で囲むと枠が二重になる。囲まずにそのまま並べる",
|
|
530
530
|
"ラベルは children で渡す。<RadioGroupItem/> と <Label htmlFor> を兄弟に並べる書き方は誤り(枠の二重化+ラベル重複を招く)",
|
|
531
|
-
"variant='chip'=ラベルを内包したChoice Chip意匠の排他選択(タグ選択・絞り込み等)。ラジオ丸は描画せず、Chip本体と同じchipVariants(filled)を再利用し、選択状態は入力部品のオン状態としてブランド色の薄い地(Chipのaccent意匠と同じトークン:
|
|
531
|
+
"variant='chip'=ラベルを内包したChoice Chip意匠の排他選択(タグ選択・絞り込み等)。ラジオ丸は描画せず、Chip本体と同じchipVariants(filled)を再利用し、選択状態は入力部品のオン状態としてブランド色の薄い地(Chipのaccent意匠と同じトークン: 静止=薄いブランド色/hover=ベタ塗り)で示す。Chip の selected(グレー地 + 黒系の枠)とは別の見た目。description/expandedContentは持たない。Radixのキーボード操作・a11yは維持",
|
|
532
532
|
"tile の未選択の枠は高コントラストのとき --Border-Control(3:1 以上)に切り替わる。枠色は border-[var(--Border-Control,var(--Border-Medium-Emphasis))] の形で書く"
|
|
533
533
|
]
|
|
534
534
|
},
|
|
@@ -631,7 +631,7 @@
|
|
|
631
631
|
"範囲スライダーの Home / End はフォーカス中のつまみを、そのつまみが動ける範囲の端(隣のつまみ ± minStepsBetweenThumbs × step、無ければ min / max)へ動かす(WAI-ARIA APG Multi-Thumb Slider)。つまみが 1 つのときは Radix の既定のまま",
|
|
632
632
|
"つまみの数は value / defaultValue の配列の長さ。どちらも無いときは Radix の既定値 [min] に合わせて 1 つ",
|
|
633
633
|
"forced-colors(Windows のハイコントラスト)では選択範囲を Highlight、レールを CanvasText の輪郭線(outline)で示す。通常表示は変わらない",
|
|
634
|
-
"溝は高コントラストのとき --Surface-Control-Track(3:1 以上)に切り替わる。溝の色は bg-[var(--Surface-Control-Track,var(--Surface-Tertiary))]
|
|
634
|
+
"溝は高コントラストのとき --Surface-Control-Track(3:1 以上)に切り替わる。溝の色は bg-[var(--Surface-Control-Track,var(--Surface-Tertiary))] の形で書く。高コントラスト時の溝と選択範囲(ブランド色)は明るさが近く、区別は色相が中心。値はつまみの位置で伝わる(つまみは 3:1 を満たす)"
|
|
635
635
|
]
|
|
636
636
|
},
|
|
637
637
|
{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"meta": {
|
|
3
3
|
"name": "Cake.jp Design System — Composition Contracts",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.22.1",
|
|
5
5
|
"description": "ページ骨格・視覚階層・余白リズムの機械可読な正本。画面パターンを選んだ後の「実際の組み方」を規定する。ページの外枠(モバイル/デスクトップ/管理)、商品グリッドの列数、余白の4段リズム、Surface のネスト階層、テキスト階層、CTA の優先順位を構造化する。人間向けの解説は guidelines/composition/layout.md・guidelines/composition/hierarchy.md・guidelines/overview.md。",
|
|
6
6
|
"source": "guidelines/composition/layout.md, guidelines/composition/hierarchy.md, guidelines/overview.md, guidelines/components/button.md(CTA 密度ルール)を正本化",
|
|
7
7
|
"roleSeparation": "screen-patterns.json はページ種別(Standard Page / Focused Workspace / ResponsiveDialog / Dialog)を選ぶための契約。composition.json は選んだ後、その骨格をどう組むか(外枠構造・余白リズム・階層)の契約。前者=何を使うか、後者=どう並べるか。",
|
|
@@ -142,12 +142,12 @@
|
|
|
142
142
|
{ "role": "meta", "typo": "typo-body-sm", "color": "--Text-Low-Emphasis", "usage": "メタ情報・タイムスタンプ" },
|
|
143
143
|
{ "role": "smallest-label", "typo": "typo-label-xs", "color": "--Text-Low-Emphasis" }
|
|
144
144
|
],
|
|
145
|
-
"accentNote": "価格などの最強調は typo-label-lg + --Text-Accent-Primary
|
|
145
|
+
"accentNote": "価格などの最強調は typo-label-lg + --Text-Accent-Primary(ブランド色=ベリー)。強調は色ではなく typo 系(heading/label)で表現し、font-bold を足さない。"
|
|
146
146
|
},
|
|
147
147
|
"ctaHierarchy": {
|
|
148
148
|
"description": "Button の variant 優先順位。1ビューポート内での CTA 密度を制御する。⚠️ これは「前進アクションの強さ」の序列であり、画面に並べた2番目のボタンが自動的に secondary になるわけではない。戻る/キャンセル/閉じるのような後退・中立アクションは序列ではなく役割で選ぶ(→ tertiary)。選ぶ前に各項目の appearance(実際の意匠)を必ず確認すること。",
|
|
149
149
|
"priority": [
|
|
150
|
-
{ "variant": "default", "role": "Primary CTA(前進・確定)", "appearance": "
|
|
150
|
+
{ "variant": "default", "role": "Primary CTA(前進・確定)", "appearance": "ブランド色(ベリー)のベタ塗り", "note": "1ビューポートに1つまで(唯一の主 CTA)" },
|
|
151
151
|
{ "variant": "secondary", "role": "Secondary action(前進系の副 CTA。例: 「サンプルを見る」「詳細を見る」)", "appearance": "⚠️ ブランドアクセント(Surface-Accent-Primary-Light 地 + Brand-Cake-Orange 文字)。Material / Bootstrap / shadcn の secondary(グレー・控えめ)とは別物", "note": "アクセント色が付くため、戻る・キャンセル・閉じる等の後退/中立アクションには使わない(→ tertiary)" },
|
|
152
152
|
{ "variant": "tertiary", "role": "Tertiary action / 後退・中立アクション(戻る・キャンセル・閉じる・スキップ・あとで)", "appearance": "ニュートラルなグレー(Surface-Tertiary 地 + Text-High-Emphasis 文字)", "note": "他 DS の secondary に相当する見た目。主 CTA の隣に置く「戻る」「キャンセル」はこれを使う" },
|
|
153
153
|
{ "variant": "outline", "role": "準主役の前進アクション(ブランド色を使わない)。「一覧を見る」等の移動ボタン、一覧・カードで1件ごとに繰り返す操作(商品カードの「カートに追加」等)、ブックマーク等の保存トグルのボタン本体", "appearance": "白地(Surface-Primary)+ 1px の黒系の枠(Border-High-Emphasis)+ Text-High-Emphasis 文字。hover / active は薄い下地(Hover-Text-Button / Active-Text-Button)", "note": "ブランド色を使わないので何個並んでもよい。ただし繰り返す操作は見た目が増えるので、ボタンに頼らずカード全体のリンクで足りるときは置かない" },
|
|
@@ -155,7 +155,7 @@
|
|
|
155
155
|
{ "variant": "link", "role": "補助リンク(「もっと見る」「利用規約を見る」等のインラインの移動)", "appearance": "ブランド色を使わない。Text-Medium-Emphasis(グレー)+ 常時下線。hover で Text-High-Emphasis", "note": "セクション見出し横の「もっと見る」は SectionHeader が同じ意匠で描く" }
|
|
156
156
|
],
|
|
157
157
|
"rules": [
|
|
158
|
-
"default
|
|
158
|
+
"default(ブランド色)の CTA は1ビューポートに1つまで。主アクションを1つに絞る",
|
|
159
159
|
"複数アクションを並べる時は default を tertiary / ghost と組み合わせる",
|
|
160
160
|
"「戻る」「キャンセル」「閉じる」「スキップ」「あとで」は tertiary(グレー)。secondary はアクセント色なので後退アクションに使わない",
|
|
161
161
|
"ブランド色を使わずに「押せるボタン」の存在感がほしい前進アクション(「一覧を見る」、1件ごとに繰り返す操作、保存トグルのボタン本体)は outline。黒ベタ塗りにしない",
|
package/contracts/rules.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"meta": {
|
|
3
3
|
"name": "Cake.jp Design System — Screen Patterns Contracts",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.22.1",
|
|
5
5
|
"description": "CRUD 機能でどの画面パターンを使うかの機械可読な判断基準。5パターンの定義・CRUD 対応・決定木・編集UIの観点比較を構造化する。人間向けの解説は guidelines/foundations/screen-patterns.md。",
|
|
6
6
|
"source": "GitHub issue #37 CRUDの画面設計の型化と基本パターンの整備",
|
|
7
7
|
"relatedContract": "本契約はページ種別の選択(何を使うか)を担う。選んだ後の骨格の組み方(外枠構造・余白リズム・視覚階層)は contracts/composition.json を参照する。",
|
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
import { jsxs as
|
|
1
|
+
import { jsxs as r, jsx as e } from "react/jsx-runtime";
|
|
2
2
|
import "react";
|
|
3
|
-
import
|
|
4
|
-
import { cn as
|
|
5
|
-
import { Button as
|
|
6
|
-
function
|
|
3
|
+
import y from "iconsax-reactjs/dist/esm/Calendar.js";
|
|
4
|
+
import { cn as u } from "../../lib/utils.js";
|
|
5
|
+
import { Button as s } from "../foundations/button.js";
|
|
6
|
+
function A({
|
|
7
7
|
name: n,
|
|
8
|
-
relation:
|
|
8
|
+
relation: c,
|
|
9
9
|
type: l,
|
|
10
|
-
date:
|
|
10
|
+
date: d,
|
|
11
11
|
daysLeft: m,
|
|
12
|
-
memo:
|
|
13
|
-
editHref:
|
|
14
|
-
onEdit:
|
|
12
|
+
memo: a,
|
|
13
|
+
editHref: t,
|
|
14
|
+
onEdit: i,
|
|
15
15
|
linkComponent: p,
|
|
16
16
|
className: o,
|
|
17
17
|
...x
|
|
18
18
|
}) {
|
|
19
|
-
const h =
|
|
20
|
-
return /* @__PURE__ */
|
|
19
|
+
const h = t ? /* @__PURE__ */ e(s, { variant: "tertiary", size: "xs", asChild: !0, children: /* @__PURE__ */ e(p ?? "a", { href: t, children: "編集" }) }) : i ? /* @__PURE__ */ e(s, { variant: "tertiary", size: "xs", onClick: i, children: "編集" }) : null;
|
|
20
|
+
return /* @__PURE__ */ r(
|
|
21
21
|
"div",
|
|
22
22
|
{
|
|
23
23
|
"data-slot": "anniversary-card",
|
|
24
|
-
className:
|
|
24
|
+
className: u(
|
|
25
25
|
"min-w-[200px] rounded-xl border border-[var(--Border-Medium-Emphasis)] bg-[var(--Surface-Primary)] p-4 space-y-2",
|
|
26
26
|
o
|
|
27
27
|
),
|
|
28
28
|
...x,
|
|
29
29
|
children: [
|
|
30
|
-
/* @__PURE__ */
|
|
31
|
-
/* @__PURE__ */
|
|
30
|
+
/* @__PURE__ */ r("div", { className: "flex items-center justify-between gap-2", children: [
|
|
31
|
+
/* @__PURE__ */ r("div", { className: "flex items-center gap-2", children: [
|
|
32
32
|
/* @__PURE__ */ e("p", { className: "typo-label-md text-[var(--Text-High-Emphasis)]", children: n }),
|
|
33
|
-
/* @__PURE__ */ e("span", { className: "typo-label-xs text-[var(--Text-Medium-Emphasis)] bg-[var(--Surface-Secondary)] px-2 py-0.5 rounded-full", children:
|
|
33
|
+
/* @__PURE__ */ e("span", { className: "typo-label-xs text-[var(--Text-Medium-Emphasis)] bg-[var(--Surface-Secondary)] px-2 py-0.5 rounded-full", children: c })
|
|
34
34
|
] }),
|
|
35
35
|
h
|
|
36
36
|
] }),
|
|
37
|
-
/* @__PURE__ */
|
|
37
|
+
/* @__PURE__ */ r("p", { className: "typo-body-sm text-[var(--Text-Medium-Emphasis)]", children: [
|
|
38
38
|
l,
|
|
39
39
|
" — ",
|
|
40
|
-
|
|
40
|
+
d
|
|
41
41
|
] }),
|
|
42
|
-
/* @__PURE__ */
|
|
42
|
+
/* @__PURE__ */ r("div", { className: "flex items-center gap-2 bg-[var(--Surface-Accent-Primary-Light)] rounded-lg px-3 py-2", children: [
|
|
43
43
|
/* @__PURE__ */ e(
|
|
44
|
-
|
|
44
|
+
y,
|
|
45
45
|
{
|
|
46
46
|
size: 16,
|
|
47
|
-
className: "text-[var(--
|
|
47
|
+
className: "text-[var(--Text-Accent-Primary)]",
|
|
48
48
|
"aria-hidden": "true"
|
|
49
49
|
}
|
|
50
50
|
),
|
|
51
|
-
/* @__PURE__ */
|
|
51
|
+
/* @__PURE__ */ r("span", { className: "typo-label-md text-[var(--Text-Accent-Primary)]", children: [
|
|
52
52
|
"あと",
|
|
53
53
|
m,
|
|
54
54
|
"日"
|
|
55
55
|
] })
|
|
56
56
|
] }),
|
|
57
|
-
|
|
57
|
+
a && /* @__PURE__ */ e("p", { className: "typo-body-sm text-[var(--Text-Low-Emphasis)]", children: a })
|
|
58
58
|
]
|
|
59
59
|
}
|
|
60
60
|
);
|
|
61
61
|
}
|
|
62
62
|
export {
|
|
63
|
-
|
|
63
|
+
A as AnniversaryCard
|
|
64
64
|
};
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { jsx as i, jsxs as f } from "react/jsx-runtime";
|
|
2
2
|
import * as h from "react";
|
|
3
3
|
import { cva as y } from "class-variance-authority";
|
|
4
|
-
import { Loader2Icon as
|
|
4
|
+
import { Loader2Icon as T } from "lucide-react";
|
|
5
5
|
import { Slot as p } from "radix-ui";
|
|
6
6
|
import { cn as c } from "../../lib/utils.js";
|
|
7
|
-
import { FOCUS_RING as
|
|
7
|
+
import { FOCUS_RING as B } from "../../lib/focus-ring.js";
|
|
8
8
|
const u = y(
|
|
9
|
-
`inline-flex shrink-0 items-center justify-center gap-2 rounded-lg typo-label-md whitespace-nowrap transition-all outline-none ${
|
|
9
|
+
`inline-flex shrink-0 items-center justify-center gap-2 rounded-lg typo-label-md whitespace-nowrap transition-all outline-none ${B} disabled:pointer-events-none aria-invalid:border-destructive aria-invalid:ring-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,
|
|
10
10
|
{
|
|
11
11
|
variants: {
|
|
12
12
|
variant: {
|
|
13
13
|
default: "bg-[var(--Brand-Cake-Orange)] text-[var(--Text-on-Inverse)] hover:bg-[var(--Hover-Primary-Button)] active:bg-[var(--Active-Primary-Button)] disabled:bg-[var(--Surface-Tertiary)] disabled:text-[var(--Text-Disable)]",
|
|
14
|
-
secondary: "border border-transparent
|
|
14
|
+
secondary: "border border-transparent bg-[var(--Surface-Accent-Primary-Light)] text-[var(--Text-Accent-Primary)] hover:border-[var(--Hover-Primary-Button)] hover:bg-[var(--Hover-Secondary-Button)] hover:text-[var(--Hover-Primary-Button)] active:border-[var(--Active-Primary-Button)] active:bg-[var(--Active-Secondary-Button)] active:text-[var(--Active-Primary-Button)] disabled:border-transparent disabled:bg-[var(--Surface-Tertiary)] disabled:text-[var(--Text-Disable)]",
|
|
15
15
|
tertiary: "bg-[var(--Surface-Tertiary)] text-[var(--Text-High-Emphasis)] hover:bg-[var(--Hover-Tertiary-Button)] active:bg-[var(--Active-Tertiary-Button)] disabled:text-[var(--Text-Disable)]",
|
|
16
16
|
destructive: "bg-[var(--Surface-Caution)] text-[var(--Text-on-Inverse)] hover:bg-[var(--Primitive-Sun-900)] active:bg-[var(--Primitive-Sun-900)] disabled:bg-[var(--Surface-Tertiary)] disabled:text-[var(--Text-Disable)]",
|
|
17
17
|
ghost: "text-[var(--Text-High-Emphasis)] hover:bg-[var(--Hover-Text-Button)] active:bg-[var(--Active-Text-Button)] disabled:text-[var(--Text-Disable)]",
|
|
@@ -29,7 +29,7 @@ const u = y(
|
|
|
29
29
|
link: "text-[var(--Text-Medium-Emphasis)] underline underline-offset-4 hover:text-[var(--Text-High-Emphasis)] disabled:text-[var(--Text-Disable)]",
|
|
30
30
|
/**
|
|
31
31
|
* inverse — 暗背景の上で使う primary CTA。
|
|
32
|
-
* 白背景 + accent text (Brand
|
|
32
|
+
* 白背景 + accent text (Brand-Cake-Orange=ベリー)。
|
|
33
33
|
* hover で薄く陰り、active で更に。
|
|
34
34
|
*/
|
|
35
35
|
inverse: "bg-[var(--Surface-Primary)] text-[var(--Brand-Cake-Orange)] hover:bg-[var(--Primitive-White-alpha-900)] active:bg-[var(--Primitive-White-alpha-800)] disabled:bg-[var(--Primitive-White-alpha-300)] disabled:text-[var(--Text-Disable)]",
|
|
@@ -211,7 +211,7 @@ function W({
|
|
|
211
211
|
"data-slot": "button-spinner",
|
|
212
212
|
"aria-hidden": "true",
|
|
213
213
|
className: "pointer-events-none absolute inset-0 flex items-center justify-center",
|
|
214
|
-
children: /* @__PURE__ */ i(
|
|
214
|
+
children: /* @__PURE__ */ i(T, { className: "animate-spin motion-reduce:animate-none" })
|
|
215
215
|
}
|
|
216
216
|
)
|
|
217
217
|
]
|
|
@@ -12,7 +12,7 @@ const t = e(
|
|
|
12
12
|
].join(" "),
|
|
13
13
|
/** accent — 薄いブランド色地 + ブランド色文字。Chip の selected は使わなくなった(明示指定の互換のために残す) */
|
|
14
14
|
accent: [
|
|
15
|
-
"bg-[var(--Surface-Accent-Primary-Light)] text-[var(--
|
|
15
|
+
"bg-[var(--Surface-Accent-Primary-Light)] text-[var(--Text-Accent-Primary)]",
|
|
16
16
|
"hover:bg-[var(--Surface-Accent-Primary)] hover:text-[var(--Text-on-Inverse)]",
|
|
17
17
|
"disabled:bg-[var(--Surface-Secondary)] disabled:text-[var(--Text-Disable)] disabled:hover:bg-[var(--Surface-Secondary)] disabled:hover:text-[var(--Text-Disable)]"
|
|
18
18
|
].join(" "),
|
|
@@ -105,12 +105,11 @@ function j({
|
|
|
105
105
|
return /* @__PURE__ */ e(
|
|
106
106
|
"span",
|
|
107
107
|
{
|
|
108
|
-
"aria-hidden": !0,
|
|
109
108
|
"data-slot": "pagination-ellipsis",
|
|
110
109
|
className: t("flex size-10 shrink-0 items-center justify-center text-muted-foreground", a),
|
|
111
110
|
...n,
|
|
112
111
|
children: [
|
|
113
|
-
/* @__PURE__ */ i(c, { className: "size-4" }),
|
|
112
|
+
/* @__PURE__ */ i(c, { "aria-hidden": !0, className: "size-4" }),
|
|
114
113
|
/* @__PURE__ */ i("span", { className: "sr-only", children: "その他のページ" })
|
|
115
114
|
]
|
|
116
115
|
}
|
|
@@ -43,9 +43,9 @@ function y({
|
|
|
43
43
|
"cursor-pointer outline-none",
|
|
44
44
|
// checked = 入力部品のオン状態なのでブランド色のまま(brandColorUsage の allowed)。
|
|
45
45
|
// Chip の selected はグレー地 + 黒系の枠に変わったため、見た目は Chip と別(Chip の accent と同一トークン)。
|
|
46
|
-
"data-[state=checked]:bg-[var(--Surface-Accent-Primary-Light)] data-[state=checked]:text-[var(--
|
|
46
|
+
"data-[state=checked]:bg-[var(--Surface-Accent-Primary-Light)] data-[state=checked]:text-[var(--Text-Accent-Primary)]",
|
|
47
47
|
"data-[state=checked]:hover:bg-[var(--Surface-Accent-Primary)] data-[state=checked]:hover:text-[var(--Text-on-Inverse)]",
|
|
48
|
-
// forced-colors(Windows
|
|
48
|
+
// forced-colors(Windows ハイコントラスト)では薄いブランド色の地が Canvas に置き換わり、未選択と
|
|
49
49
|
// 見分けがつかないため、選択中だけ OS の選択色で示す(Chip の selected と同じ。通常表示は不変)
|
|
50
50
|
"forced-colors:data-[state=checked]:bg-[Highlight] forced-colors:data-[state=checked]:text-[HighlightText]",
|
|
51
51
|
// form 固有の状態(chipVariants に無い分のみ compose)。disabled の配色は chipVariants filled が担う。
|
|
@@ -67,7 +67,7 @@ function y({
|
|
|
67
67
|
"hover:border-[var(--Text-High-Emphasis)] hover:bg-[var(--Surface-Secondary)]",
|
|
68
68
|
"data-[state=checked]:border-[var(--Object-Accent-Primary)] data-[state=checked]:bg-[var(--Surface-Primary)]",
|
|
69
69
|
// フォーカス意匠は DS 共通(FOCUS_RING = 緑リング)。以前はオレンジの
|
|
70
|
-
// ring-2 で checked
|
|
70
|
+
// ring-2 で checked 状態(同じくブランド色の枠)と紛らわしかったため統一した。
|
|
71
71
|
m,
|
|
72
72
|
"aria-invalid:border-[var(--Border-Caution)]",
|
|
73
73
|
"disabled:cursor-not-allowed disabled:border-[var(--Border-Medium-Emphasis)] disabled:bg-[var(--Surface-Secondary)] disabled:hover:border-[var(--Border-Medium-Emphasis)] disabled:hover:bg-[var(--Surface-Secondary)]",
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { jsx as n } from "react/jsx-runtime";
|
|
3
3
|
import * as s from "react";
|
|
4
4
|
import { cva as l } from "class-variance-authority";
|
|
5
|
-
import { ToggleGroup as
|
|
6
|
-
import { cn as
|
|
5
|
+
import { ToggleGroup as c } from "radix-ui";
|
|
6
|
+
import { cn as d } from "../../lib/utils.js";
|
|
7
7
|
import { FORCED_COLORS_FOCUS_INSET as u } from "../../lib/focus-ring.js";
|
|
8
8
|
const p = l(
|
|
9
9
|
"flex items-center gap-1.5 py-1.5 overflow-x-auto scrollbar-none",
|
|
@@ -42,7 +42,7 @@ const p = l(
|
|
|
42
42
|
default: [
|
|
43
43
|
"bg-[var(--Surface-Tertiary)] text-[var(--Text-Medium-Emphasis)]",
|
|
44
44
|
"hover:bg-[var(--Surface-Tertiary)]/80",
|
|
45
|
-
"data-[state=on]:bg-[var(--Surface-Accent-Primary-Light)] data-[state=on]:text-[var(--
|
|
45
|
+
"data-[state=on]:bg-[var(--Surface-Accent-Primary-Light)] data-[state=on]:text-[var(--Text-Accent-Primary)] data-[state=on]:font-bold",
|
|
46
46
|
"dark:bg-[var(--Surface-Secondary)] dark:text-[var(--Text-Low-Emphasis)]",
|
|
47
47
|
"dark:data-[state=on]:bg-[var(--Surface-Accent-Primary-Light)] dark:data-[state=on]:text-[var(--Text-Accent-Primary)]"
|
|
48
48
|
].join(" "),
|
|
@@ -63,7 +63,7 @@ const p = l(
|
|
|
63
63
|
size: "default"
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
),
|
|
66
|
+
), g = s.createContext({
|
|
67
67
|
variant: "default",
|
|
68
68
|
size: "default"
|
|
69
69
|
});
|
|
@@ -76,12 +76,12 @@ function T({
|
|
|
76
76
|
...t
|
|
77
77
|
}) {
|
|
78
78
|
return /* @__PURE__ */ n(
|
|
79
|
-
|
|
79
|
+
c.Root,
|
|
80
80
|
{
|
|
81
81
|
"data-slot": "toggle-group",
|
|
82
|
-
className:
|
|
82
|
+
className: d(p({ width: o }), a),
|
|
83
83
|
...t,
|
|
84
|
-
children: /* @__PURE__ */ n(
|
|
84
|
+
children: /* @__PURE__ */ n(g.Provider, { value: { variant: e, size: r }, children: i })
|
|
85
85
|
}
|
|
86
86
|
);
|
|
87
87
|
}
|
|
@@ -92,12 +92,12 @@ function y({
|
|
|
92
92
|
size: o,
|
|
93
93
|
...i
|
|
94
94
|
}) {
|
|
95
|
-
const t = s.useContext(
|
|
95
|
+
const t = s.useContext(g);
|
|
96
96
|
return /* @__PURE__ */ n(
|
|
97
|
-
|
|
97
|
+
c.Item,
|
|
98
98
|
{
|
|
99
99
|
"data-slot": "toggle-group-item",
|
|
100
|
-
className:
|
|
100
|
+
className: d(
|
|
101
101
|
f({
|
|
102
102
|
variant: t.variant || r,
|
|
103
103
|
size: t.size || o
|
|
@@ -16,7 +16,7 @@ const x = o(
|
|
|
16
16
|
info: "bg-[var(--Primitive-Sea-50)] text-[var(--Primitive-Sea-600)] dark:bg-[var(--Primitive-Sea-600)] dark:text-[var(--Primitive-White-alpha-1000)]",
|
|
17
17
|
"info-fill": "bg-[var(--Primitive-Sea-600)] text-[var(--Text-on-Inverse)]",
|
|
18
18
|
success: "bg-[var(--Primitive-Forest-50)] text-[var(--Text-Success)]",
|
|
19
|
-
accent: "bg-[var(--Surface-Accent-Primary-Light)] text-[var(--
|
|
19
|
+
accent: "bg-[var(--Surface-Accent-Primary-Light)] text-[var(--Text-Accent-Primary)]",
|
|
20
20
|
timesale: "bg-[var(--Primitive-Wood-400)] text-[var(--Text-on-Inverse)]",
|
|
21
21
|
berry: "bg-[var(--Primitive-Berry-700)] text-[var(--Text-on-Inverse)]",
|
|
22
22
|
coupon: "bg-[var(--Primitive-Sea-500)] text-[var(--Text-on-Inverse)]"
|