@godxjp/ui 19.6.0 → 20.0.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.
Files changed (137) hide show
  1. package/dist/components/data-display/card.d.ts +2 -2
  2. package/dist/components/data-display/collapsible.d.ts +23 -4
  3. package/dist/components/data-display/collapsible.js +119 -4
  4. package/dist/components/data-display/index.d.ts +3 -1
  5. package/dist/components/data-display/index.js +2 -0
  6. package/dist/components/data-display/legend.d.ts +15 -0
  7. package/dist/components/data-display/legend.js +11 -0
  8. package/dist/components/data-display/list-row.js +1 -1
  9. package/dist/components/data-display/popover.d.ts +58 -5
  10. package/dist/components/data-display/popover.js +206 -27
  11. package/dist/components/data-display/progress.d.ts +50 -2
  12. package/dist/components/data-display/progress.js +57 -9
  13. package/dist/components/data-entry/calendar.d.ts +1 -1
  14. package/dist/components/data-entry/calendar.js +67 -32
  15. package/dist/components/data-entry/checkbox.d.ts +19 -6
  16. package/dist/components/data-entry/checkbox.js +55 -16
  17. package/dist/components/data-entry/choice-option.d.ts +1 -1
  18. package/dist/components/data-entry/date-range-picker.d.ts +1 -1
  19. package/dist/components/data-entry/field.js +0 -1
  20. package/dist/components/data-entry/form.js +1 -1
  21. package/dist/components/data-entry/label.d.ts +3 -2
  22. package/dist/components/data-entry/label.js +23 -10
  23. package/dist/components/data-entry/month-picker.d.ts +1 -1
  24. package/dist/components/data-entry/month-range-picker.d.ts +1 -1
  25. package/dist/components/data-entry/transfer.js +16 -6
  26. package/dist/components/data-entry/tree-select-strategy.d.ts +1 -1
  27. package/dist/components/data-entry/tree-select.js +29 -12
  28. package/dist/components/data-entry/tree-utils.d.ts +1 -1
  29. package/dist/components/data-entry/upload.js +7 -2
  30. package/dist/components/feedback/dialog.d.ts +105 -38
  31. package/dist/components/feedback/dialog.js +272 -194
  32. package/dist/components/feedback/overlay-close-focus.d.ts +31 -0
  33. package/dist/components/feedback/overlay-close-focus.js +31 -0
  34. package/dist/components/feedback/overlay-header-tone.d.ts +1 -1
  35. package/dist/components/feedback/sheet.d.ts +53 -11
  36. package/dist/components/feedback/sheet.js +150 -81
  37. package/dist/components/feedback/tooltip.d.ts +51 -7
  38. package/dist/components/feedback/tooltip.js +107 -25
  39. package/dist/components/general/button.js +2 -2
  40. package/dist/components/general/logo.d.ts +17 -0
  41. package/dist/components/general/logo.js +22 -16
  42. package/dist/components/layout/app-shell.d.ts +1 -1
  43. package/dist/components/layout/app-shell.js +52 -8
  44. package/dist/components/layout/aspect-ratio.js +0 -1
  45. package/dist/components/layout/auth-divider.js +0 -1
  46. package/dist/components/layout/flex.d.ts +1 -1
  47. package/dist/components/layout/flex.js +19 -2
  48. package/dist/components/layout/nav-surface.d.ts +26 -0
  49. package/dist/components/layout/nav-surface.js +17 -0
  50. package/dist/components/layout/org-switcher.d.ts +5 -1
  51. package/dist/components/layout/org-switcher.js +5 -3
  52. package/dist/components/layout/separator.js +0 -1
  53. package/dist/components/layout/sidebar.js +4 -1
  54. package/dist/components/layout/split-pane.d.ts +14 -1
  55. package/dist/components/layout/split-pane.js +26 -13
  56. package/dist/components/layout/topbar-item.js +1 -2
  57. package/dist/components/navigation/app-setting-picker.js +21 -2
  58. package/dist/components/navigation/app-setting-toggle.d.ts +16 -0
  59. package/dist/components/navigation/app-setting-toggle.js +96 -0
  60. package/dist/components/navigation/dropdown-menu.d.ts +199 -18
  61. package/dist/components/navigation/dropdown-menu.js +344 -117
  62. package/dist/components/navigation/index.d.ts +2 -0
  63. package/dist/components/navigation/index.js +2 -0
  64. package/dist/components/navigation/pagination-utils.d.ts +2 -1
  65. package/dist/components/navigation/tabs.d.ts +47 -6
  66. package/dist/components/navigation/tabs.js +152 -90
  67. package/dist/components/ui/accordion.d.ts +50 -5
  68. package/dist/components/ui/accordion.js +239 -33
  69. package/dist/components/ui/aspect-ratio.d.ts +23 -2
  70. package/dist/components/ui/aspect-ratio.js +15 -13
  71. package/dist/components/ui/avatar.d.ts +29 -4
  72. package/dist/components/ui/avatar.js +111 -25
  73. package/dist/components/ui/hover-card.d.ts +42 -4
  74. package/dist/components/ui/hover-card.js +183 -27
  75. package/dist/components/ui/label.js +0 -1
  76. package/dist/components/ui/segmented.d.ts +3 -3
  77. package/dist/components/ui/separator.d.ts +8 -2
  78. package/dist/components/ui/separator.js +17 -9
  79. package/dist/components/ui/toggle-group.d.ts +50 -5
  80. package/dist/components/ui/toggle-group.js +79 -20
  81. package/dist/components/ui/toggle.d.ts +31 -5
  82. package/dist/components/ui/toggle.js +42 -3
  83. package/dist/i18n/messages/en.json +8 -0
  84. package/dist/i18n/messages/ja.json +8 -0
  85. package/dist/i18n/messages/vi.json +8 -0
  86. package/dist/lib/control-styles.d.ts +1 -1
  87. package/dist/lib/control-styles.js +1 -1
  88. package/dist/lib/slot.d.ts +32 -0
  89. package/dist/lib/slot.js +22 -0
  90. package/dist/lib/variants.d.ts +22 -3
  91. package/dist/lib/variants.js +56 -1
  92. package/dist/props/components/app.prop.d.ts +25 -1
  93. package/dist/props/components/data-display.prop.d.ts +17 -0
  94. package/dist/props/components/data-entry.prop.d.ts +32 -4
  95. package/dist/props/components/index.d.ts +1 -1
  96. package/dist/props/components/layout.prop.d.ts +118 -5
  97. package/dist/props/components/navigation.prop.d.ts +1 -1
  98. package/dist/props/registry.d.ts +22 -2
  99. package/dist/props/registry.js +33 -2
  100. package/dist/props/vocabulary/content.prop.d.ts +1 -1
  101. package/dist/props/vocabulary/index.d.ts +2 -2
  102. package/dist/props/vocabulary/interaction.prop.d.ts +17 -1
  103. package/dist/props/vocabulary/layout.prop.d.ts +57 -1
  104. package/dist/styles/control.css +142 -1
  105. package/dist/styles/core.css +5 -2
  106. package/dist/styles/data-display-layout.css +72 -0
  107. package/dist/styles/focus-ring.css +4 -0
  108. package/dist/styles/index.css +5 -2
  109. package/dist/styles/layout.css +106 -0
  110. package/dist/styles/shell-layout.css +140 -8
  111. package/dist/styles/text-layout.css +5 -4
  112. package/dist/tokens/base.css +1 -1
  113. package/dist/tokens/components/data-display.css +11 -0
  114. package/dist/tokens/components/shell.css +3 -1
  115. package/dist/tokens/foundation.css +2 -0
  116. package/docs/COMPONENTS.md +9 -3
  117. package/docs/DESIGN-AUTHORITY.md +96 -71
  118. package/docs/FRAME-COVERAGE-REPORT.md +5 -3
  119. package/docs/README.md +14 -14
  120. package/docs/WHAT-BELONGS-HERE.md +179 -0
  121. package/docs/data-display/legend.tsx +145 -0
  122. package/docs/data-display/progress.tsx +32 -0
  123. package/docs/data-entry/segmented.tsx +1 -1
  124. package/docs/data-entry/select.tsx +2 -2
  125. package/docs/feedback/sheet.tsx +1 -1
  126. package/docs/layout/app-shell-arrangements.tsx +225 -0
  127. package/docs/layout/aspect-ratio.tsx +1 -1
  128. package/docs/navigation/app-setting-picker.tsx +26 -1
  129. package/docs/navigation/app-setting-toggle.tsx +111 -0
  130. package/package.json +11 -8
  131. package/scripts/_agent-setup.mjs +165 -3
  132. package/scripts/consumer-rule.md +98 -0
  133. package/scripts/guinea-pig-skill.md +322 -0
  134. package/scripts/init-guinea-pig.mjs +62 -0
  135. package/scripts/postinstall.mjs +13 -2
  136. package/scripts/ui-audit.mjs +115 -14
  137. /package/dist/tokens/{antd.generated.css → derived.css} +0 -0
