@cakejp/design-system 0.21.0 → 0.22.0
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 +26 -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/content-carousel.js +85 -76
- package/dist/components/primitives/tag.js +1 -1
- package/dist/index.css +1 -1
- package/dist/index.js +37 -20
- package/dist/types/components/primitives/content-carousel.d.ts +1 -0
- 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,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
|
+
## [0.22.0] - 2026-10-26
|
|
15
|
+
|
|
16
|
+
### 🎨 Changed
|
|
17
|
+
|
|
18
|
+
- **ブランドカラーをオレンジ(`#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`)
|
|
19
|
+
- 変数名(`--Brand-Cake-Orange` など)は据え置き。利用側のコード変更は不要で、バージョンを上げると色が変わる
|
|
20
|
+
- 旧カラー(オレンジ)は `--Primitive-Orange-*` に元の値のまま残している。`bg-orange-*` などの Tailwind ユーティリティもオレンジのまま
|
|
21
|
+
- accent-primary の文字・地のコントラストが 4.5:1 を満たすようになったため、コントラスト検査の例外 3 件を削除
|
|
22
|
+
- 薄いアクセント地(`--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 では一段濃い赤になる。コントラスト検査の例外は不要になり削除
|
|
23
|
+
|
|
24
|
+
### 🐛 Fixed
|
|
25
|
+
|
|
26
|
+
- **Button `secondary` の hover / active の線が太すぎた**([#300](https://github.com/flashpark/cake-design-system/issues/300)): 1px の枠線と 2px の outline が同色で重なり約 3px に見えていた。hover / active は 1px の枠線の色替えだけにした(Pagination の選択中も同じ)。フォーカス表示は従来どおり共通のリング
|
|
27
|
+
- **PaginationEllipsis の「その他のページ」が読み上げられなかった**([#300](https://github.com/flashpark/cake-design-system/issues/300)): 外側の `aria-hidden` を外し、アイコンだけを読み上げから外した。見た目は変わらない
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## [0.21.1] - 2026-10-21
|
|
32
|
+
|
|
33
|
+
### 🐛 Fixed
|
|
34
|
+
|
|
35
|
+
- **`ContentCarousel` の矢印が、複数枚表示(`itemsPerView`)でも 1 枚ずつしか送らなかった**([#325](https://github.com/flashpark/cake-design-system/pull/325)): 見えている枚数を実際の幅から求め、その枚数ずつ送る(PC で 4 枚表示なら 4 枚ずつ)。SP・peek(1 枚表示)は従来どおり 1 枚ずつ。末尾から次へで先頭、先頭から前へで末尾に戻る動きは変えない
|
|
36
|
+
- `autoPlay` も同じく 1 画面ずつ送る。既存の `itemsPerView` 2 以上の利用箇所は、矢印の送り幅が表示枚数に変わる
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
14
40
|
## [0.21.0] - 2026-10-15
|
|
15
41
|
|
|
16
42
|
### ✨ Added
|
|
@@ -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.0",
|
|
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.0",
|
|
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.0",
|
|
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
|
|
@@ -1,156 +1,165 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsxs as w, jsx as
|
|
2
|
+
import { jsxs as w, jsx as n, Fragment as j } from "react/jsx-runtime";
|
|
3
3
|
import * as s from "react";
|
|
4
4
|
import O from "iconsax-reactjs/dist/esm/ArrowLeft2.js";
|
|
5
5
|
import R from "iconsax-reactjs/dist/esm/ArrowRight2.js";
|
|
6
|
-
import { cn as
|
|
6
|
+
import { cn as f } from "../../lib/utils.js";
|
|
7
7
|
import { usePrefersReducedMotion as F } from "../../lib/use-prefers-reduced-motion.js";
|
|
8
|
-
const
|
|
8
|
+
const W = {
|
|
9
9
|
1: "@[960px]:w-full",
|
|
10
10
|
2: "@[960px]:w-[calc((100%-16px)/2)]",
|
|
11
11
|
3: "@[960px]:w-[calc((100%-32px)/3)]",
|
|
12
12
|
4: "@[960px]:w-[calc((100%-48px)/4)]"
|
|
13
13
|
};
|
|
14
|
-
function
|
|
14
|
+
function _({
|
|
15
15
|
slides: p,
|
|
16
16
|
showDots: E = !0,
|
|
17
|
-
showArrows:
|
|
18
|
-
autoPlay:
|
|
19
|
-
peek:
|
|
20
|
-
itemsPerView:
|
|
21
|
-
ariaLabel:
|
|
22
|
-
className:
|
|
23
|
-
...
|
|
17
|
+
showArrows: I = !0,
|
|
18
|
+
autoPlay: m = 0,
|
|
19
|
+
peek: v = !1,
|
|
20
|
+
itemsPerView: b = 1,
|
|
21
|
+
ariaLabel: N = "コンテンツカルーセル",
|
|
22
|
+
className: S,
|
|
23
|
+
...L
|
|
24
24
|
}) {
|
|
25
|
-
const
|
|
25
|
+
const i = s.useRef(null), [c, z] = s.useState(0), l = F(), r = p.length;
|
|
26
26
|
s.useEffect(() => {
|
|
27
|
-
const
|
|
28
|
-
if (!
|
|
29
|
-
let
|
|
27
|
+
const e = i.current;
|
|
28
|
+
if (!e) return;
|
|
29
|
+
let t = 0;
|
|
30
30
|
const o = () => {
|
|
31
|
-
cancelAnimationFrame(
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
),
|
|
35
|
-
let
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
}), z(
|
|
31
|
+
cancelAnimationFrame(t), t = requestAnimationFrame(() => {
|
|
32
|
+
const u = Array.from(
|
|
33
|
+
e.querySelectorAll("[data-slide]")
|
|
34
|
+
), M = u[0]?.offsetLeft ?? 0;
|
|
35
|
+
let g = 0, y = Number.POSITIVE_INFINITY;
|
|
36
|
+
u.forEach((k, T) => {
|
|
37
|
+
const C = Math.abs(k.offsetLeft - M - e.scrollLeft);
|
|
38
|
+
C < y && (y = C, g = T);
|
|
39
|
+
}), z(g);
|
|
40
40
|
});
|
|
41
41
|
};
|
|
42
|
-
o(),
|
|
43
|
-
const
|
|
44
|
-
return
|
|
45
|
-
cancelAnimationFrame(
|
|
42
|
+
o(), e.addEventListener("scroll", o, { passive: !0 });
|
|
43
|
+
const a = typeof ResizeObserver > "u" ? void 0 : new ResizeObserver(o);
|
|
44
|
+
return a?.observe(e), () => {
|
|
45
|
+
cancelAnimationFrame(t), e.removeEventListener("scroll", o), a?.disconnect();
|
|
46
46
|
};
|
|
47
|
-
}, [
|
|
47
|
+
}, [r]);
|
|
48
48
|
const d = s.useCallback(
|
|
49
|
-
(
|
|
50
|
-
const
|
|
51
|
-
if (!
|
|
52
|
-
const o =
|
|
53
|
-
o &&
|
|
54
|
-
left: o.offsetLeft -
|
|
55
|
-
behavior:
|
|
49
|
+
(e) => {
|
|
50
|
+
const t = i.current;
|
|
51
|
+
if (!t) return;
|
|
52
|
+
const o = t.children[e], a = t.children[0];
|
|
53
|
+
o && a && t.scrollTo({
|
|
54
|
+
left: o.offsetLeft - a.offsetLeft,
|
|
55
|
+
behavior: l ? "auto" : "smooth"
|
|
56
56
|
});
|
|
57
57
|
},
|
|
58
|
-
[
|
|
59
|
-
),
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
[l]
|
|
59
|
+
), h = s.useCallback(() => {
|
|
60
|
+
const e = i.current, t = e?.children[0], o = e?.children[1];
|
|
61
|
+
if (!e || !t || !o) return 1;
|
|
62
|
+
const a = o.offsetLeft - t.offsetLeft;
|
|
63
|
+
if (a <= 0) return 1;
|
|
64
|
+
const u = a - t.offsetWidth;
|
|
65
|
+
return Math.max(1, Math.floor((e.clientWidth + u + 1) / a));
|
|
66
|
+
}, []), x = s.useCallback(() => {
|
|
67
|
+
const e = i.current, t = e ? e.scrollLeft >= e.scrollWidth - e.clientWidth - 1 : !1;
|
|
68
|
+
d(
|
|
69
|
+
c >= r - 1 || t ? 0 : Math.min(c + h(), r - 1)
|
|
70
|
+
);
|
|
71
|
+
}, [c, r, d, h]);
|
|
63
72
|
s.useEffect(() => {
|
|
64
|
-
if (
|
|
65
|
-
const
|
|
66
|
-
return () => clearInterval(
|
|
67
|
-
}, [
|
|
73
|
+
if (l || m <= 0 || r <= 1) return;
|
|
74
|
+
const e = setInterval(x, m);
|
|
75
|
+
return () => clearInterval(e);
|
|
76
|
+
}, [m, r, l, x]);
|
|
68
77
|
function A() {
|
|
69
|
-
d(
|
|
78
|
+
d(c <= 0 ? r - 1 : Math.max(0, c - h()));
|
|
70
79
|
}
|
|
71
|
-
return
|
|
80
|
+
return r === 0 ? null : /* @__PURE__ */ w(
|
|
72
81
|
"div",
|
|
73
82
|
{
|
|
74
83
|
"data-slot": "content-carousel",
|
|
75
84
|
role: "region",
|
|
76
85
|
"aria-roledescription": "carousel",
|
|
77
|
-
"aria-label":
|
|
78
|
-
className:
|
|
79
|
-
...
|
|
86
|
+
"aria-label": N,
|
|
87
|
+
className: f("@container group/carousel relative", S),
|
|
88
|
+
...L,
|
|
80
89
|
children: [
|
|
81
|
-
/* @__PURE__ */
|
|
90
|
+
/* @__PURE__ */ n(
|
|
82
91
|
"div",
|
|
83
92
|
{
|
|
84
|
-
ref:
|
|
85
|
-
className:
|
|
93
|
+
ref: i,
|
|
94
|
+
className: f(
|
|
86
95
|
"flex snap-x snap-mandatory overflow-x-auto scroll-smooth motion-reduce:scroll-auto scrollbar-none",
|
|
87
96
|
// peek: 端の余白 = Container の gutter(外に置いたときは 16px)。Container の中では
|
|
88
97
|
// gutter 分だけ外へはみ出して画面端までスクロールさせる。scroll-padding も同じ幅にして、
|
|
89
98
|
// スナップ後も端の余白が消えないようにする。PC (@[960px]:) では peek しないので外す
|
|
90
|
-
|
|
91
|
-
|
|
99
|
+
v && "-mx-[var(--Container-Gutter,0px)] gap-3 px-[var(--Container-Gutter,16px)] scroll-px-[var(--Container-Gutter,16px)] @[960px]:mx-0 @[960px]:gap-0 @[960px]:px-0 @[960px]:scroll-px-0",
|
|
100
|
+
b > 1 && "@[960px]:gap-4"
|
|
92
101
|
),
|
|
93
102
|
style: { scrollbarWidth: "none", msOverflowStyle: "none" },
|
|
94
|
-
children: p.map((
|
|
103
|
+
children: p.map((e, t) => /* @__PURE__ */ n(
|
|
95
104
|
"div",
|
|
96
105
|
{
|
|
97
106
|
"data-slide": !0,
|
|
98
|
-
"data-index":
|
|
107
|
+
"data-index": t,
|
|
99
108
|
role: "group",
|
|
100
109
|
"aria-roledescription": "スライド",
|
|
101
|
-
"aria-label": `${
|
|
102
|
-
className:
|
|
110
|
+
"aria-label": `${t + 1} / ${r}`,
|
|
111
|
+
className: f(
|
|
103
112
|
"shrink-0 snap-start",
|
|
104
113
|
// peek: 端の余白 16px のとき、カード幅は導入前(全幅に置いた場合)と同じ「全幅 - 76px」
|
|
105
|
-
|
|
106
|
-
|
|
114
|
+
v ? "w-[calc(100%-44px)]" : "w-full",
|
|
115
|
+
W[b]
|
|
107
116
|
),
|
|
108
|
-
children:
|
|
117
|
+
children: e
|
|
109
118
|
},
|
|
110
|
-
|
|
119
|
+
t
|
|
111
120
|
))
|
|
112
121
|
}
|
|
113
122
|
),
|
|
114
|
-
|
|
115
|
-
/* @__PURE__ */
|
|
123
|
+
I && r > 1 && /* @__PURE__ */ w(j, { children: [
|
|
124
|
+
/* @__PURE__ */ n(
|
|
116
125
|
"button",
|
|
117
126
|
{
|
|
118
127
|
type: "button",
|
|
119
128
|
onClick: A,
|
|
120
129
|
"aria-label": "前へ",
|
|
121
130
|
className: "absolute left-2 top-1/2 z-10 hidden size-10 -translate-y-1/2 items-center justify-center rounded-full border border-[var(--Border-Control,var(--Border-Medium-Emphasis))] bg-[var(--Surface-Secondary)] shadow-md transition-opacity hover:bg-[var(--Surface-Tertiary)] @md:flex @[960px]:opacity-0 @[960px]:group-hover/carousel:opacity-100",
|
|
122
|
-
children: /* @__PURE__ */
|
|
131
|
+
children: /* @__PURE__ */ n(O, { size: 20, className: "text-[var(--Object-High-Emphasis)]" })
|
|
123
132
|
}
|
|
124
133
|
),
|
|
125
|
-
/* @__PURE__ */
|
|
134
|
+
/* @__PURE__ */ n(
|
|
126
135
|
"button",
|
|
127
136
|
{
|
|
128
137
|
type: "button",
|
|
129
|
-
onClick:
|
|
138
|
+
onClick: x,
|
|
130
139
|
"aria-label": "次へ",
|
|
131
140
|
className: "absolute right-2 top-1/2 z-10 hidden size-10 -translate-y-1/2 items-center justify-center rounded-full border border-[var(--Border-Control,var(--Border-Medium-Emphasis))] bg-[var(--Surface-Secondary)] shadow-md transition-opacity hover:bg-[var(--Surface-Tertiary)] @md:flex @[960px]:opacity-0 @[960px]:group-hover/carousel:opacity-100",
|
|
132
|
-
children: /* @__PURE__ */
|
|
141
|
+
children: /* @__PURE__ */ n(R, { size: 20, className: "text-[var(--Object-High-Emphasis)]" })
|
|
133
142
|
}
|
|
134
143
|
)
|
|
135
144
|
] }),
|
|
136
|
-
E &&
|
|
145
|
+
E && r > 1 && /* @__PURE__ */ n("div", { className: "mt-2 flex flex-wrap items-center justify-center gap-1.5 @[960px]:hidden", children: p.map((e, t) => /* @__PURE__ */ n(
|
|
137
146
|
"button",
|
|
138
147
|
{
|
|
139
148
|
type: "button",
|
|
140
|
-
onClick: () => d(
|
|
141
|
-
"aria-label": `スライド ${
|
|
142
|
-
className:
|
|
149
|
+
onClick: () => d(t),
|
|
150
|
+
"aria-label": `スライド ${t + 1}`,
|
|
151
|
+
className: f(
|
|
143
152
|
// shrink-0 必須: 空要素なので min-content 幅が 0、既定の flex-shrink:1 だとドットが消える
|
|
144
153
|
"size-2 shrink-0 rounded-full transition-colors",
|
|
145
|
-
|
|
154
|
+
t === c ? "bg-[var(--Text-High-Emphasis)]" : "bg-[var(--Surface-Tertiary)]"
|
|
146
155
|
)
|
|
147
156
|
},
|
|
148
|
-
|
|
157
|
+
t
|
|
149
158
|
)) })
|
|
150
159
|
]
|
|
151
160
|
}
|
|
152
161
|
);
|
|
153
162
|
}
|
|
154
163
|
export {
|
|
155
|
-
|
|
164
|
+
_ as ContentCarousel
|
|
156
165
|
};
|
|
@@ -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)]"
|