@cakejp/design-system 0.9.0 → 0.11.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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * AdminLayout — 管理画面の共通レイアウト
2
+ * AdminShell — 管理画面の共通レイアウト
3
3
  *
4
4
  * 本番の shop_layout.ctp を参考に、Header + SideNav + Main Content の構造を再現。
5
5
  * 汎用の枠は primitives(AdminSideNav / AdminHeader)に切り出し、
@@ -17,7 +17,7 @@ export declare function MissingComponent({ name, children, className, }: {
17
17
  children: React.ReactNode;
18
18
  className?: string;
19
19
  }): import("react/jsx-runtime").JSX.Element;
20
- export interface AdminLayoutProps {
20
+ export interface AdminShellProps {
21
21
  children: React.ReactNode;
22
22
  /** 現在アクティブなナビアイテム */
23
23
  activeNav?: string;
@@ -34,5 +34,13 @@ export interface AdminLayoutProps {
34
34
  navItems?: AdminNavItem[];
35
35
  /** ヘッダー右側のアクション slot(既定=通知ベル+プロフィール) */
36
36
  headerActions?: React.ReactNode;
37
+ /**
38
+ * 戻る導線のクリックハンドラ。渡されたときのみ、main 内のパンくずより上に戻るボタンを描画する。
39
+ * 編集系ページの戻る導線はパンくずより上に置く(シェルが位置を保証する)。
40
+ * 子コンテンツ内に戻るリンクを手書きしないこと。未指定なら何も出ない。
41
+ */
42
+ onBack?: () => void;
43
+ /** 戻るボタンのラベル(既定="戻る") */
44
+ backLabel?: string;
37
45
  }
38
- export declare function AdminLayout({ children, activeNav, title, breadcrumbs, shopName, navItems, headerActions, }: AdminLayoutProps): import("react/jsx-runtime").JSX.Element;
46
+ export declare function AdminShell({ children, activeNav, title, breadcrumbs, shopName, navItems, headerActions, onBack, backLabel, }: AdminShellProps): import("react/jsx-runtime").JSX.Element;
@@ -16,8 +16,19 @@
16
16
  * ❌ マイページトップ (Dashboard) — メインカラムに白背景を持たず、セクションごとにカード化
17
17
  *
18
18
  * 上記の例外は意図的な別パターンなのでこのシェルを使わない。
19
+ *
20
+ * ## 事業横断での再利用
21
+ *
22
+ * 骨格(ヘッダー+2カラム+BottomTabBar)は事業横断で再利用できる。
23
+ * ジョブボード・他ブランドの consumer では `logo` / `navItems` / `menuGroups` /
24
+ * `breadcrumbs` / `bottomNavItems` / `headerActions` を差し替えて骨格を再利用する。
25
+ * 既定値は Cake.jp EC(ロゴ=CakeLogo、メニュー=マイページメニュー)。
26
+ * `logo` / `navItems` を渡せば PC ヘッダーのブランドを差し替えられ、
27
+ * 「マイページ配下だけ Cake.jp ロゴに割れる」問題を避けられる。
19
28
  */
20
29
  import React from "react";
30
+ import { type HeaderAction, type HeaderNavItem } from "../../components/primitives/header";
31
+ import { type SideNavGroup, type SideNavItem } from "../../components/primitives/side-nav";
21
32
  import { type BottomTabBarItem } from "../../components/primitives/bottom-tab-bar";
22
33
  export interface MypageShellBreadcrumb {
23
34
  label: string;
@@ -26,16 +37,50 @@ export interface MypageShellBreadcrumb {
26
37
  export interface MypageShellProps {
27
38
  /** ページタイトル(SP の h1 + PC の main h1 + 末尾パンくず に使用) */
28
39
  title: string;
29
- /** SideNav の activeMenu に渡すキー */
30
- activeMenu: string;
40
+ /** SideNav の activeMenu に渡すキー(完全一致)。`currentPath` / `isActiveMenuItem` 使用時は省略可。 */
41
+ activeMenu?: string;
42
+ /**
43
+ * 現在の URL パス。渡すと SideNav が `href` と照合してアクティブ項目を自動判定する
44
+ * (`activeMenu` の手動指定が不要になる)。既定の照合は完全一致(`activeMatch="prefix"` で配下ページ全体を対象に)。
45
+ */
46
+ currentPath?: string;
47
+ /**
48
+ * `currentPath` と SideNav 各項目 `href` の照合方法(既定 `"exact"`)。
49
+ * `"prefix"` にすると詳細・配下ページ(例: `/mypage/orders/123/`)でも一覧項目(`/mypage/orders/`)がアクティブになる。
50
+ */
51
+ activeMatch?: "exact" | "prefix";
52
+ /** SideNav のアクティブ判定を上書きする述語(最優先)。consumer 固有の URL 集約ロジックを注入する。 */
53
+ isActiveMenuItem?: (item: SideNavItem) => boolean;
31
54
  /** コンテンツ */
32
55
  children: React.ReactNode;
33
56
  /** パンくず(省略時はデフォルト: ホーム > 山田 太郎 さまのマイページ > {title}) */
34
57
  breadcrumbs?: MypageShellBreadcrumb[];
35
58
  /** BottomTabBar items(省略時はデフォルト。isActive 等を渡したい場合はこちら) */
36
59
  bottomNavItems?: BottomTabBarItem[];
60
+ /**
61
+ * PC サイドバーのメニューグループ(既定=Cake.jp EC のマイページメニュー)。
62
+ * ジョブボード等の他事業では差し替えて骨格を再利用する。
63
+ */
64
+ menuGroups?: SideNavGroup[];
65
+ /**
66
+ * PC ヘッダー右側のアクション(既定=検索/マイページ/カート)。
67
+ * 他事業では差し替えて骨格を再利用する。
68
+ */
69
+ headerActions?: HeaderAction[];
70
+ /**
71
+ * PC ヘッダーのロゴ(既定=`CakeLogo`)。
72
+ * 他ブランドの consumer は自社ロゴを渡してマイページのブランド割れを防ぐ。
73
+ * ※ SP は `Header variant="back"`(戻るボタン)でロゴを表示しないため、この prop は PC ヘッダーにのみ作用する。
74
+ */
75
+ logo?: React.ReactNode;
76
+ /**
77
+ * PC ヘッダーのグローバルナビ(既定=なし)。
78
+ * 他ブランドの consumer は自社ナビ(例: 商品を探す/ご利用ガイド/よくある質問)を渡して骨格を再利用する。
79
+ * SP では非表示(`Header` の仕様)。
80
+ */
81
+ navItems?: HeaderNavItem[];
37
82
  /** SP の戻るボタン押下時のハンドラ(Header variant="back" に委譲) */
38
83
  onBack?: () => void;
39
84
  }
40
- declare function MypageShell({ title, activeMenu, children, breadcrumbs, bottomNavItems, onBack, }: MypageShellProps): import("react/jsx-runtime").JSX.Element;
85
+ declare function MypageShell({ title, activeMenu, currentPath, activeMatch, isActiveMenuItem, children, breadcrumbs, bottomNavItems, menuGroups, headerActions, logo, navItems, onBack, }: MypageShellProps): import("react/jsx-runtime").JSX.Element;
41
86
  export { MypageShell };
@@ -33,10 +33,11 @@ declare function DataTableCheckboxCell({ className, checked, onCheckedChange, in
33
33
  indeterminate?: boolean;
34
34
  "aria-label"?: string;
35
35
  }): import("react/jsx-runtime").JSX.Element;
36
- declare function DataTableActionCell({ className, actions, ...props }: Omit<React.ComponentProps<"td">, "children" | "width" | "align"> & {
36
+ declare function DataTableActionCell({ className, actions, onClick, ...props }: Omit<React.ComponentProps<"td">, "children" | "width" | "align"> & {
37
37
  actions: Array<{
38
38
  label: string;
39
- onClick?: () => void;
39
+ /** メニュー項目選択時。Radix DropdownMenuItem から MouseEvent が渡る */
40
+ onClick?: (event: React.MouseEvent<HTMLElement>) => void;
40
41
  destructive?: boolean;
41
42
  separator?: boolean;
42
43
  }>;
@@ -10,7 +10,9 @@ export interface AdminHeaderProps {
10
10
  /**
11
11
  * 管理画面向け固定ヘッダー
12
12
  *
13
- * 上端に fixed 配置される横バー。左に SP ハンバーガー+ブランド、右にアクション slot を持つ。
13
+ * 上端に **全幅** で fixed 配置される横バー(z-40)。左に SP ハンバーガー+ブランド、
14
+ * 右にアクション slot を持つ。PC ではこのヘッダーの下端(top-16)から `AdminSideNav`
15
+ * のレール(z-30)が始まる=ヘッダーが最前面・全幅で、レールはヘッダー帯に重ならない。
14
16
  * 「{shopName}管理」のような文言合成は行わない(利用側が `brand` に組み立てて渡す)。
15
17
  *
16
18
  * ### インポート
@@ -39,6 +39,8 @@ export interface ChipProps extends React.ButtonHTMLAttributes<HTMLButtonElement>
39
39
  * - 売り切れタイル: `<Chip shape="square" size="tile" soldOut>5号</Chip>`
40
40
  * - カウント付き: `<Chip selected count={156}>すべて</Chip>`
41
41
  * - ステータスフィルター: Chip + count でステータス別件数タブを構成
42
+ *
43
+ * removable 時は本体(`data-slot="chip-trigger"`)と削除ボタンが兄弟の2タブストップ構造(ルートは `span[data-slot="chip"]`)。
42
44
  */
43
45
  declare function Chip({ className, variant, size, shape, href, selected, soldOut, removable, onRemove, count, children, ...props }: ChipProps): import("react/jsx-runtime").JSX.Element;
44
46
  export { Chip, chipVariants };
@@ -6,11 +6,23 @@ export interface FunnelStep {
6
6
  label: string;
7
7
  }
8
8
  export interface FunnelShellProps {
9
- /** ファネルのタイトル(集中ヘッダーのタイトル。例: 「ご購入手続き」) */
10
- title: string;
11
- /** 戻る導線のクリックハンドラ。離脱確認は利用側が onBack 内で行う想定 */
9
+ /**
10
+ * ヘッダーのロゴ(`CakeLogo` 等)。**基本形はこちら**。
11
+ * 渡すとヘッダーを `Header variant="logo-center"`(中央ロゴのみ)で描画する。
12
+ * ライブ本番の購入導線(/carts_v2/ = cart_layout.ctp の cartHeader)に準拠し、
13
+ * 戻る・タイトルを持たず離脱導線をロゴのみに絞る。`logo` と `title` は
14
+ * どちらか一方を渡す(`logo` が優先)。
15
+ */
16
+ logo?: React.ReactNode;
17
+ /**
18
+ * ファネルのタイトル(集中ヘッダーのタイトル。例: 「ご購入手続き」)。
19
+ * `logo` 未指定時の**代替形**(`Header variant="back"` の中央タイトル)。
20
+ * 多段申込などタイトル・戻るが要るファネル向け。`logo` 使用時は不要。
21
+ */
22
+ title?: string;
23
+ /** 戻る導線のクリックハンドラ(title 使用時)。離脱確認は利用側が onBack 内で行う想定 */
12
24
  onBack?: () => void;
13
- /** 戻るボタンのラベル */
25
+ /** 戻るボタンのラベル(title 使用時) */
14
26
  backLabel?: string;
15
27
  /**
16
28
  * 進捗インジケータのステップ定義(任意)。
@@ -27,7 +39,7 @@ export interface FunnelShellProps {
27
39
  /**
28
40
  * 下部固定アクションの slot(StickyActionBar 等を受ける)。
29
41
  * 渡された場合、本文が隠れないための下余白はシェルが管理する
30
- * (EcPageShell の bottomTab と同じ思想。ページ側で pb を書かない)。
42
+ * (StandardPageShell の bottomTab と同じ思想。ページ側で pb を書かない)。
31
43
  */
32
44
  bottomAction?: React.ReactNode;
33
45
  /** ルート要素の追加クラス */
@@ -39,14 +51,35 @@ export interface FunnelShellProps {
39
51
  * カート → お届け先 → 支払い → 確認 のような一直線の購入フローに集中させる骨格。
40
52
  * グローバルナビ・BottomTabBar・パンくずを構造的に持たない(離脱を誘う導線を置けなくする)。
41
53
  *
54
+ * ## なぜ購入導線は中央ロゴのヘッダーなのか(理由)
55
+ *
56
+ * 購入導線は **戻り・離脱をしづらくして途中離脱を抑制する** ため、グロナビ・戻る・
57
+ * タイトルを持たない中央ロゴのヘッダーを基本形にする。根拠は2つ:
58
+ *
59
+ * 1. **DS の Header の既定用途** — `Header` の docstring が
60
+ * `variant="logo-center": ロゴ中央配置(決済・申し込みページ用)` と規定している
61
+ * (src/components/primitives/header.tsx の `variant` prop)。決済・申込ページ向けの
62
+ * バリアントを購入導線でそのまま使う。
63
+ * 2. **ライブ本番の購入導線ヘッダー** — `www-test-htdocs/app/views/layouts/cart_layout.ctp`
64
+ * の cartHeader は中央ロゴのみで、ロゴクリックのリンク先も `/cart/` と thanks に限定
65
+ * (=カート/完了以外へは飛ばさず、離脱導線を最小化している)。本シェルはこの実挙動に
66
+ * 準拠する。
67
+ *
42
68
  * 設計上の約束:
43
- * - ヘッダーは既存 `Header`(variant="back")を使う。左上=戻る導線、中央=タイトル。
69
+ * - ヘッダーは既存 `Header` を使う。
70
+ * - **基本形=中央ロゴ**: `logo` を渡すと `Header variant="logo-center"`(中央ロゴのみ)で
71
+ * 描画する。ライブ本番の購入導線(cart_layout.ctp の cartHeader)準拠で、離脱導線は
72
+ * ロゴのみ(戻る・タイトルを持たない)=上記のとおり途中離脱の抑制が目的。
73
+ * - **代替形=back+title**: `logo` を渡さず `title` を渡すと `Header variant="back"`
74
+ * (左上=戻る・中央=タイトル)で描画する。多段申込などタイトル・戻るが要るファネル向け。
75
+ * - `logo` と `title` はどちらか一方を渡す(`logo` が優先)。両方無い場合はヘッダーを描画しない。
44
76
  * - 進捗インジケータ(`steps` / `activeStep`)は完了=Brand 色・現在=強調・未来=Low-Emphasis
45
- * の点+ラベルで表す。SP ではラベルを省略し点のみにする簡易レスポンシブ。
77
+ * で表す。各ステップはドット(上)+ラベル(下)の縦積みで、コネクタ線はドット中心の
78
+ * 高さで隣ステップ中心まで引く。ラベルは SP でも省略しない。
46
79
  * - `bottomAction` を渡すと本文の下余白はシェルが管理する(二重がけ/付け忘れの構造的防止)。
47
80
  *
48
- * 管理画面の集中編集は `WorkspaceLayout`(EC 購入導線=本コンポーネント)。
81
+ * 管理画面の集中編集は `WorkspaceShell`(EC 購入導線=本コンポーネント)。
49
82
  * 判断基準は contracts/screen-patterns.json(focused-workspace)を参照。
50
83
  */
51
- declare function FunnelShell({ title, onBack, backLabel, steps, activeStep, children, bottomAction, className, }: FunnelShellProps): import("react/jsx-runtime").JSX.Element;
84
+ declare function FunnelShell({ logo, title, onBack, backLabel, steps, activeStep, children, bottomAction, className, }: FunnelShellProps): import("react/jsx-runtime").JSX.Element;
52
85
  export { FunnelShell };
@@ -29,7 +29,7 @@ export interface SectionNavProps extends React.HTMLAttributes<HTMLElement> {
29
29
  * - チェブロン・矢印を**付けない**。「別ページへ遷移する」印象を与えず、
30
30
  * 同一画面内の位置移動であることを見た目で示す(aria-current="location")。
31
31
  * - 固有幅・背景・境界を持たない(`w-full`)。パネル化・幅決定はシェル/利用側の責務。
32
- * (SideNav の `w-64` 固定が WorkspaceLayout で幅ミスマッチを起こした反省)
32
+ * (SideNav の `w-64` 固定が WorkspaceShell で幅ミスマッチを起こした反省)
33
33
  * - IntersectionObserver は内包しない。`activeKey` を利用側が渡す。
34
34
  *
35
35
  * ### インポート
@@ -18,8 +18,26 @@ export interface SideNavGroup {
18
18
  items: SideNavItem[];
19
19
  }
20
20
  export interface SideNavProps extends React.HTMLAttributes<HTMLElement> {
21
- /** 現在アクティブなメニューの key */
21
+ /** 現在アクティブなメニューの key(完全一致)。`currentPath` / `isActive` 未指定時の既定判定。 */
22
22
  activeMenu?: string;
23
+ /**
24
+ * 現在の URL パス。指定すると各項目の `href` と照合してアクティブ項目を自動判定する
25
+ * (`activeMenu` より優先)。詳細ページや配下ページで `activeMenu` を手動指定する必要がなくなる。
26
+ */
27
+ currentPath?: string;
28
+ /**
29
+ * `currentPath` と `href` の照合方法(既定 `"exact"`)。
30
+ * - `"exact"`: `href === currentPath`
31
+ * - `"prefix"`: `currentPath` が `href` 配下(前方一致)。1 項目が配下ページ全体でアクティブになる
32
+ * (例: 「注文履歴」`/mypage/orders/` が `/mypage/orders/123/` でもアクティブ)。
33
+ * 複数項目が一致した場合は**最長 href の 1 項目のみ**アクティブにし、親子の二重アクティブを防ぐ。
34
+ */
35
+ activeMatch?: "exact" | "prefix";
36
+ /**
37
+ * アクティブ判定を完全に上書きする述語(最優先)。
38
+ * consumer 固有の URL 集約ロジック(複数 URL を 1 項目へ束ねる等)を注入する。
39
+ */
40
+ isActive?: (item: SideNavItem) => boolean;
23
41
  /** メニューグループ(必須) */
24
42
  groups: SideNavGroup[];
25
43
  /** aria-label */
@@ -55,8 +73,11 @@ export interface SideNavProps extends React.HTMLAttributes<HTMLElement> {
55
73
  * | Prop | 型 | デフォルト | 説明 |
56
74
  * |------|-----|-----------|------|
57
75
  * | groups | SideNavGroup[] | — | メニューグループ(必須) |
58
- * | activeMenu | string | — | アクティブなメニュー項目の key |
76
+ * | activeMenu | string | — | アクティブなメニュー項目の key(完全一致・後方互換) |
77
+ * | currentPath | string | — | 現在 URL。href と照合して自動判定(activeMenu より優先) |
78
+ * | activeMatch | "exact" \| "prefix" | "exact" | currentPath の照合方法。prefix は配下ページ全体でアクティブ |
79
+ * | isActive | (item) => boolean | — | アクティブ判定を上書きする述語(最優先) |
59
80
  * | ariaLabel | string | "サイドメニュー" | aria-label |
60
81
  */
61
- declare function SideNav({ activeMenu, groups, ariaLabel, className, ...props }: SideNavProps): import("react/jsx-runtime").JSX.Element;
82
+ declare function SideNav({ activeMenu, currentPath, activeMatch, isActive, groups, ariaLabel, className, ...props }: SideNavProps): import("react/jsx-runtime").JSX.Element;
62
83
  export { SideNav };
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- export interface EcPageShellProps {
2
+ export interface StandardPageShellProps {
3
3
  /**
4
4
  * ページ上端に固定するヘッダー。通常は DS の `Header`(variant="logo" / "back" 等)を渡す。
5
5
  * 未指定時はヘッダーなし(枠だけ)。
@@ -23,25 +23,29 @@ export interface EcPageShellProps {
23
23
  className?: string;
24
24
  }
25
25
  /**
26
- * EcPageShell — EC 標準ページ(standard-page-view / standard-page-edit)の骨格。
26
+ * StandardPageShell — 消費者向け標準ページ(standard-page-view / standard-page-edit)の骨格。
27
27
  *
28
28
  * `contracts/composition.json` の pageSkeletons(mobile / desktop)を構造的に保証する
29
29
  * 実装体。`min-h-dvh flex flex-col` の全高コンテナに、上端ヘッダー・伸縮する main・
30
30
  * 下部固定 BottomTabBar(SP のみ)・フッターを積む。
31
31
  *
32
+ * 名前はプロダクト・ドメインに依存しない(旧名 `EcPageShell` は deprecated alias として残置)。
33
+ * 骨格自体に EC 固有の要素は無く、Cake.jp の EC ページも求人検索(jobboard)の
34
+ * 「検索と結果の表示」のような消費者向けページも、同じこのシェルで組む。
35
+ *
32
36
  * 設計上の約束(あくまで「枠」— ページ固有の中身は焼き込まない):
33
- * - Cake.jp のロゴ・タブ項目・ナビ項目・文言を **一切内蔵しない**。それらは
37
+ * - プロダクトのロゴ・タブ項目・ナビ項目・文言を **一切内蔵しない**。それらは
34
38
  * 利用側が `header` / `bottomTab` に組み立てて渡す(ec 層が Cake.jp 既定値を束ねる役割)。
35
39
  * - `bottomTab` を渡すと main に BottomTabBar 分の下余白をシェルが付与する
36
40
  * (pb の付け忘れ/二重がけを構造的に防ぐ)。ページ側で pb-20 を書かない。
37
41
  * - 左右 padding は持たない。中身は Section(全幅背景帯)+ Container(中央寄せ・左右余白)で組む。
38
42
  *
39
43
  * 使い分け:
40
- * - 管理画面のシェルは `AdminLayout`。
41
- * - 複数情報をまたぐ集中編集は `WorkspaceLayout`。
44
+ * - 管理画面のシェルは `AdminShell`。
45
+ * - 複数情報をまたぐ集中編集は `WorkspaceShell`。
42
46
  * - マイページ配下の固有ページは `MypageShell`。
43
47
  *
44
48
  * 判断基準は contracts/composition.json(pageSkeletons)/ contracts/screen-patterns.json を参照。
45
49
  */
46
- declare function EcPageShell({ header, bottomTab, footer, children, className, }: EcPageShellProps): import("react/jsx-runtime").JSX.Element;
47
- export { EcPageShell };
50
+ declare function StandardPageShell({ header, bottomTab, footer, children, className, }: StandardPageShellProps): import("react/jsx-runtime").JSX.Element;
51
+ export { StandardPageShell };
@@ -1,5 +1,5 @@
1
1
  import * as React from "react";
2
- export interface WorkspaceLayoutProps {
2
+ export interface WorkspaceShellProps {
3
3
  /** 編集対象名(編集ヘッダーのタイトル) */
4
4
  title: string;
5
5
  /** 戻る導線のクリックハンドラ。未保存確認は利用側が onBack 内で行う想定 */
@@ -16,15 +16,25 @@ export interface WorkspaceLayoutProps {
16
16
  * 編集内のセクションナビ/ステップナビ(任意)。
17
17
  * PC(@md+)ではコンテンツ左のサイドに、SP では非表示にする。
18
18
  * 通常は `SectionNav`(ページ内アンカー移動専用)を渡す。ページ間遷移用の `SideNav` は流用しない。
19
+ *
20
+ * 注意: セクション数が少ない編集では、ページ遷移に見える左レールを置くより
21
+ * `asidePanel`(右メタパネル)だけを使う構成(Shopify 型)を推奨する。
19
22
  */
20
23
  sectionNav?: React.ReactNode;
24
+ /**
25
+ * コンテンツ右のメタ情報/上位アクションパネル(任意)。
26
+ * 公開状態・スケジュール・プレビュー等「編集そのものではない付帯情報と操作」を集約する。
27
+ * PC(@md+)では右に sticky 表示、SP ではメイン本体の下に縦積み。
28
+ * ページ内アンカーではないため、左レールのような「別ページ風」の誤認を生まない。
29
+ */
30
+ asidePanel?: React.ReactNode;
21
31
  /** 編集コンテンツ本体 */
22
32
  children: React.ReactNode;
23
33
  /** ルート要素の追加クラス */
24
34
  className?: string;
25
35
  }
26
36
  /**
27
- * WorkspaceLayout — Focused Workspace(全画面集中編集)のシェル。
37
+ * WorkspaceShell — Focused Workspace(全画面集中編集)のシェル。
28
38
  *
29
39
  * 複数情報をまたぐ複雑な編集に集中させるための骨格。
30
40
  * グローバルナビ・パンくずを構造的に持たない(集中を妨げる導線を置けなくする)。
@@ -34,9 +44,9 @@ export interface WorkspaceLayoutProps {
34
44
  * 右上=`primaryAction`(ワークスペース全体の上位アクションがある場合のみ)。
35
45
  * - `sectionNav` は編集内ナビのみ。グロナビは置かない。
36
46
  * - `sectionNav` は Surface-Secondary から浮いた独立パネルとして、シェル側で角丸パネルにラップされる。
37
- * - 標準的な編集は `AdminLayout`(Standard Page(Edit)/旧 Form Page)。複雑・集中編集・没入執筆のみ本コンポーネント。
47
+ * - 標準的な編集は `AdminShell`(Standard Page(Edit)/旧 Form Page)。複雑・集中編集・没入執筆のみ本コンポーネント。
38
48
  *
39
49
  * 判断基準は contracts/screen-patterns.json / guidelines/foundations/screen-patterns.md を参照。
40
50
  */
41
- declare function WorkspaceLayout({ title, onBack, backLabel, primaryAction, sectionNav, children, className, }: WorkspaceLayoutProps): import("react/jsx-runtime").JSX.Element;
42
- export { WorkspaceLayout };
51
+ declare function WorkspaceShell({ title, onBack, backLabel, primaryAction, sectionNav, asidePanel, children, className, }: WorkspaceShellProps): import("react/jsx-runtime").JSX.Element;
52
+ export { WorkspaceShell };
@@ -62,8 +62,16 @@ export { CategoryScroll } from "./components/primitives/category-scroll";
62
62
  export type { CategoryScrollProps, CategoryItem } from "./components/primitives/category-scroll";
63
63
  export { Chip, chipVariants } from "./components/primitives/chip";
64
64
  export type { ChipProps } from "./components/primitives/chip";
65
- export { EcPageShell } from "./components/primitives/ec-page-shell";
66
- export type { EcPageShellProps } from "./components/primitives/ec-page-shell";
65
+ export { StandardPageShell } from "./components/primitives/standard-page-shell";
66
+ export type { StandardPageShellProps } from "./components/primitives/standard-page-shell";
67
+ /**
68
+ * @deprecated 旧名。`StandardPageShell` を使うこと。
69
+ * この骨格は EC 専用ではなく、求人検索など消費者向けの標準ページ全般で使うため中立名に改称した。
70
+ * 次のメジャーで削除する。
71
+ */
72
+ export { StandardPageShell as EcPageShell } from "./components/primitives/standard-page-shell";
73
+ /** @deprecated 旧名。`StandardPageShellProps` を使うこと。次のメジャーで削除する。 */
74
+ export type { StandardPageShellProps as EcPageShellProps } from "./components/primitives/standard-page-shell";
67
75
  export { EmptyState } from "./components/primitives/empty-state";
68
76
  export { ErrorState } from "./components/primitives/error-state";
69
77
  export { FilterBar } from "./components/primitives/filter-bar";
@@ -97,9 +105,26 @@ export type { SideNavProps, SideNavGroup, SideNavItem } from "./components/primi
97
105
  export { SocialLoginButton } from "./components/primitives/social-login-button";
98
106
  export { StatusCountTabs } from "./components/primitives/status-count-tabs";
99
107
  export { Tag, tagVariants } from "./components/primitives/tag";
100
- export { WorkspaceLayout } from "./components/primitives/workspace-layout";
101
- export type { WorkspaceLayoutProps } from "./components/primitives/workspace-layout";
102
- export { AdminLayout, MissingComponent } from "./components/ec/admin-layout";
108
+ export { WorkspaceShell } from "./components/primitives/workspace-shell";
109
+ export type { WorkspaceShellProps } from "./components/primitives/workspace-shell";
110
+ /**
111
+ * @deprecated 旧名。`WorkspaceShell` を使うこと。
112
+ * `kind:"shell"` の一級概念・Shells セクションに合わせ、接尾辞を Shell に統一した。
113
+ * 次のメジャーで削除する。
114
+ */
115
+ export { WorkspaceShell as WorkspaceLayout } from "./components/primitives/workspace-shell";
116
+ /** @deprecated 旧名。`WorkspaceShellProps` を使うこと。次のメジャーで削除する。 */
117
+ export type { WorkspaceShellProps as WorkspaceLayoutProps } from "./components/primitives/workspace-shell";
118
+ export { AdminShell, MissingComponent } from "./components/ec/admin-shell";
119
+ export type { AdminShellProps } from "./components/ec/admin-shell";
120
+ /**
121
+ * @deprecated 旧名。`AdminShell` を使うこと。
122
+ * `kind:"shell"` の一級概念・Shells セクションに合わせ、接尾辞を Shell に統一した。
123
+ * 次のメジャーで削除する。
124
+ */
125
+ export { AdminShell as AdminLayout } from "./components/ec/admin-shell";
126
+ /** @deprecated 旧名。`AdminShellProps` を使うこと。次のメジャーで削除する。 */
127
+ export type { AdminShellProps as AdminLayoutProps } from "./components/ec/admin-shell";
103
128
  export { AnniversaryCard } from "./components/ec/anniversary-card";
104
129
  export { CakeLogo } from "./components/ec/cake-logo";
105
130
  export { ChartControls } from "./components/ec/chart-controls";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cakejp/design-system",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "type": "module",
5
5
  "description": "Cake.jp Design System — UI コンポーネント・カラートークン・タイポグラフィ",
6
6
  "license": "UNLICENSED",
@@ -35,6 +35,7 @@
35
35
  "CLAUDE.md",
36
36
  "CLAUDE_PRODUCTION.md",
37
37
  "MIGRATION.md",
38
+ "UPDATING.md",
38
39
  "bin",
39
40
  "contracts",
40
41
  "dist",
@@ -87,60 +88,43 @@
87
88
  "lint:reuse": "bash scripts/check-story-reuse.sh",
88
89
  "lint:border": "node scripts/check-border-color.mjs",
89
90
  "lint:docs": "bash scripts/check-docs-drift.sh",
91
+ "typecheck:stories": "tsc --noEmit -p tsconfig.stories.json",
90
92
  "generate:lint-rules": "node scripts/generate-lint-rules.mjs",
91
93
  "generate:lookup": "node scripts/generate-component-lookup.mjs",
92
- "check": "tsc --noEmit && bash scripts/check-deps.sh && bash scripts/check-drift.sh && bash scripts/check-docs-drift.sh && bash scripts/lint-scratch.sh && bash scripts/check-story-reuse.sh && bash scripts/check-responsive.sh && node scripts/check-border-color.mjs && bash scripts/lint-scratch.sh --components && bash scripts/check-generated-drift.sh",
94
+ "check": "tsc --noEmit -p tsconfig.app.json && npm run typecheck:stories && bash scripts/check-deps.sh && bash scripts/check-drift.sh && bash scripts/check-docs-drift.sh && bash scripts/lint-scratch.sh && bash scripts/check-story-reuse.sh && bash scripts/check-responsive.sh && node scripts/check-border-color.mjs && bash scripts/lint-scratch.sh --components && bash scripts/check-generated-drift.sh",
93
95
  "test": "vitest run --config vitest.config.ts"
94
96
  },
95
97
  "dependencies": {
96
98
  "class-variance-authority": "^0.7.1",
97
99
  "clsx": "^2.1.1",
98
- "tailwind-merge": "^3.5.0"
100
+ "cmdk": "^1.0.0",
101
+ "next-themes": "^0.4.0",
102
+ "react-day-picker": "^9.0.0",
103
+ "react-hook-form": "^7.0.0",
104
+ "sonner": "^2.0.0",
105
+ "tailwind-merge": "^3.5.0",
106
+ "vaul": "^1.0.0"
99
107
  },
100
108
  "peerDependencies": {
101
109
  "@hookform/resolvers": "^5.0.0",
102
- "cmdk": "^1.0.0",
103
110
  "date-fns": "^4.0.0",
104
111
  "iconsax-reactjs": "^0.0.8",
105
112
  "lucide-react": ">=0.400.0",
106
- "next-themes": "^0.4.0",
107
113
  "radix-ui": "^1.0.0",
108
114
  "react": "^18.0.0 || ^19.0.0",
109
- "react-day-picker": "^9.0.0",
110
115
  "react-dom": "^18.0.0 || ^19.0.0",
111
- "react-hook-form": "^7.0.0",
112
- "sonner": "^2.0.0",
113
116
  "tailwindcss": "^4.0.0",
114
- "vaul": "^1.0.0",
115
117
  "zod": "^4.0.0"
116
118
  },
117
119
  "peerDependenciesMeta": {
118
120
  "@hookform/resolvers": {
119
121
  "optional": true
120
122
  },
121
- "react-hook-form": {
122
- "optional": true
123
- },
124
123
  "zod": {
125
124
  "optional": true
126
125
  },
127
- "react-day-picker": {
128
- "optional": true
129
- },
130
126
  "date-fns": {
131
127
  "optional": true
132
- },
133
- "cmdk": {
134
- "optional": true
135
- },
136
- "next-themes": {
137
- "optional": true
138
- },
139
- "vaul": {
140
- "optional": true
141
- },
142
- "sonner": {
143
- "optional": true
144
128
  }
145
129
  },
146
130
  "devDependencies": {
package/src/preset.css CHANGED
@@ -32,6 +32,22 @@
32
32
  /* --- Dark mode variant --- */
33
33
  @custom-variant dark (&:is(.dark *));
34
34
 
35
+ /* --- Container query breakpoints ---
36
+ md / lg は本番(cakejp.css)の「切替段」に合わせる。xl は役割が違い、
37
+ DS が定める「コンテンツ上限段」(本番に対応する切替段は無い)。
38
+ Tailwind v4 既定の --container-md は 28rem(448px) で、本番の SP/PC 境界
39
+ (max-width:767px / min-width:768px)と大きくズレる。DS 内の @md: は
40
+ 「SP/PC の切り替え」の意図で使われているため 768px に再定義する。
41
+ @lg は本番の PC 中段(min-width:960px。既存の @[960px] 群と同じ意図)。
42
+ @xl は本番に対応する切替段が無い DS 独自の「コンテンツ上限段」
43
+ (ページコンテナの標準上限。1280px 以上では原則レイアウト変形を追加しない)。 */
44
+ @theme {
45
+ /* 正本の値は tokens.json(breakpoints)にも記載。変更時は両方を更新する。 */
46
+ --container-md: 48rem; /* 768px — SP/PC 境界(切替段。本番と一致) */
47
+ --container-lg: 60rem; /* 960px — PC 中段(切替段。本番と一致) */
48
+ --container-xl: 80rem; /* 1280px — コンテンツ上限段(DS 定義。本番の切替段ではない) */
49
+ }
50
+
35
51
  /* --- Theme: Tailwind integration --- */
36
52
  @theme inline {
37
53
  /* Radius */
@@ -36,18 +36,45 @@ DS に該当パターンが無い場合のみカスタム実装を許可。そ
36
36
 
37
37
  ### CSS のセットアップ(重要)
38
38
 
39
- DS のプリビルド CSS(`dist/index.css`)を**必ず**プロジェクトのエントリ CSS で
40
- `@import` すること。これにより consumer の Tailwind 設定に依存せず、DS と同じ
41
- 見た目が保証される。
39
+ #### ✅ 推奨(consumer が Tailwind v4 を使う場合): `@source` 単一ビルド方式
40
+
41
+ consumer のエントリ CSS で Tailwind を読み込み、`preset`(トークン・`typo-*`・
42
+ コンテナクエリ段・dark variant)を足したうえで、DS の className を **consumer と
43
+ 同じ Tailwind ビルド**でスキャン・生成させる。
44
+
45
+ ```css
46
+ /* globals.css / app.css など。@source のパスは この CSS ファイルからの相対で
47
+ node_modules/@cakejp/design-system/dist/index.js を指す */
48
+ @import "tailwindcss";
49
+ @import "@cakejp/design-system/preset"; /* トークン・typo-*・コンテナ段・dark variant */
50
+ @source "../node_modules/@cakejp/design-system/dist/index.js"; /* DS の className を consumer と同一ビルドで生成 */
51
+ ```
52
+
53
+ **なぜこれが推奨か:** ユーティリティのビルドが 1 つに統一されるため、Tailwind の
54
+ 「基底ユーティリティ→バリアント」の並び順が保証される。consumer が `.hidden` /
55
+ `.border-transparent` 等 DS と同名のユーティリティを 1 箇所でも使っても、DS の
56
+ コンテナクエリ・データ属性バリアント(`@lg:block`・
57
+ `group-data-[state=active]:border-…` 等)が同一 `@layer utilities` 内で正しく後勝ち
58
+ する。
59
+
60
+ > `@source` のパスは CSS ファイルからの相対。深さが違う場合は `../` の数を調整して
61
+ > 必ず `node_modules/@cakejp/design-system/dist/index.js` を指すこと。Tailwind v4 は
62
+ > 既定で `node_modules` をスキャンしないため、この明示 `@source` が要(かなめ)。
63
+
64
+ #### プリビルド CSS 方式(`dist/index.css`): **consumer が Tailwind を使わない場合のみ**
42
65
 
43
66
  ```css
44
- /* globals.css / app.css など */
45
67
  @import "@cakejp/design-system/dist/index.css"; /* DS のコンポーネントスタイル・トークン・preflight */
46
- @import "tailwindcss"; /* consumer 自身の utility */
47
68
  ```
48
69
 
49
- > ❌ `@source` ディレクティブで DS を再ビルドする方式は非推奨。consumer の
50
- > Tailwind 設定次第で出力がズレるリスクがある(トークン値の差・preflight の差等)。
70
+ > ⚠️ **consumer が Tailwind v4 を併用する構成でこの方式を使ってはいけない。**
71
+ > DS のプリビルド CSS と consumer の Tailwind は**独立した 2 つのビルド**で、同名
72
+ > ユーティリティ(`.hidden` 等)を別々に同じ `@layer utilities` へ二重出力する。
73
+ > 後段(consumer)の基底ルールが前段(DS)のバリアントルールを宣言順で打ち消し、
74
+ > **DS のバリアントが効かなくなる**。実害例: `Header` / `Footer` / `MenuDrawer` が
75
+ > デスクトップ幅でも永久にモバイル表示になる(consumer の `.hidden` が DS の
76
+ > `@lg:block` に後勝ちする)。import 順を入れ替えても解決しない。**Tailwind 併用時は
77
+ > 上の `@source` 方式を使うこと。**
51
78
 
52
79
  ### コンポーネントの使用
53
80