@qijenchen/design-system 0.1.0-beta.63 → 0.1.0-beta.65

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.
Files changed (62) hide show
  1. package/CLAUDE.md +1 -1
  2. package/dist/components/Checkbox/checkbox.d.ts.map +1 -1
  3. package/dist/components/Checkbox/checkbox.js +28 -3
  4. package/dist/components/Checkbox/checkbox.js.map +1 -1
  5. package/dist/components/PeoplePicker/person-display.d.ts.map +1 -1
  6. package/dist/components/PeoplePicker/person-display.js +1 -1
  7. package/dist/components/PeoplePicker/person-display.js.map +1 -1
  8. package/dist/components/RadioGroup/radio-group.d.ts +1 -1
  9. package/dist/components/RadioGroup/radio-group.d.ts.map +1 -1
  10. package/dist/components/RadioGroup/radio-group.js +46 -14
  11. package/dist/components/RadioGroup/radio-group.js.map +1 -1
  12. package/dist/components/Rating/rating.d.ts.map +1 -1
  13. package/dist/components/Rating/rating.js +5 -3
  14. package/dist/components/Rating/rating.js.map +1 -1
  15. package/dist/components/Slider/slider.d.ts +1 -1
  16. package/dist/components/Slider/slider.d.ts.map +1 -1
  17. package/dist/components/Slider/slider.js +11 -6
  18. package/dist/components/Slider/slider.js.map +1 -1
  19. package/dist/components/Switch/switch.d.ts +9 -7
  20. package/dist/components/Switch/switch.d.ts.map +1 -1
  21. package/dist/components/Switch/switch.js +30 -5
  22. package/dist/components/Switch/switch.js.map +1 -1
  23. package/dist/components/Tabs/tabs.d.ts.map +1 -1
  24. package/dist/components/Tabs/tabs.js +9 -3
  25. package/dist/components/Tabs/tabs.js.map +1 -1
  26. package/ds-canonical/hooks/check_consumer_app_invariants.sh +9 -0
  27. package/ds-canonical/references/story-baseline-registry.json +18 -2
  28. package/ds-canonical/references/ui-dev-rules.md +21 -0
  29. package/llms-full.txt +1 -1
  30. package/llms.txt +1 -1
  31. package/package.json +1 -1
  32. package/src/components/Accordion/accordion.spec.md +1 -1
  33. package/src/components/AppShell/app-shell.stories.tsx +3 -3
  34. package/src/components/Carousel/carousel.principles.stories.tsx +3 -3
  35. package/src/components/Checkbox/checkbox.spec.md +9 -1
  36. package/src/components/Checkbox/checkbox.tsx +45 -3
  37. package/src/components/Field/field-controls.spec.md +3 -1
  38. package/src/components/Field/field.anatomy.stories.tsx +3 -1
  39. package/src/components/Field/field.stories.tsx +14 -1
  40. package/src/components/PeoplePicker/person-display.tsx +4 -3
  41. package/src/components/ProgressBar/progress-bar.anatomy.stories.tsx +2 -2
  42. package/src/components/RadioGroup/radio-group.anatomy.stories.tsx +1 -1
  43. package/src/components/RadioGroup/radio-group.spec.md +2 -0
  44. package/src/components/RadioGroup/radio-group.tsx +59 -15
  45. package/src/components/Rating/rating.tsx +7 -3
  46. package/src/components/Sidebar/sidebar.spec.md +2 -0
  47. package/src/components/Slider/slider.anatomy.stories.tsx +2 -1
  48. package/src/components/Slider/slider.spec.md +8 -7
  49. package/src/components/Slider/slider.tsx +24 -11
  50. package/src/components/Switch/switch.anatomy.stories.tsx +4 -4
  51. package/src/components/Switch/switch.principles.stories.tsx +3 -3
  52. package/src/components/Switch/switch.spec.md +10 -6
  53. package/src/components/Switch/switch.tsx +45 -12
  54. package/src/components/Tabs/tabs.anatomy.stories.tsx +3 -3
  55. package/src/components/Tabs/tabs.principles.stories.tsx +1 -1
  56. package/src/components/Tabs/tabs.spec.md +4 -0
  57. package/src/components/Tabs/tabs.stories.tsx +4 -4
  58. package/src/components/Tabs/tabs.tsx +9 -3
  59. package/src/patterns/header-canonical/header-canonical.spec.md +1 -1
  60. package/src/styles/base.css +9 -2
  61. package/src/tokens/color/color.spec.md +7 -5
  62. package/src/tokens/color/semantic.css +5 -1