@@ -27,6 +27,23 @@ export type ProseProp = {
27
27
  children?: ChildrenProp;
28
28
  };
29
29
  import type { ActionProp, ClassNameProp, DescriptionProp, IconProp, TitleProp, ColumnDefProp, GetRowIdProp, OnRowClickProp, OnSelectChangeProp, OnSortChangeProp, OnTableDensityChangeProp, SelectedIdsProp, SortStateProp, TableDensityProp, TablePresetProp, BreakpointProp, DensityProp, ChildrenProp, ToneProp, AvatarShapeProp, HeadingLevelProp, HandlerProp, SizeProp, LabelProp, IdProp, DescriptionsLayoutProp } from "../vocabulary/index.js";
30
+ /**
31
+ * One key in a `Legend`: a tone, and the words that tone stands for.
32
+ *
33
+ * `label` is required and there is no way to omit it. That is the point of a key — colour alone
34
+ * never carries meaning (WCAG 1.4.1), and a legend whose entries could be wordless would be a
35
+ * component that lets a caller build the exact failure it exists to prevent.
36
+ */
37
+ export type LegendItemProp = {
38
+ /** The tone this key explains — the SAME tone the marks it stands for are drawn in. */
39
+ tone: ToneProp;
40
+ label: LabelProp;
41
+ };
42
+ /** @see Legend — the key for a colour-coded surface: a breakdown bar, a chart, a status column. */
43
+ export type LegendProp = Omit<React.HTMLAttributes<HTMLUListElement>, "children"> & {
44
+ items: LegendItemProp[];
45
+ className?: ClassNameProp;
46
+ };
30
47
  /** @see EmptyState */
31
48
  /**
32
49
  * Semantic intent of the EmptyState icon medallion — a subset of the shared `ToneProp` vocabulary
@@ -8,7 +8,7 @@ import type { DateRange } from "react-day-picker";
8
8
  import type * as React from "react";
9
9
  import type { UploadFileItem } from "../../components/data-entry/upload-types.js";
10
10
  import type { FieldA11yProps } from "../../lib/field-a11y.js";
11
- import type { ClassNameProp, DisabledProp, EmptyMessageProp, ErrorBagProp, ErrorProp, HelperProp, IdProp, LabelProp, NameProp, OnValueChangeProp, OnSearchChangeProp, OpenProp, OnOpenChangeProp, PlaceholderProp, RequiredProp, ValueProp, DefaultValueProp, FormLayoutProp, WidthProp, BreakpointProp, DensityProp, SizeProp, TitleProp } from "../vocabulary/index.js";
11
+ import type { ClassNameProp, ControlWidthProp, DisabledProp, EmptyMessageProp, ErrorBagProp, ErrorProp, HelperProp, IdProp, LabelProp, NameProp, OnValueChangeProp, OnSearchChangeProp, OpenProp, OnOpenChangeProp, PlaceholderProp, RequiredProp, ValueProp, DefaultValueProp, FormLayoutProp, WidthProp, BreakpointProp, DensityProp, SizeProp, TitleProp } from "../vocabulary/index.js";
12
12
  import type { ResponsiveGridColumnsProp } from "./layout.prop.js";
13
13
  /** One-outline-per-group appearance for the compound InputOTP control. */
14
14
  export type InputOTPGroupAppearanceProp = "slots" | "grouped";
@@ -228,7 +228,7 @@ export type SearchInputProp = FieldA11yProps & {
228
228
  };
229
229
  /** @see Checkbox — extends Radix checkbox root props. */
230
230
  export type CheckboxProp = React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>;
231
- /** Shared option row — Ant Design `CheckboxOptionType`. */
231
+ /** Shared option row — the conventional `CheckboxOptionType` shape. */
232
232
  export type ChoiceOptionProp = {
233
233
  label: React.ReactNode;
234
234
  value: string;
@@ -283,6 +283,34 @@ export type SliderProp = React.ComponentPropsWithoutRef<typeof SliderPrimitive.R
283
283
  export type CalendarProp = DayPickerProps & CalendarFooterProp & {
284
284
  /** Replaces the built-in footer actions. */
285
285
  footer?: React.ReactNode;
286
+ /**
287
+ * How the grid claims horizontal space. Default `auto` shrink-wraps to seven fixed day
288
+ * columns — the shape a picker popover needs, because the panel is shrink-to-fit and takes
289
+ * ITS width from the calendar inside it.
290
+ *
291
+ * `full` is for an EMBEDDED calendar — a shift board, a booking month — where the calendar is
292
+ * the content of a card rather than a dropdown. It stacks the months, lets each one grow, and
293
+ * lets the day cells share the row.
294
+ *
295
+ * Opt-in on purpose, and the default is load-bearing: making the calendar fluid globally was
296
+ * measured to collapse the DatePicker popover from 250px to 157.8px with 18.8px day cells.
297
+ * `Calendar` and `DatePicker` want opposite answers here, which is why the enterprise
298
+ * libraries split them too
299
+ * (`Calendar fullscreen` is 100% of its container; the DatePicker dropdown is a fixed 288px).
300
+ */
301
+ width?: Extract<ControlWidthProp, "auto" | "full">;
302
+ /**
303
+ * Rule the grid: one border per day cell, weekday header included.
304
+ *
305
+ * NOT a box around the calendar — that is what `Card` is for, and nesting one inside a section
306
+ * card was measured on a real page as two rounded edges 16px apart with both paddings stacked.
307
+ * What a month grid needs is the ruling BETWEEN days, so a week reads as a row of cells the
308
+ * eye can track across.
309
+ *
310
+ * Default `false`, because a picker popover wants the opposite: floating day buttons with no
311
+ * ruling, so the selected day is the only shape in the panel.
312
+ */
313
+ bordered?: boolean;
286
314
  };
287
315
  /** Footer actions shared by Calendar and the pickers that embed it. Both default to off. */
288
316
  export type CalendarFooterProp = {
@@ -430,10 +458,10 @@ export type SearchSelectProp = {
430
458
  /** Remote fetcher — debounced search + infinite-scroll pagination call into this. Provide this
431
459
  * OR `options`. */
432
460
  loadOptions?: (params: SearchSelectLoadParamsProp) => Promise<SearchSelectLoadResultProp>;
433
- /** Custom per-option renderer (Ant-Design style). Defaults to label + optional sublabel. */
461
+ /** Custom per-option renderer. Defaults to label + optional sublabel. */
434
462
  renderOption?: (option: SearchSelectOptionProp) => React.ReactNode;
435
463
  /**
436
- * Custom renderer for the SELECTED value shown on the trigger (Ant Design `labelRender`).
464
+ * Custom renderer for the SELECTED value shown on the trigger (the conventional `labelRender`).
437
465
  * Receives the value, the resolved label, and the full option when it is loaded (undefined for
438
466
  * an async preset whose page hasn't arrived).
439
467
  */
@@ -6,5 +6,5 @@ export type { ChartDatum, ChartSeriesProp, LineChartProp, BarChartProp, AreaChar
6
6
  export type { AlertQueryErrorProp, AlertProp, AlertTitleProp, AlertContentProp, AlertDescriptionProp, AlertActionsProp, SheetResponsiveProp, SkeletonRowsProp, } from "./feedback.prop.js";
7
7
  export type { DataStateProp, InfiniteQueryStateProp, InfiniteQueryHelpers, PrefetchLinkProp, } from "./query.prop.js";
8
8
  export type { PaginationProp, StepsProp, StepItemProp, StepStatusProp, TabsProp, TabItemProp, } from "./navigation.prop.js";
9
- export type { AppProviderProp, AppContextValue, AppSettingKind, AppSettingPickerProp, } from "./app.prop.js";
9
+ export type { AppProviderProp, AppContextValue, AppSettingKind, AppSettingPickerProp, AppSettingToggleKind, AppSettingToggleProp, } from "./app.prop.js";
10
10
  export type { ZodSchemaProp, UseZodFormOptionsProp, UseZodFormReturnProp, FormRootProp, FormFieldControlProp, FieldErrorMessageProp, } from "./form.prop.js";
@@ -1,7 +1,7 @@
1
1
  /** Layout component prop types — @see docs/COMPONENTS.md#layout */
2
2
  import type * as React from "react";
3
3
  import type { ComponentType, ReactNode, SVGProps } from "react";
4
- import type { BreadcrumbProp, TitleProp, SubtitleProp, StatusProp, ExtraProp, FooterProp, PageDensityProp, PageContainerVariantProp, CenteredShellWidthProp, CenteredShellAlignProp, CenteredShellPresetProp, ErrorSurfaceModeProp, ErrorSurfaceStatusProp, AuthShellPresetProp, MobileShellHeightProp, OrientationProp, TextAlignProp, TextToneProp, BreakpointProp, GapProp, ClassNameProp, ChildrenProp, IdProp, DisabledProp, DescriptionProp, ActionProp, IconProp, HeadingLevelProp, ToneProp } from "../vocabulary/index.js";
4
+ import type { BreadcrumbProp, TitleProp, SubtitleProp, StatusProp, ExtraProp, FooterProp, PageDensityProp, PageContainerVariantProp, CenteredShellWidthProp, CenteredShellAlignProp, CenteredShellPresetProp, ErrorSurfaceModeProp, ErrorSurfaceStatusProp, AuthShellPresetProp, MobileShellHeightProp, OrientationProp, TextAlignProp, TextToneProp, BreakpointProp, GapProp, PadProp, PadRawProp, ClassNameProp, ChildrenProp, IdProp, DisabledProp, DescriptionProp, ActionProp, IconProp, HeadingLevelProp, ToneProp, WidthProp } from "../vocabulary/index.js";
5
5
  import type { EmptyStateToneProp } from "./data-display.prop.js";
6
6
  /**
7
7
  * Arrangement of the page header's title band and its `extra` slot below the 640px step.
@@ -112,6 +112,55 @@ export type FlexProp = React.HTMLAttributes<HTMLDivElement> & {
112
112
  as?: "div" | "span";
113
113
  direction?: FlexDirectionProp;
114
114
  gap?: GapProp;
115
+ /**
116
+ * CỬA THOÁT: một khoảng cách tính bằng pixel, ngoài mọi bậc của thang.
117
+ *
118
+ * ## Vì sao một design system lại mở cửa thoát
119
+ *
120
+ * Vì bịt nó lại không làm thiết kế biến mất — nó chỉ làm cách làm ĐÚNG trở
121
+ * thành bất hợp pháp. Một bản thiết kế thật dùng 2px, 5px, 6px, 10px; thang
122
+ * gốc không có bậc nào như thế. Người viết mã khi ấy có ba nước, và cả ba
123
+ * đều tệ: làm tròn xuống bậc gần nhất (lệch bố cục, và "gần nhất" giữa hai
124
+ * số cách đều vốn đã là một phép đoán), viết literal (audit chặn), hoặc mở
125
+ * issue ngược lên rồi CHỜ. Đó là lý do mọi dự án đều lệch design — không
126
+ * phải người viết cẩu thả.
127
+ *
128
+ * ## Cái giá của nó
129
+ *
130
+ * Nó phát ra `data-gap-raw` lên DOM. Đó không phải trang trí: nó làm mỗi lần
131
+ * thoát trở nên ĐẾM ĐƯỢC — grep mã nguồn hoặc quét DOM đều ra, nên một kho
132
+ * đang trôi dần khỏi thang sẽ tự lộ ra bằng con số thay vì bằng cảm giác.
133
+ *
134
+ * ## Khi nào ĐỪNG dùng
135
+ *
136
+ * Khi giá trị bạn cần có trong thang. `gap={3}` là 12px và nó đọc theo
137
+ * `--scaling` của người dùng; `gapRaw={12}` thì không, nó đứng yên khi người
138
+ * ta phóng to giao diện. Thang có mười bậc — hãy tiêu hết chúng trước.
139
+ *
140
+ * Khi có mặt, nó THẮNG `gap`, và `gap` không phát lớp nào nữa để hai bên
141
+ * không tranh độ đặc hiệu.
142
+ */
143
+ gapRaw?: number;
144
+ /**
145
+ * Đệm TRONG, theo thang token. Nhận một bậc cho cả bốn cạnh, hoặc một object
146
+ * theo cạnh LOGIC (`inline`, `block`, `inlineStart`, `blockEnd`…).
147
+ *
148
+ * Vì sao có: chạy `ui-audit` trên consumer thật (godx-chat, 08/09/2026) ra
149
+ * **42 trong 51 lỗi** là `no-utility-spacing`, và gần như tất cả xin cùng
150
+ * một thứ — padding. `<Flex className="p-3">` không phải cẩu thả; đó là nước
151
+ * đi duy nhất còn lại khi primitive không có prop đệm. Một prop thiếu đẻ ra
152
+ * 42 lỗi (gh#408).
153
+ */
154
+ pad?: PadProp;
155
+ /**
156
+ * Đệm bằng pixel THÔ, cho giá trị ngoài thang — cùng lý do và cùng cái giá
157
+ * với `gapRaw`: nó để lại `data-pad-raw` trên DOM nên mỗi lần thoát đều đếm
158
+ * được. Đo trên 51 lỗi ấy: thiết kế cần 2px, 6px, 10px, 14px, 44px, không
159
+ * bậc nào có.
160
+ *
161
+ * Ghi đè `pad` ở TỪNG CẠNH, không phải cả cụm.
162
+ */
163
+ padRaw?: PadRawProp;
115
164
  align?: FlexAlignProp;
116
165
  justify?: FlexJustifyProp;
117
166
  wrap?: boolean;
@@ -126,6 +175,31 @@ export type FlexProp = React.HTMLAttributes<HTMLDivElement> & {
126
175
  * only on the narrow side (a compact-only affordance). Omit for no attribute and no rule.
127
176
  */
128
177
  hideFrom?: BreakpointProp;
178
+ /**
179
+ * Take the space the siblings leave — the Flex becomes the row's ELASTIC column.
180
+ *
181
+ * ## Vì sao là một trục, không phải một tiện ích
182
+ *
183
+ * Một hàng thật gần như luôn có hình `cố định | co giãn | cố định`: tên bên trái, thước đo ở
184
+ * giữa, con số bên phải. Không có trục này thì nước đi duy nhất là `className="flex-1 min-w-0"`
185
+ * — mà `ui-audit` chặn `no-utility-spacing`, nên cách làm ĐÚNG lại là cách bất hợp pháp.
186
+ * `PageContainer` đã có `fill` với đúng nghĩa ấy; `Flex` không có là bất đối xứng, không phải
187
+ * quyết định (gh#405 §2).
188
+ *
189
+ * Nó kèm luôn `min-inline-size: 0`. Đó không phải chi tiết thừa: một flex item mặc định không
190
+ * co nhỏ hơn nội dung, nên một `Text truncate` bên trong sẽ ĐẨY hàng rộng ra thay vì cắt bớt.
191
+ */
192
+ fill?: boolean;
193
+ /**
194
+ * Bề rộng CỐ ĐỊNH của một cột trong hàng — số là px, chuỗi là mọi CSS length (`"12rem"`, `"40%"`).
195
+ *
196
+ * Đi kèm `flex: none`. Một `inline-size` mà sibling vẫn bóp được thì không phải cột, nó chỉ là
197
+ * một đề nghị — và sáu thanh xếp dọc dưới nhau sẽ bắt đầu ở sáu toạ độ x khác nhau.
198
+ *
199
+ * Nó để lại `data-width-raw` trên DOM, cùng lý do với `gapRaw`/`padRaw`: mỗi số đo cứng viết ở
200
+ * call site đều ĐẾM ĐƯỢC, nên một kho đang trôi khỏi thang tự lộ ra bằng con số.
201
+ */
202
+ width?: WidthProp;
129
203
  };
130
204
  /** Container column counts; omitted steps inherit from the previous step. Base defaults to 1. */
131
205
  export type ResponsiveGridColumnsProp = number | {
@@ -213,11 +287,50 @@ export type AppShellProp = {
213
287
  * belonging to it.
214
288
  */
215
289
  topbarSpan?: "content" | "full";
290
+ /**
291
+ * A SECOND navigation column, narrower than `sidebar` and placed before it — the
292
+ * workspace/organization switcher shape (Slack, Teams, Discord). Passing a node adds the track;
293
+ * omitting it leaves the two-column shell exactly as it was. Width is
294
+ * `--app-shell-nav-rail-width` (3.5rem — deliberately NOT the collapsed sidebar's 4rem: at equal
295
+ * widths the two navigation tracks fuse into one block the moment the sidebar collapses).
296
+ *
297
+ * THE THREE COLUMNS ARE THREE SCOPES, and the scope — not the free space — is what decides where
298
+ * a control goes. The rail is PLATFORM scope: whatever is true across every app in the
299
+ * organization (which organization, which app, notifications, messages, events, organization
300
+ * settings, cross-app shortcuts). The sidebar is APP scope: this app's own sections. The topbar
301
+ * is PAGE scope: where you are and what you can do here.
302
+ *
303
+ * So app navigation never goes in the rail, a platform switch never goes in the sidebar, and a
304
+ * destination that would fit both belongs to the rail — because it survives changing apps. A
305
+ * rail that repeats the sidebar's own entries is a second chrome band carrying the first one's
306
+ * rank, just vertical instead of horizontal.
307
+ *
308
+ * Orthogonal to `topbarSpan`: the rail says how many navigation COLUMNS there are, `topbarSpan`
309
+ * says how far the BAR reaches, and every combination of the two is a real shape, so they never
310
+ * need to be reconciled. `sidebarCollapsed` folds the sidebar track only — the rail keeps its
311
+ * width, which is what keeps its destinations reachable while collapsed.
312
+ *
313
+ * Building this by hand inside the single `sidebar` slot is the trap it replaces: `Sidebar`
314
+ * renders `.sb-root { display: contents }`, so two of them dropped side by side dissolve into
315
+ * one flex row and both collapse to zero unless each is separately wrapped — and sizing the one
316
+ * available track for two columns means overriding `--app-shell-sidebar-width`, which is how a
317
+ * shipped consumer moved its content edge by 64px between routes.
318
+ */
319
+ navRail?: ReactNode;
320
+ /**
321
+ * Accessible name for the `navRail` landmark. Defaults to the localized "Workspaces".
322
+ *
323
+ * The rail and the sidebar are two `complementary` landmarks on one page, so ARIA requires them
324
+ * to be tellable apart by name; the shell always supplies both defaults rather than requiring
325
+ * this prop, so the two columns of equal rank behave the same way.
326
+ */
327
+ navRailLabel?: string;
216
328
  /**
217
329
  * Navigation shown in the mobile drawer at the DXS 900px breakpoint, where the docked sidebar is
218
- * hidden. Defaults to `sidebar`, so the same nav is available on mobile with no extra wiring;
219
- * pass a distinct node for a mobile-tailored menu, or `null` to opt out (only when navigation
220
- * lives elsewhere, e.g. a bottom bar).
330
+ * hidden. Defaults to `navRail` followed by `sidebar` both docked columns are hidden at that
331
+ * width, so a default of `sidebar` alone would silently strip every app-level destination the
332
+ * rail carries. Pass a distinct node for a mobile-tailored menu, or `null` to opt out (only when
333
+ * navigation lives elsewhere, e.g. a bottom bar).
221
334
  */
222
335
  mobileNav?: ReactNode;
223
336
  /** Accessible title for the mobile navigation drawer. Defaults to the localized "Menu". */
@@ -842,7 +955,7 @@ export type TopbarProp = Omit<React.HTMLAttributes<HTMLDivElement>, "children">
842
955
  * It exists because the alternative is a `Button`, and a Button in a bar is a control that landed
843
956
  * in the bar rather than a part of it — a pill of its own height floating in a taller strip, with
844
957
  * its own hover surface and its own focus ring drawn around that pill. Fluent, SLDS, Atlassian and
845
- * antd's ProLayout all draw a top-bar trigger the other way: the cell is as tall as the bar, its
958
+ * and enterprise pro-layouts all draw a top-bar trigger the other way: the cell is as tall as the bar, its
846
959
  * hover is the bar's own surface, and the focus mark is hosted INSIDE the cell because a
847
960
  * full-bleed cell has nothing outside itself to ring.
848
961
  */
@@ -168,7 +168,7 @@ export type StepsProp = {
168
168
  };
169
169
  /** @see Steps — inline separator glyph. */
170
170
  export type StepsSeparatorProp = "chevron" | "arrow";
171
- /** Tab pane — Ant Design `items` entry. */
171
+ /** Tab pane — the conventional `items` entry. */
172
172
  export type TabItemProp = {
173
173
  value: string;
174
174
  label: React.ReactNode;
@@ -289,6 +289,11 @@ export declare const VOCABULARY_REGISTRY: {
289
289
  readonly category: "interaction";
290
290
  readonly description: "AppSettingPicker trigger presentation: labeled (icon + value) | icon (square icon-only topbar trigger) | inline (compact text footer trigger)";
291
291
  };
292
+ readonly AppSettingToggleAppearanceProp: {
293
+ readonly file: "vocabulary/interaction.prop.ts";
294
+ readonly category: "interaction";
295
+ readonly description: "AppSettingToggle box: bar (default — a full-height CELL of the bar, TopbarItem shape) | icon (square --control-height ghost button for anywhere that is not a bar)";
296
+ };
292
297
  readonly ShapeProp: {
293
298
  readonly file: "vocabulary/interaction.prop.ts";
294
299
  readonly category: "interaction";
@@ -491,6 +496,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
491
496
  readonly reason: "Trigger DENSITY for the picker only (sm control tier + content-hugging width) — orthogonal to `appearance`, and not the page-level DensityProp scope.";
492
497
  }];
493
498
  };
499
+ readonly AppSettingToggleProp: {
500
+ readonly group: "app";
501
+ readonly file: "components/app.prop.ts";
502
+ readonly vocabulary: readonly ["ValueProp", "OnValueChangeProp", "DisabledProp", "IdProp", "ClassNameProp", "AppSettingToggleAppearanceProp"];
503
+ };
494
504
  readonly PageContainerHeaderLayoutProp: {
495
505
  readonly group: "layout";
496
506
  readonly file: "components/layout.prop.ts";
@@ -1057,7 +1067,7 @@ export declare const COMPONENT_PROP_REGISTRY: {
1057
1067
  readonly CalendarProp: {
1058
1068
  readonly group: "data-entry";
1059
1069
  readonly file: "components/data-entry.prop.ts";
1060
- readonly vocabulary: readonly [];
1070
+ readonly vocabulary: readonly ["ControlWidthProp"];
1061
1071
  };
1062
1072
  readonly CalendarFooterProp: {
1063
1073
  readonly group: "data-entry";
@@ -1771,7 +1781,17 @@ export declare const COMPONENT_PROP_REGISTRY: {
1771
1781
  readonly ProgressProp: {
1772
1782
  readonly group: "data-display";
1773
1783
  readonly file: "components/data-display/progress.tsx";
1774
- readonly vocabulary: readonly ["ValueProp", "LabelProp", "ClassNameProp"];
1784
+ readonly vocabulary: readonly ["ValueProp", "LabelProp", "ToneProp", "ClassNameProp"];
1785
+ };
1786
+ readonly LegendItemProp: {
1787
+ readonly group: "data-display";
1788
+ readonly file: "components/data-display.prop.ts";
1789
+ readonly vocabulary: readonly ["ToneProp", "LabelProp"];
1790
+ };
1791
+ readonly LegendProp: {
1792
+ readonly group: "data-display";
1793
+ readonly file: "components/data-display.prop.ts";
1794
+ readonly vocabulary: readonly ["ClassNameProp"];
1775
1795
  };
1776
1796
  readonly CodeBlockProp: {
1777
1797
  readonly group: "data-display";
@@ -288,6 +288,11 @@ const VOCABULARY_REGISTRY = {
288
288
  category: "interaction",
289
289
  description: "AppSettingPicker trigger presentation: labeled (icon + value) | icon (square icon-only topbar trigger) | inline (compact text footer trigger)"
290
290
  },
291
+ AppSettingToggleAppearanceProp: {
292
+ file: "vocabulary/interaction.prop.ts",
293
+ category: "interaction",
294
+ description: "AppSettingToggle box: bar (default \u2014 a full-height CELL of the bar, TopbarItem shape) | icon (square --control-height ghost button for anywhere that is not a bar)"
295
+ },
291
296
  ShapeProp: {
292
297
  file: "vocabulary/interaction.prop.ts",
293
298
  category: "interaction",
@@ -495,6 +500,18 @@ const COMPONENT_PROP_REGISTRY = {
495
500
  }
496
501
  ]
497
502
  },
503
+ AppSettingToggleProp: {
504
+ group: "app",
505
+ file: "components/app.prop.ts",
506
+ vocabulary: [
507
+ "ValueProp",
508
+ "OnValueChangeProp",
509
+ "DisabledProp",
510
+ "IdProp",
511
+ "ClassNameProp",
512
+ "AppSettingToggleAppearanceProp"
513
+ ]
514
+ },
498
515
  PageContainerHeaderLayoutProp: {
499
516
  group: "layout",
500
517
  file: "components/layout.prop.ts",
@@ -1204,7 +1221,11 @@ const COMPONENT_PROP_REGISTRY = {
1204
1221
  file: "components/data-entry.prop.ts",
1205
1222
  vocabulary: ["DisabledProp"]
1206
1223
  },
1207
- CalendarProp: { group: "data-entry", file: "components/data-entry.prop.ts", vocabulary: [] },
1224
+ CalendarProp: {
1225
+ group: "data-entry",
1226
+ file: "components/data-entry.prop.ts",
1227
+ vocabulary: ["ControlWidthProp"]
1228
+ },
1208
1229
  CalendarFooterProp: {
1209
1230
  group: "data-entry",
1210
1231
  file: "components/data-entry.prop.ts",
@@ -1983,7 +2004,17 @@ const COMPONENT_PROP_REGISTRY = {
1983
2004
  ProgressProp: {
1984
2005
  group: "data-display",
1985
2006
  file: "components/data-display/progress.tsx",
1986
- vocabulary: ["ValueProp", "LabelProp", "ClassNameProp"]
2007
+ vocabulary: ["ValueProp", "LabelProp", "ToneProp", "ClassNameProp"]
2008
+ },
2009
+ LegendItemProp: {
2010
+ group: "data-display",
2011
+ file: "components/data-display.prop.ts",
2012
+ vocabulary: ["ToneProp", "LabelProp"]
2013
+ },
2014
+ LegendProp: {
2015
+ group: "data-display",
2016
+ file: "components/data-display.prop.ts",
2017
+ vocabulary: ["ClassNameProp"]
1987
2018
  },
1988
2019
  CodeBlockProp: {
1989
2020
  group: "data-display",
@@ -14,7 +14,7 @@ export type DescriptionProp = React.ReactNode;
14
14
  * Owned by the canonical page-header contract so consumers never hand-lay a badge row.
15
15
  */
16
16
  export type StatusProp = React.ReactNode;
17
- /** Top-right action slot on pages (Ant Design `extra`). */
17
+ /** Top-right action slot on pages (the conventional `extra` slot). */
18
18
  export type ExtraProp = React.ReactNode;
19
19
  /** Bottom action bar on pages — save/cancel, pagination controls. */
20
20
  export type FooterProp = React.ReactNode;
@@ -1,7 +1,7 @@
1
1
  /** Barrel — all vocabulary prop types. */
2
2
  export type { ClassNameProp, ChildrenProp, IdProp, OpenProp, DefaultOpenProp, OnOpenChangeProp, HandlerProp, PendingProp, RequiredProp, DisabledProp, LabelProp, HelperProp, ErrorProp, ErrorBagProp, PlaceholderProp, NameProp, ValueProp, DefaultValueProp, OnValueChangeProp, OnChangeProp, OnClickProp, AsChildProp, FlushProp, WidthProp, ControlWidthProp, } from "./shared.prop.js";
3
3
  export type { TitleProp, SubtitleProp, StatusProp, DescriptionProp, ExtraProp, FooterProp, ActionProp, IconProp, ConfirmLabelProp, CancelLabelProp, ActionsProp, EmptyMessageProp, } from "./content.prop.js";
4
- export type { PageDensityProp, PageContainerVariantProp, CenteredShellWidthProp, CenteredShellAlignProp, CenteredShellPresetProp, ErrorSurfaceModeProp, ErrorSurfaceStatusProp, AuthShellPresetProp, MobileShellHeightProp, OrientationProp, TableDensityProp, DensityProp, GapProp, } from "./layout.prop.js";
5
- export type { ButtonVariantProp, ButtonSizeProp, BadgeVariantProp, AppSettingPickerAppearanceProp, ShapeProp, AvatarShapeProp, TextSizeProp, TextToneProp, FontWeightProp, HeadingLevelProp, TextAlignProp, SizeProp, FormLayoutProp, DescriptionsLayoutProp, BreakpointProp, ConfirmVariantProp, ToneProp, AlertVariantProp, SortDirectionProp, ColumnAlignProp, SortStateProp, RevealDelayProp, ActivityVariantProp, ActivityAnnounceProp, } from "./interaction.prop.js";
4
+ export type { PageDensityProp, PageContainerVariantProp, CenteredShellWidthProp, CenteredShellAlignProp, CenteredShellPresetProp, ErrorSurfaceModeProp, ErrorSurfaceStatusProp, AuthShellPresetProp, MobileShellHeightProp, OrientationProp, TableDensityProp, DensityProp, GapNameProp, PadProp, PadRawProp, PadSides, GapProp, GapStepProp, } from "./layout.prop.js";
5
+ export type { ButtonVariantProp, ButtonSizeProp, BadgeVariantProp, AppSettingPickerAppearanceProp, AppSettingToggleAppearanceProp, ShapeProp, AvatarShapeProp, TextSizeProp, TextToneProp, FontWeightProp, HeadingLevelProp, TextAlignProp, SizeProp, FormLayoutProp, DescriptionsLayoutProp, BreakpointProp, ConfirmVariantProp, ToneProp, AlertVariantProp, SortDirectionProp, ColumnAlignProp, SortStateProp, RevealDelayProp, ActivityVariantProp, ActivityAnnounceProp, } from "./interaction.prop.js";
6
6
  export type { BreadcrumbItemProp, BreadcrumbProp } from "./navigation.prop.js";
7
7
  export type { GetRowIdProp, OnRowClickProp, ColumnDefProp, TablePresetProp, TableColumnPriorityProp, TableCellIndentProp, SelectedIdsProp, OnSelectChangeProp, OnTableDensityChangeProp, OnSortChangeProp, OnSearchChangeProp, OnClearFiltersProp, HasActiveFiltersProp, StickyProp, } from "./data.prop.js";
@@ -39,8 +39,24 @@ export type BadgeVariantProp = "default" | "secondary" | "outline" | "dashed";
39
39
  * STRUCTURALLY drops the value text and the picker's owned trigger width, keeping the localized
40
40
  * `aria-label`, focus ring, keyboard behaviour and a `--control-height` tap target (which is
41
41
  * ≥44px on coarse/touch pointers per Rule #24) — so consumers never hide internal nodes via CSS.
42
+ * - `bar` — the same structural drops as `icon`, re-shaped as a CELL OF THE BAR rather than a
43
+ * control dropped into it: it fills the bar's height and squares its corners, so the hover
44
+ * surface paints the whole strip. Reach for it in a `Topbar` slot or AppShell's own bar, where
45
+ * `icon` leaves a --control-height pill floating in a taller strip and reads as a different
46
+ * control family from the bar's own chrome (`TopbarItem`).
42
47
  */
43
- export type AppSettingPickerAppearanceProp = "labeled" | "icon" | "inline";
48
+ export type AppSettingPickerAppearanceProp = "labeled" | "icon" | "bar" | "inline";
49
+ /**
50
+ * AppSettingToggle presentation. The toggle has no menu, so it has no `labeled`/`inline` form —
51
+ * the two members here are the two BOXES a one-tap cycler can take.
52
+ * - `bar` (default) — a CELL of the bar (`TopbarItem`): full bar height, the bar's own hover
53
+ * surface, square corners (`--topbar-item-radius`). This is the canonical placement, which is
54
+ * why it is the default: a toggle exists for a top bar.
55
+ * - `icon` — a square `--control-height` ghost button for everywhere that is NOT a bar (a
56
+ * settings row, a card header). In a taller bar this leaves a pill floating mid-strip, which is
57
+ * the defect `bar` exists to avoid.
58
+ */
59
+ export type AppSettingToggleAppearanceProp = "bar" | "icon";
44
60
  /** Button size preset. */
45
61
  export type SizeProp = "xs" | "sm" | "md" | "lg";
46
62
  /** Button size preset; icon-only sizes are a documented Button subset. */
@@ -59,7 +59,63 @@ export type AuthShellPresetProp = "default" | "login" | "registration" | "device
59
59
  * Without it those stacks had to carry `gap="xs"`, which is a visual change forced by a missing
60
60
  * step rather than by design.
61
61
  */
62
- export type GapProp = "none" | "xs" | "sm" | "md" | "lg" | "xl";
62
+ export type GapNameProp = "none" | "xs" | "sm" | "md" | "lg" | "xl";
63
+ /**
64
+ * Bậc SỐ, ánh xạ thẳng vào `--space-{n}` của thang gốc.
65
+ *
66
+ * Vì sao cần, dù đã có sáu tên ở trên: thang gốc có MƯỜI bậc
67
+ * (0·4·8·12·16·20·24·32·40·48px) nhưng lớp tên chỉ với tới năm trong số đó.
68
+ * `md` là 16px, `lg` là 24px — và `--space-5` (20px) tồn tại mà không có đường
69
+ * nào gọi tới. Người viết mã gặp một thiết kế 20px thì không còn nước đi hợp
70
+ * lệ nào: làm tròn thì lệch, viết literal thì `no-arbitrary-spacing` chặn.
71
+ *
72
+ * Bậc số KHÔNG theo trục — `gap={3}` là 12px ở cả hàng lẫn cột. Đó là chủ ý:
73
+ * tên mang ý ĐỊNH ("cách nhau vừa phải, tuỳ trục"), số mang GIÁ TRỊ ("đúng
74
+ * 12px"). Trộn hai nghĩa vào một thang là lý do thang cũ vừa thô vừa khó đoán.
75
+ */
76
+ export type GapStepProp = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 12;
77
+ export type GapProp = GapNameProp | GapStepProp;
78
+ /**
79
+ * Đệm TRONG của một primitive bố cục.
80
+ *
81
+ * ## Vì sao tồn tại
82
+ *
83
+ * Chạy `ui-audit` trên consumer thật (godx-chat, 08/09/2026): **42 trong 51
84
+ * lỗi** là `no-utility-spacing`, và gần như toàn bộ chúng xin cùng một thứ —
85
+ * padding. `<Flex className="p-3">` không phải người viết cẩu thả; đó là nước
86
+ * đi duy nhất còn lại khi primitive không có prop đệm. Một prop thiếu đẻ ra 42
87
+ * lỗi, và mỗi lỗi ấy trước nay chỉ có hai đường: để đỏ, hoặc mở issue rồi chờ.
88
+ *
89
+ * ## Vì sao ba tầng chứ không phải một
90
+ *
91
+ * Đo trên chính 51 lỗi ấy: có `p-3` (bốn cạnh), có `px-4`/`py-1` (theo trục),
92
+ * và **16 dòng cần cạnh riêng** (`pt-2.5` khác `pb-2.5` trên cùng phần tử).
93
+ * Một prop chỉ nhận một số sẽ không phủ nổi, và ép người ta quay lại class.
94
+ *
95
+ * Tên cạnh là LOGIC (`inlineStart`, `blockEnd`), không phải vật lý (`left`,
96
+ * `top`) — cùng luật với `ms-`/`me-` mà audit đang bắt, và là thứ giữ cho giao
97
+ * diện RTL không phải viết lại.
98
+ */
99
+ export type PadSides<T> = T | {
100
+ /** Hai cạnh theo trục viết (trái+phải ở LTR). */
101
+ inline?: T;
102
+ /** Hai cạnh theo trục khối (trên+dưới). */
103
+ block?: T;
104
+ inlineStart?: T;
105
+ inlineEnd?: T;
106
+ blockStart?: T;
107
+ blockEnd?: T;
108
+ };
109
+ /** Đệm theo thang token — bậc tên hoặc bậc số, cùng thang với `gap`. */
110
+ export type PadProp = PadSides<GapProp>;
111
+ /**
112
+ * Đệm bằng pixel THÔ, cho giá trị ngoài thang.
113
+ *
114
+ * Cùng lý do với `gapRaw`, và cùng cái giá: nó để lại `data-pad-raw` trên DOM
115
+ * nên mỗi lần thoát đều đếm được. Thiết kế thật cần 2px, 6px, 10px, 14px, 44px
116
+ * — thang không có bậc nào như thế, và bịt lại không làm chúng biến mất.
117
+ */
118
+ export type PadRawProp = PadSides<number>;
63
119
  /** DataTable row density subset. */
64
120
  export type TableDensityProp = Exclude<DensityProp, "default">;
65
121
  /**