@@ -157,7 +157,7 @@ const TabsList = React.forwardRef<
157
157
  <TabsContext.Provider value={tabsSizeContext}>
158
158
  <TabsPrimitive.List
159
159
  ref={ref}
160
- className={cn(TABS_LIST_BASE, 'w-fit', className)}
160
+ className={cn(TABS_LIST_BASE, 'w-full', className)}
161
161
  {...props}
162
162
  >
163
163
  {children}
@@ -213,7 +213,7 @@ const ScrollTabsList = React.forwardRef<
213
213
  >
214
214
  <TabsPrimitive.List
215
215
  ref={ref}
216
- className={cn(TABS_LIST_BASE, 'w-fit', className)}
216
+ className={cn(TABS_LIST_BASE, 'min-w-full', className)}
217
217
  {...props}
218
218
  >
219
219
  {children}
@@ -309,7 +309,7 @@ const MenuTabsList = React.forwardRef<
309
309
  >
310
310
  <TabsPrimitive.List
311
311
  ref={ref}
312
- className={cn(TABS_LIST_BASE, 'w-fit', className)}
312
+ className={cn(TABS_LIST_BASE, 'min-w-full', className)}
313
313
  {...props}
314
314
  >
315
315
  {enhancedChildren}
@@ -481,6 +481,12 @@ const TabsContent = React.forwardRef<
481
481
  <TabsPrimitive.Content
482
482
  ref={ref}
483
483
  className={cn(
484
+ // 與 TabsList 的間距 canonical(2026-06-12 user 拍板):--layout-space-tight(md 12px,
485
+ // density 連動)。依 layoutSpace.spec「親疏 3 級」:Tabs↔Content 同 bundle(第一級,
486
+ // 元件 spec own),值取規則 3「直接功能依賴 = tight」精神(heading → labeled content 同類)。
487
+ // 收斂原 DS-wide 四種土法(無間距 / mt-4 / p-4 / pt-4 — M17 假 SSOT)。
488
+ // full-height 佈局(AppShell pane)用 className="mt-0" 覆寫(tailwind-merge)。
489
+ 'mt-[var(--layout-space-tight)]',
484
490
  'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1',
485
491
  className
486
492
  )}
@@ -69,7 +69,7 @@ benchmark:
69
69
  ### 4. Dismiss icon button(close X)
70
70
 
71
71
  - **Token**:`<Button iconOnly size="sm" dismiss />`(28px @ md / 32px @ lg)
72
- - **永遠 size="sm"**(不論家族 / density):chrome / overlay header 內 button 一律 sm
72
+ - **永遠 size="sm"**(不論家族 / density):chrome / overlay header 內 button 一律 sm。**廣化(2026-06-12 user 拍板)**:header 內**所有 field-height 控件**(Button / Input / Select / SegmentedControl / Combobox 等)一律 `sm`,禁混雜不同 field height(Tabs 跟齊 chrome 高度,唯一例外 = 「Tabs 取代整個 header」的 standalone `size="lg"`,見上方表)
73
73
  - 對齊 既有 `dialog.tsx:132-153` + `sheet.tsx:122-139` + `popover.tsx:87-110`(Dialog/Sheet/Popover 已內建 close X)
74
74
 
75
75
  ### 4.5 Chrome header avatar SSOT(2026-05-21 codify per user directive)
@@ -13,8 +13,15 @@
13
13
  * @import '@qijenchen/design-system/styles/base';
14
14
  */
15
15
 
16
- /* lucide 全域 stroke width */
17
- .lucide {
16
+ /* lucide 全域 stroke width — DS-wide icon 預設 1.75(比 lucide 原廠 2 輕一階的整體風格)。
17
+ ⚠️ 必須限定 [stroke-width="2"](= 沒被 component 顯式覆寫的 icon):
18
+ 2026-06-12 修 — 原寫法 `.lucide { ... }` 無條件蓋掉所有 explicit strokeWidth prop
19
+ (CSS class > SVG presentation attribute),導致 Checkbox/Switch/Steps/PeoplePicker
20
+ 的小尺寸 stroke 補償(strokeWidth 3 / 2.5)自 2026-04-08 起從未真正渲染
21
+ (rendered DOM 驗證:attr=3 但 computed=1.75px,實畫 0.80px vs 設計 1.50px)。
22
+ 限定後:lucide 預設(attr=2)→ 1.75;顯式 prop(3 / 2.5 / 1.75)→ attribute 直接生效。
23
+ 補償值 SSOT → .claude/references/ui-dev-rules.md「小尺寸 icon stroke 補償」 */
24
+ .lucide[stroke-width='2'] {
18
25
  stroke-width: 1.75;
19
26
  }
20
27
 
@@ -117,7 +117,7 @@ disabled 元件內的所有子元素必須呈現 disabled 狀態:
117
117
 
118
118
  | 策略 | 何時用 | 消費者 | 做法 |
119
119
  |---|---|---|---|
120
- | **灰階 token swap** | State 由形狀 / 位置 / icon / 文字 等**非顏色載體**承載,顏色只是美學 | Button、Checkbox、Input、Slider、Tag | 每個元素換到 disabled 對應的灰階 token(`bg-disabled` / `text-fg-disabled` / `border-fg-disabled` 等) |
120
+ | **灰階 token swap** | State 由形狀 / 位置 / icon / 文字 等**非顏色載體**承載,顏色只是美學 | Button、Checkbox、Input、Slider、Tag | 每個元素換到 disabled 對應的灰階 token(`bg-disabled` / `text-fg-disabled` / `bg-border` 等) |
121
121
  | **`opacity-disabled`** | State **完全只靠顏色區分**(形狀在 on/off 之間沒有差異),灰階化會丟失 state 辨識 | **Switch** | Root 層套 `opacity-disabled`,保留原有顏色身分,透過透明度均勻降級 |
122
122
 
123
123
  **具體判準(寫新元件時問自己)**:
@@ -133,14 +133,16 @@ disabled 元件內的所有子元素必須呈現 disabled 狀態:
133
133
 
134
134
  ### Disabled 視覺階層公式(多元素元件參考)
135
135
 
136
- 多元素互動元件(Slider、Progress、複合 Input 等)在 disabled 狀態常需要 3–4 階灰階深度來分層:
136
+ 多元素互動元件(Slider、Progress、複合 Input 等)在 disabled 狀態常需要 2–3 階灰階深度來分層:
137
137
 
138
138
  ```
139
- 底層背景 (n-2) < 中層填充 (n-5) < 輪廓邊框 (n-6) < 文字 (n-7+)
140
- bg-muted bg-border border-fg-disabled text-fg-disabled
139
+ 底層背景 (n-2) < 中層填充 / 輪廓 (n-5) < 文字 (n-6)
140
+ bg-muted bg-border / border-border text-fg-disabled
141
141
  ```
142
142
 
143
- 每階至少差 1 個 primitive step,使用者掃視時才能分清四個層。Slider 的 disabled 就是這個公式:track()< range(填充)< thumb border(輪廓)< label(文字)。
143
+ 每階至少差 1 個 primitive step,使用者掃視時才能分清層次。Slider 的 disabled 就是這個公式:track(底,n-2)< range 填充 = thumb 邊框(n-5,**同色**——「Range 色 = Thumb border 色」invariant,thumb 邊框是 range 的視覺延續,不論 state 永遠同色,詳 slider.tsx 註解)< label 文字(n-6)。
144
+
145
+ > 2026-06-12 修:本段原寫 4 階公式、輪廓層用 `border-fg-disabled`(n-6)、文字層標 n-7+——三者皆與 code 不符(`border-fg-disabled` 全 code 零使用且違反下方規則 3「border-* 一律從 border family 選」;`--fg-disabled` 實為 n-6;slider.tsx 的 range/thumb 邊框同色是刻意設計,曾踩 thumb 融入 track 的同色融色 bug)。對齊 code 真實。
144
146
 
145
147
  ### ⚠️ fg token 不可當 bg 用(跨 family 借用是 smell)
146
148
 
@@ -206,7 +206,11 @@
206
206
 
207
207
  /* Status: Info — 資訊狀態色
208
208
  目前指向 blue(與 primary 同源),但語義獨立——如未來 brand 改色,
209
- primary 跟著改,info 仍維持「資訊=藍」的通用慣例 */
209
+ primary 跟著改,info 仍維持「資訊=藍」的通用慣例。
210
+ ⚠️ 選取控件(Checkbox/Switch/Radio/Calendar selected)的 checked 藍 = --primary 非 --info:
211
+ 選取是「互動操作的 selected state」隨 brand 走(Material 3 CheckboxTokens
212
+ SelectedContainerColor=Primary / shadcn bg-primary / Ant colorPrimary 同款);
213
+ --info 只給資訊呈報(Alert/Badge/Toast info)。2026-06-12 codify per user 提問 */
210
214
  --info: var(--color-blue-6);
211
215
  --info-hover: var(--color-blue-5);
212
216
  --info-active: var(--color-blue-7);