@godxjp/ui 27.7.0 → 27.9.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 (37) hide show
  1. package/dist/components/data-display/range-timeline.d.ts +19 -0
  2. package/dist/components/data-display/range-timeline.js +2 -0
  3. package/dist/components/data-display/tree.js +2 -0
  4. package/dist/components/data-entry/upload.js +17 -15
  5. package/dist/components/layout/app-shell.d.ts +1 -1
  6. package/dist/components/layout/app-shell.js +8 -2
  7. package/dist/components/layout/topbar-item.d.ts +2 -0
  8. package/dist/components/layout/topbar-item.js +34 -4
  9. package/dist/components/layout/topbar.d.ts +1 -1
  10. package/dist/components/layout/topbar.js +2 -0
  11. package/dist/contracts/measurement.json +1 -1
  12. package/dist/props/components/data-display.prop.d.ts +11 -0
  13. package/dist/props/components/data-entry.prop.d.ts +6 -3
  14. package/dist/props/components/layout.prop.d.ts +56 -0
  15. package/dist/props/registry.d.ts +28 -4
  16. package/dist/props/registry.js +44 -4
  17. package/dist/styles/control.css +6 -7
  18. package/dist/styles/data-display-layout.css +25 -7
  19. package/dist/styles/data-entry-layout.css +13 -0
  20. package/dist/styles/layout.css +68 -4
  21. package/dist/styles/shell-layout.css +43 -1
  22. package/dist/tokens/components/control.css +5 -2
  23. package/dist/tokens/components/data-display.css +10 -1
  24. package/dist/tokens/components/shell.css +3 -0
  25. package/dist/tokens/components/tree.css +2 -0
  26. package/docs/DESIGN-AUTHORITY.md +20 -0
  27. package/docs/FRAME-COVERAGE-REPORT.md +1 -1
  28. package/docs/data-display/timeline.tsx +77 -1
  29. package/docs/data-display/tree.tsx +94 -0
  30. package/docs/data-entry/calendar.tsx +3 -2
  31. package/docs/general/icon.tsx +3 -1
  32. package/docs/layout/app-shell-narrow-bar.tsx +205 -0
  33. package/docs/layout/app-shell.tsx +10 -0
  34. package/docs/layout/topbar-item.tsx +37 -0
  35. package/docs/layout/topbar.tsx +11 -1
  36. package/package.json +2 -2
  37. package/scripts/cli.mjs +3 -0
@@ -1,4 +1,5 @@
1
1
  import * as React from "react";
2
+ import type { DensityProp } from "../../props/vocabulary/index.js";
2
3
  export type RangeTimelineRow = {
3
4
  id: string;
4
5
  label: React.ReactNode;
@@ -34,6 +35,15 @@ export type RangeTimelineProps = React.HTMLAttributes<HTMLElement> & {
34
35
  * the header-only ruling. Colour `--range-timeline-grid-color`, weight `--range-timeline-grid-width`.
35
36
  */
36
37
  bordered?: boolean;
38
+ /**
39
+ * How wide ONE axis unit is — the canonical density vocabulary, the same three steps
40
+ * `DataTable density` uses. `default` (56px/day) is the shipped width, so an existing Gantt
41
+ * does not move; `compact` (42px/day) fits a third more days on the same screen; `comfortable`
42
+ * (70px/day) spreads them out. It moves the column width ONLY — row height, bar height and the
43
+ * label column are identical at every step. Retune a step with
44
+ * `--range-timeline-unit-width-{compact,default,comfortable}`.
45
+ */
46
+ density?: DensityProp;
37
47
  /**
38
48
  * Controlled ids of the EXPANDED parent rows (same spelling as `Tree expandedValues`). A folded
39
49
  * parent hides every descendant row — label and bar.
@@ -66,6 +76,15 @@ export declare const RangeTimeline: React.ForwardRefExoticComponent<React.HTMLAt
66
76
  * the header-only ruling. Colour `--range-timeline-grid-color`, weight `--range-timeline-grid-width`.
67
77
  */
68
78
  bordered?: boolean;
79
+ /**
80
+ * How wide ONE axis unit is — the canonical density vocabulary, the same three steps
81
+ * `DataTable density` uses. `default` (56px/day) is the shipped width, so an existing Gantt
82
+ * does not move; `compact` (42px/day) fits a third more days on the same screen; `comfortable`
83
+ * (70px/day) spreads them out. It moves the column width ONLY — row height, bar height and the
84
+ * label column are identical at every step. Retune a step with
85
+ * `--range-timeline-unit-width-{compact,default,comfortable}`.
86
+ */
87
+ density?: DensityProp;
69
88
  /**
70
89
  * Controlled ids of the EXPANDED parent rows (same spelling as `Tree expandedValues`). A folded
71
90
  * parent hides every descendant row — label and bar.
@@ -15,6 +15,7 @@ const RangeTimeline = React.forwardRef(
15
15
  today,
16
16
  onRangeChange,
17
17
  bordered = true,
18
+ density = "default",
18
19
  expandedValues,
19
20
  defaultExpandedValues,
20
21
  onExpandedValuesChange,
@@ -92,6 +93,7 @@ const RangeTimeline = React.forwardRef(
92
93
  ref,
93
94
  className: cn("ui-range-timeline", className),
94
95
  "data-bordered": bordered ? "true" : void 0,
96
+ "data-density": density === "default" ? void 0 : density,
95
97
  "aria-label": label,
96
98
  tabIndex: 0,
97
99
  children: /* @__PURE__ */ jsxs(
@@ -64,6 +64,7 @@ function TreeRoot({
64
64
  titleRender,
65
65
  showLine = false,
66
66
  showIcon = false,
67
+ divided = false,
67
68
  variant = "default",
68
69
  size = "md",
69
70
  disabled = false,
@@ -411,6 +412,7 @@ function TreeRoot({
411
412
  "data-size": size,
412
413
  "data-variant": variant,
413
414
  "data-show-line": showLine ? "true" : void 0,
415
+ "data-divided": divided ? "true" : void 0,
414
416
  "data-empty": isEmpty ? "true" : void 0,
415
417
  className: cn("ui-tree", className),
416
418
  children: isEmpty ? null : renderNodes(options, 0)
@@ -772,21 +772,23 @@ function UploadFileList({
772
772
  ] }),
773
773
  item.status === "uploading" && /* @__PURE__ */ jsx(Progress, { value: item.percent ?? 0, "aria-label": t("dataEntry.upload.uploading") })
774
774
  ] }),
775
- onPreview && (hasCustomPreview || item.previewUrl) && /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => onPreview(item), children: t("dataEntry.upload.preview") }),
776
- onDownload && /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => onDownload(item), children: t("dataEntry.upload.download") }),
777
- onStart && item.file && item.status !== "uploading" && item.status !== "done" && /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => onStart(item), children: t(item.status === "error" ? "dataEntry.upload.retry" : "dataEntry.upload.start") }),
778
- onCancel && item.status === "uploading" && /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => onCancel(item.uid), children: t("dataEntry.upload.cancel") }),
779
- onRemove && /* @__PURE__ */ jsx(
780
- Button,
781
- {
782
- type: "button",
783
- size: "sm",
784
- variant: "ghost",
785
- "aria-label": t("dataEntry.upload.removeFile", { name: item.name }),
786
- onClick: () => onRemove(item.uid),
787
- children: /* @__PURE__ */ jsx(X, { className: "ui-upload-row-icon", "aria-hidden": "true" })
788
- }
789
- )
775
+ /* @__PURE__ */ jsxs("div", { className: "ui-upload-row-actions", children: [
776
+ onPreview && (hasCustomPreview || item.previewUrl) && /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => onPreview(item), children: t("dataEntry.upload.preview") }),
777
+ onDownload && /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => onDownload(item), children: t("dataEntry.upload.download") }),
778
+ onStart && item.file && item.status !== "uploading" && item.status !== "done" && /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => onStart(item), children: t(item.status === "error" ? "dataEntry.upload.retry" : "dataEntry.upload.start") }),
779
+ onCancel && item.status === "uploading" && /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => onCancel(item.uid), children: t("dataEntry.upload.cancel") }),
780
+ onRemove && /* @__PURE__ */ jsx(
781
+ Button,
782
+ {
783
+ type: "button",
784
+ size: "sm",
785
+ variant: "ghost",
786
+ "aria-label": t("dataEntry.upload.removeFile", { name: item.name }),
787
+ onClick: () => onRemove(item.uid),
788
+ children: /* @__PURE__ */ jsx(X, { className: "ui-upload-row-icon", "aria-hidden": "true" })
789
+ }
790
+ )
791
+ ] })
790
792
  ] });
791
793
  return /* @__PURE__ */ jsx("li", { children: itemRender ? itemRender(node, item, items, {
792
794
  remove: () => onRemove?.(item.uid),
@@ -3,4 +3,4 @@ import type { AppShellProp } from "../../props/components/layout.prop.js";
3
3
  export type { AppShellProp, AppShellProp as AppShellProps, } from "../../props/components/layout.prop.js";
4
4
  /** Same rail boundary as shell-layout.css; SSR starts in docked mode. */
5
5
  export declare function useAppShellNavigationMode(): "drawer" | "docked";
6
- export declare function AppShell({ sidebar, topbar, topbarLeft, topbarRight, logo, breadcrumb, footer, children, sidebarCollapsed, responsiveNavigation, topbarSpan, navRail, navRailPosition, navRailEnd, navRailLabel, mobileNav, mobileNavLabel, mobileNavOpen, onMobileNavOpenChange, }: AppShellProp): React.JSX.Element;
6
+ export declare function AppShell({ sidebar, topbar, topbarLeft, topbarRight, logo, logoCompact, logoCompactBelow, breadcrumb, footer, children, sidebarCollapsed, responsiveNavigation, topbarSpan, navRail, navRailPosition, navRailEnd, navRailLabel, mobileNav, mobileNavLabel, mobileNavOpen, onMobileNavOpenChange, }: AppShellProp): React.JSX.Element;
@@ -17,6 +17,8 @@ function AppShell({
17
17
  topbarLeft,
18
18
  topbarRight,
19
19
  logo,
20
+ logoCompact,
21
+ logoCompactBelow = "sm",
20
22
  breadcrumb,
21
23
  footer,
22
24
  children,
@@ -72,11 +74,15 @@ function AppShell({
72
74
  }
73
75
  }
74
76
  const logoInRail = hasSidebar && logo !== void 0 && topbarSpan !== "full";
77
+ const brand = logoCompact === void 0 ? logo : /* @__PURE__ */ jsxs(Fragment, { children: [
78
+ /* @__PURE__ */ jsx("span", { className: "app-topbar-brand", "data-hide-below": logoCompactBelow, children: logo }),
79
+ /* @__PURE__ */ jsx("span", { className: "app-topbar-brand", "data-hide-from": logoCompactBelow, children: logoCompact })
80
+ ] });
75
81
  const resolvedTopbar = topbar !== void 0 ? /* @__PURE__ */ jsxs("div", { className: "app-topbar-rail", children: [
76
- !logoInRail && logo !== void 0 && /* @__PURE__ */ jsx("div", { className: "app-topbar-logo", children: logo }),
82
+ !logoInRail && logo !== void 0 && /* @__PURE__ */ jsx("div", { className: "app-topbar-logo", children: brand }),
77
83
  /* @__PURE__ */ jsx("div", { className: "app-topbar-custom", children: topbar })
78
84
  ] }) : /* @__PURE__ */ jsxs("div", { className: "app-topbar-rail", children: [
79
- !logoInRail && logo !== void 0 && /* @__PURE__ */ jsx("div", { className: "app-topbar-logo", children: logo }),
85
+ !logoInRail && logo !== void 0 && /* @__PURE__ */ jsx("div", { className: "app-topbar-logo", children: brand }),
80
86
  topbarLeft !== void 0 && /* @__PURE__ */ jsx("div", { className: "app-topbar-left", children: topbarLeft }),
81
87
  /* @__PURE__ */ jsx("div", { className: "app-topbar-spacer" }),
82
88
  topbarRight !== void 0 && /* @__PURE__ */ jsx("div", { className: "app-topbar-right", children: topbarRight })
@@ -13,6 +13,8 @@ export type { TopbarItemProp, TopbarItemProp as TopbarItemProps, } from "../../p
13
13
  export declare const TopbarItem: React.ForwardRefExoticComponent<Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children"> & {
14
14
  hideBelow?: import("../../props/index.js").BreakpointProp;
15
15
  icon?: React.ReactNode;
16
+ iconHideFrom?: import("../../props/index.js").BreakpointProp;
17
+ labelHideBelow?: import("../../props/index.js").BreakpointProp;
16
18
  badge?: React.ReactNode;
17
19
  badgeTone?: import("../../props/components/layout.prop.js").SidebarBadgeToneProp;
18
20
  asChild?: boolean;
@@ -2,10 +2,40 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import { Slot } from "../../lib/slot.js";
4
4
  import { cn } from "../../lib/utils.js";
5
- const TopbarItem = React.forwardRef(function TopbarItem2({ asChild = false, className, type, hideBelow, icon, badge, badgeTone, children, ...props }, ref) {
5
+ const TopbarItem = React.forwardRef(function TopbarItem2({
6
+ asChild = false,
7
+ className,
8
+ type,
9
+ hideBelow,
10
+ icon,
11
+ iconHideFrom,
12
+ labelHideBelow,
13
+ badge,
14
+ badgeTone,
15
+ children,
16
+ ...props
17
+ }, ref) {
6
18
  const Comp = asChild ? Slot : "button";
7
19
  const showBadge = !asChild && badge !== void 0 && badge !== "";
8
- const iconNode = !asChild && icon !== void 0 && icon !== null && icon !== false ? /* @__PURE__ */ jsx("span", { "data-slot": "topbar-item-icon", className: "ui-topbar-item-icon", children: icon }) : null;
20
+ const iconNode = icon !== void 0 && icon !== null && icon !== false ? /* @__PURE__ */ jsx(
21
+ "span",
22
+ {
23
+ "data-slot": "topbar-item-icon",
24
+ className: "ui-topbar-item-icon",
25
+ "data-hide-from": iconHideFrom,
26
+ children: icon
27
+ }
28
+ ) : null;
29
+ const labelOf = (label) => labelHideBelow === void 0 || label === void 0 || label === null || label === false ? label : /* @__PURE__ */ jsx(
30
+ "span",
31
+ {
32
+ "data-slot": "topbar-item-label",
33
+ className: "ui-topbar-item-label",
34
+ "data-hide-below": labelHideBelow,
35
+ children: label
36
+ }
37
+ );
38
+ const slotted = asChild && (iconNode !== null || labelHideBelow !== void 0) && React.isValidElement(children) ? React.cloneElement(children, void 0, iconNode, labelOf(children.props.children)) : children;
9
39
  const badgeNode = showBadge ? /* @__PURE__ */ jsx(
10
40
  "span",
11
41
  {
@@ -24,9 +54,9 @@ const TopbarItem = React.forwardRef(function TopbarItem2({ asChild = false, clas
24
54
  className: cn("ui-topbar-item ui-focus-ring", className),
25
55
  type: asChild ? void 0 : type ?? "button",
26
56
  ...props,
27
- children: asChild ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
57
+ children: asChild ? slotted : /* @__PURE__ */ jsxs(Fragment, { children: [
28
58
  iconNode,
29
- children,
59
+ labelOf(children),
30
60
  badgeNode
31
61
  ] })
32
62
  }
@@ -4,4 +4,4 @@ export type { TopbarProp, TopbarProp as TopbarProps } from "../../props/componen
4
4
  * Topbar — a PURE SLOT bar. It positions three clusters (`start` / `center` / `end`) and owns the
5
5
  * bar's flex layout; it does NOT bake any chrome.
6
6
  */
7
- export declare function Topbar({ start, center, end, className, children, height, pad, style, ...props }: TopbarProp): import("react").JSX.Element;
7
+ export declare function Topbar({ start, center, end, className, children, height, overflow, pad, style, ...props }: TopbarProp): import("react").JSX.Element;
@@ -8,6 +8,7 @@ function Topbar({
8
8
  className,
9
9
  children,
10
10
  height,
11
+ overflow = "scroll",
11
12
  pad,
12
13
  style,
13
14
  ...props
@@ -16,6 +17,7 @@ function Topbar({
16
17
  "div",
17
18
  {
18
19
  "data-height": height,
20
+ "data-overflow": overflow,
19
21
  style: { ...style, ...padStyle(pad, void 0) },
20
22
  "data-slot": "topbar",
21
23
  className: cn("ui-topbar", className),
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$comment": "AUTO-GENERATED by scripts/gen-measurement-contract.mjs — do not edit. Read this instead of guessing: docs/MEASUREMENT-CONTRACT.md.",
3
- "version": "27.7.0",
3
+ "version": "27.9.0",
4
4
  "targetSize": {
5
5
  "standard": "WCAG 2.2 SC 2.5.8 Target Size (Minimum), level AA — 24×24 CSS px",
6
6
  "min": 24,
@@ -700,6 +700,17 @@ export type TreeProp = {
700
700
  titleRender?: (node: TreeNodeProp) => React.ReactNode;
701
701
  /** Draw the connector rails between a parent and its children (antd `showLine`). */
702
702
  showLine?: boolean;
703
+ /**
704
+ * Rule between the rows: a hairline on every node's block-start except the outline's first, so a
705
+ * tree used as navigation inside a Card reads as a list instead of one block (gh#732). The rule
706
+ * runs the FULL width of the row at every depth — it is never indented per level, which would
707
+ * make the children read as a nested table. Colour is `--tree-divider-color`.
708
+ *
709
+ * Off by default: a rule is chrome, and this component's chrome defaults quiet (cardinal rule
710
+ * #44 — the same reason `showLine` ships off). Not antd's name — antd's `Tree` has no such
711
+ * capability; see docs/DESIGN-AUTHORITY.md.
712
+ */
713
+ divided?: boolean;
703
714
  /** Draw each node's `icon` (antd `showIcon`). `variant="directory"` supplies folder/file glyphs. */
704
715
  showIcon?: boolean;
705
716
  /** `directory` is antd's `<DirectoryTree>`: folder/file glyphs and a full-row selected band. */
@@ -745,9 +745,12 @@ export type CalendarProp = DayPickerProps & CalendarFooterProp & {
745
745
  *
746
746
  * Default `true` — the owner's call, from a real screen: with no ruling the month read as a
747
747
  * cloud of numbers and was "very hard to read". Pass `bordered={false}` for the floating-button
748
- * look. The line colour is `--calendar-grid-border-color` (default `--input` at 0.5 alpha,
749
- * 1.74:1 light / 1.95:1 dark on the popover; the full `--input` read too dark, and the
750
- * decorative `--border` measured 1.15:1 and was invisible as a 1px ruling).
748
+ * look. The line colour is `--calendar-grid-border-color`, default `hsl(var(--border))` — the
749
+ * same tier as the popover edge, a Card edge and a DataTable row rule, so the ruling can never
750
+ * out-weigh the surface it is drawn on (L* 93.80 / 1.149:1 light, L* 20.76 / 1.270:1 dark).
751
+ * It was `--input` at 0.5 alpha (L* 78.67 / 1.738:1) through 27.6.0 and was reported darker
752
+ * than every card and table in the system (gh#730); the full `--input` (3.463:1) was reported
753
+ * too dark before that. Set `--calendar-grid-border-color` to retint.
751
754
  */
752
755
  bordered?: boolean;
753
756
  /** Decorate a day cell — 祝日, a booked day, a deadline. @see CalendarCellRenderProp */
@@ -353,6 +353,28 @@ export type AppShellProp = {
353
353
  topbarLeft?: ReactNode;
354
354
  topbarRight?: ReactNode;
355
355
  logo?: ReactNode;
356
+ /**
357
+ * The brand node a NARROW bar gets instead of `logo` — a mark without the wordmark, a shorter
358
+ * lockup, a different `viewBox` (gh#728).
359
+ *
360
+ * The brand cell shrinks without this prop: below the `sm` step it is capped at
361
+ * `--app-shell-brand-compact-max-inline-size` and anything past the cap is cropped from the
362
+ * inline-end. A CROP is all a stylesheet can do to artwork it did not author — `viewBox` is an
363
+ * attribute, which is why consumers were re-cropping their own SVG through a media-query hook.
364
+ * Passing a node here is how you CHOOSE what the narrow bar shows instead.
365
+ *
366
+ * Both nodes are rendered; the breakpoint drops one with `display: none`, so exactly one brand
367
+ * is ever in the accessibility tree. Applies to the brand IN THE BAR only: under the default
368
+ * `topbarSpan="content"` with a sidebar the brand sits at the head of the rail, which the
369
+ * responsive shell has already replaced with the drawer at that width.
370
+ */
371
+ logoCompact?: ReactNode;
372
+ /**
373
+ * The step at which `logoCompact` takes over — `Flex hideBelow`'s own vocabulary and the same
374
+ * canonical scale (sm 40rem · md 48rem · lg 64rem · xl 80rem). Defaults to `"sm"`, the step the
375
+ * brand cap uses. Ignored without `logoCompact`.
376
+ */
377
+ logoCompactBelow?: BreakpointProp;
356
378
  breadcrumb?: ReactNode;
357
379
  footer?: ReactNode;
358
380
  sidebarCollapsed?: boolean;
@@ -1318,6 +1340,24 @@ export type TopbarProp = Omit<React.HTMLAttributes<HTMLDivElement>, "children">
1318
1340
  center?: ReactNode;
1319
1341
  /** Inline-end cluster — settings pickers, notifications, the user menu. */
1320
1342
  end?: ReactNode;
1343
+ /**
1344
+ * What a bar that does not fit does with the cells that do not fit (gh#728).
1345
+ *
1346
+ * - `"scroll"` (default) — the BAR scrolls on the inline axis while the `start` and `end`
1347
+ * clusters keep their cells whole (`start` floors at one cell, `end` at its content), so what
1348
+ * does not fit is off-port rather than half-painted. Every cell stays in the DOM and in the
1349
+ * accessibility tree, Tab reaches each one in order, and the browser scrolls a focused cell
1350
+ * fully into view; the scrollbar is suppressed (a horizontal bar inside a 48px chrome row
1351
+ * would eat the height that caused the deficit) so the pointer affordance is drag/wheel.
1352
+ * - `"clip"` — the pre-gh#728 behaviour: a cell past the cluster's edge is simply not painted.
1353
+ * Still focusable, still announced, invisible and unreachable by pointer. Choose it only for a
1354
+ * bar you have measured as never overflowing.
1355
+ *
1356
+ * Independent of `TopbarItem hideBelow`, which REMOVES a cell at a step: dropping a cell is the
1357
+ * consumer saying it does not belong on a phone, and that remains the way to spend the budget
1358
+ * deliberately. This prop is only about what happens once there is no budget left.
1359
+ */
1360
+ overflow?: "scroll" | "clip";
1321
1361
  /** Escape hatch — render fully custom bar content instead of the three slots. */
1322
1362
  children?: ReactNode;
1323
1363
  };
@@ -1354,8 +1394,24 @@ export type TopbarItemProp = Omit<React.ButtonHTMLAttributes<HTMLButtonElement>,
1354
1394
  * visible label, not from the glyph. For a glyph that must carry a name, or one that needs a
1355
1395
  * step other than the bar's, pass `<Icon as={…} size=… label=… />` — as this prop's value or as
1356
1396
  * a child — and it keeps its own metric and its own semantics.
1397
+ *
1398
+ * Rendered under `asChild` too: the slot is inserted ahead of the child element's own children,
1399
+ * and the child element stays the cell (gh#726).
1357
1400
  */
1358
1401
  icon?: ReactNode;
1402
+ /**
1403
+ * Drop the `icon` slot FROM a breakpoint step upwards — `Flex hideFrom`'s contract, scoped to
1404
+ * the cell's glyph, so a cell reads label-only on a wide bar without the consumer wrapping the
1405
+ * glyph (gh#726). Purely decorative: the accessible name is unaffected.
1406
+ */
1407
+ iconHideFrom?: BreakpointProp;
1408
+ /**
1409
+ * Visually hide the cell's label BELOW a breakpoint step — `Flex hideBelow`'s contract, scoped to
1410
+ * the label — so the cell collapses to icon-only on a narrow bar (gh#726). The label stays in the
1411
+ * accessibility tree (visually hidden, not `display: none`), so the collapsed cell keeps its
1412
+ * accessible name. Under `asChild` the child element's own children are the label.
1413
+ */
1414
+ labelHideBelow?: BreakpointProp;
1359
1415
  /**
1360
1416
  * Unread count OVERLAID on the cell's glyph — the notification-bell affordance the cell's own use
1361
1417
  * cases name (gh#398). Pass the CONTENT ONLY, exactly like `SidebarItemProp.badge`: a number, a
@@ -883,7 +883,15 @@ export declare const COMPONENT_PROP_REGISTRY: {
883
883
  readonly AppShellProp: {
884
884
  readonly group: "layout";
885
885
  readonly file: "components/layout.prop.ts";
886
- readonly vocabulary: readonly ["ChildrenProp"];
886
+ readonly vocabulary: readonly ["ChildrenProp", "BreakpointProp", {
887
+ readonly field: "logoCompact";
888
+ readonly local: true;
889
+ readonly reason: "The brand node a narrow bar gets instead of `logo` — the consumer's own mark/viewBox, which a stylesheet cannot produce (gh#728).";
890
+ }, {
891
+ readonly field: "logoCompactBelow";
892
+ readonly local: true;
893
+ readonly reason: "Flex `hideBelow` scoped to the brand cell — the step at which `logoCompact` takes over (gh#728).";
894
+ }];
887
895
  };
888
896
  readonly AuthShellProp: {
889
897
  readonly group: "layout";
@@ -1178,7 +1186,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
1178
1186
  readonly TopbarProp: {
1179
1187
  readonly group: "layout";
1180
1188
  readonly file: "components/layout.prop.ts";
1181
- readonly vocabulary: readonly ["ChildrenProp"];
1189
+ readonly vocabulary: readonly ["ChildrenProp", {
1190
+ readonly field: "overflow";
1191
+ readonly local: true;
1192
+ readonly reason: "The bar's overflow contract — `scroll` (default) keeps every cell reachable, `clip` is the pre-gh#728 slicing.";
1193
+ }];
1182
1194
  };
1183
1195
  readonly TopbarItemProp: {
1184
1196
  readonly group: "layout";
@@ -1187,6 +1199,14 @@ export declare const COMPONENT_PROP_REGISTRY: {
1187
1199
  readonly field: "asChild";
1188
1200
  readonly local: true;
1189
1201
  readonly reason: "Radix Slot passthrough — merges onto the child";
1202
+ }, "BreakpointProp", {
1203
+ readonly field: "iconHideFrom";
1204
+ readonly local: true;
1205
+ readonly reason: "Flex `hideFrom` scoped to the cell's icon slot — label-only from a breakpoint up without hand-wrapping the glyph (gh#726).";
1206
+ }, {
1207
+ readonly field: "labelHideBelow";
1208
+ readonly local: true;
1209
+ readonly reason: "Flex `hideBelow` scoped to the cell's label — icon-only below a breakpoint; visually hidden so the accessible name survives (gh#726).";
1190
1210
  }];
1191
1211
  };
1192
1212
  readonly NavListProp: {
@@ -2808,7 +2828,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
2808
2828
  readonly TreeProp: {
2809
2829
  readonly group: "data-display";
2810
2830
  readonly file: "components/data-display.prop.ts";
2811
- readonly vocabulary: readonly ["ValueProp", "DefaultValueProp", "OnValueChangeProp", "DisabledProp", "SizeProp", "ClassNameProp", "IdProp"];
2831
+ readonly vocabulary: readonly ["ValueProp", "DefaultValueProp", "OnValueChangeProp", "DisabledProp", "SizeProp", "ClassNameProp", "IdProp", {
2832
+ readonly field: "divided";
2833
+ readonly local: true;
2834
+ readonly reason: "Rules between the rows — a hairline on every node's block-start but the outline's first, full row width at every depth (gh#732). Default false, because chrome defaults quiet here (#44). Not antd's spelling: antd's Tree has no such capability, and `bordered` already means a grid's frame plus column rules on Table / Calendar / RangeTimeline; see docs/DESIGN-AUTHORITY.md.";
2835
+ }];
2812
2836
  };
2813
2837
  readonly CardProp: {
2814
2838
  readonly group: "data-display";
@@ -2935,7 +2959,7 @@ export declare const COMPONENT_PROP_REGISTRY: {
2935
2959
  readonly RangeTimelineProp: {
2936
2960
  readonly group: "data-display";
2937
2961
  readonly file: "components/data-display/range-timeline.tsx";
2938
- readonly vocabulary: readonly ["LabelProp", {
2962
+ readonly vocabulary: readonly ["LabelProp", "DensityProp", {
2939
2963
  readonly field: "columns";
2940
2964
  readonly local: true;
2941
2965
  readonly reason: "Labels, positive numeric unit counts and an optional muted flag (non-working period) define a consumer-supplied axis.";
@@ -883,7 +883,20 @@ const COMPONENT_PROP_REGISTRY = {
883
883
  AppShellProp: {
884
884
  group: "layout",
885
885
  file: "components/layout.prop.ts",
886
- vocabulary: ["ChildrenProp"]
886
+ vocabulary: [
887
+ "ChildrenProp",
888
+ "BreakpointProp",
889
+ {
890
+ field: "logoCompact",
891
+ local: true,
892
+ reason: "The brand node a narrow bar gets instead of `logo` \u2014 the consumer's own mark/viewBox, which a stylesheet cannot produce (gh#728)."
893
+ },
894
+ {
895
+ field: "logoCompactBelow",
896
+ local: true,
897
+ reason: "Flex `hideBelow` scoped to the brand cell \u2014 the step at which `logoCompact` takes over (gh#728)."
898
+ }
899
+ ]
887
900
  },
888
901
  AuthShellProp: {
889
902
  group: "layout",
@@ -1276,7 +1289,14 @@ const COMPONENT_PROP_REGISTRY = {
1276
1289
  TopbarProp: {
1277
1290
  group: "layout",
1278
1291
  file: "components/layout.prop.ts",
1279
- vocabulary: ["ChildrenProp"]
1292
+ vocabulary: [
1293
+ "ChildrenProp",
1294
+ {
1295
+ field: "overflow",
1296
+ local: true,
1297
+ reason: "The bar's overflow contract \u2014 `scroll` (default) keeps every cell reachable, `clip` is the pre-gh#728 slicing."
1298
+ }
1299
+ ]
1280
1300
  },
1281
1301
  TopbarItemProp: {
1282
1302
  group: "layout",
@@ -1284,7 +1304,18 @@ const COMPONENT_PROP_REGISTRY = {
1284
1304
  vocabulary: [
1285
1305
  "ChildrenProp",
1286
1306
  "ClassNameProp",
1287
- { field: "asChild", local: true, reason: "Radix Slot passthrough \u2014 merges onto the child" }
1307
+ { field: "asChild", local: true, reason: "Radix Slot passthrough \u2014 merges onto the child" },
1308
+ "BreakpointProp",
1309
+ {
1310
+ field: "iconHideFrom",
1311
+ local: true,
1312
+ reason: "Flex `hideFrom` scoped to the cell's icon slot \u2014 label-only from a breakpoint up without hand-wrapping the glyph (gh#726)."
1313
+ },
1314
+ {
1315
+ field: "labelHideBelow",
1316
+ local: true,
1317
+ reason: "Flex `hideBelow` scoped to the cell's label \u2014 icon-only below a breakpoint; visually hidden so the accessible name survives (gh#726)."
1318
+ }
1288
1319
  ]
1289
1320
  },
1290
1321
  NavListProp: {
@@ -3296,7 +3327,12 @@ const COMPONENT_PROP_REGISTRY = {
3296
3327
  "DisabledProp",
3297
3328
  "SizeProp",
3298
3329
  "ClassNameProp",
3299
- "IdProp"
3330
+ "IdProp",
3331
+ {
3332
+ field: "divided",
3333
+ local: true,
3334
+ reason: "Rules between the rows \u2014 a hairline on every node's block-start but the outline's first, full row width at every depth (gh#732). Default false, because chrome defaults quiet here (#44). Not antd's spelling: antd's Tree has no such capability, and `bordered` already means a grid's frame plus column rules on Table / Calendar / RangeTimeline; see docs/DESIGN-AUTHORITY.md."
3335
+ }
3300
3336
  ]
3301
3337
  },
3302
3338
  CardProp: {
@@ -3442,6 +3478,10 @@ const COMPONENT_PROP_REGISTRY = {
3442
3478
  file: "components/data-display/range-timeline.tsx",
3443
3479
  vocabulary: [
3444
3480
  "LabelProp",
3481
+ // The CANONICAL three-step axis, the same type DataTable takes — not a local subset. It
3482
+ // moves `--range-timeline-unit-width` only (42 / 56 / 70px per day), never the row or bar
3483
+ // height, so a compact Gantt is the same schedule with more days on screen (gh#730).
3484
+ "DensityProp",
3445
3485
  {
3446
3486
  field: "columns",
3447
3487
  local: true,
@@ -2229,13 +2229,13 @@
2229
2229
 
2230
2230
  .ui-calendar[data-bordered="true"] .ui-calendar-day,
2231
2231
  .ui-calendar[data-bordered="true"] .ui-calendar-weekday {
2232
- border-inline-start: 1px solid var(--calendar-grid-border-color, hsl(var(--input) / 0.5));
2233
- border-block-start: 1px solid var(--calendar-grid-border-color, hsl(var(--input) / 0.5));
2232
+ border-inline-start: 1px solid var(--calendar-grid-border-color, hsl(var(--border)));
2233
+ border-block-start: 1px solid var(--calendar-grid-border-color, hsl(var(--border)));
2234
2234
  }
2235
2235
 
2236
2236
  .ui-calendar[data-bordered="true"] .ui-calendar-week,
2237
2237
  .ui-calendar[data-bordered="true"] .ui-calendar-weekdays {
2238
- border-inline-end: 1px solid var(--calendar-grid-border-color, hsl(var(--input) / 0.5));
2238
+ border-inline-end: 1px solid var(--calendar-grid-border-color, hsl(var(--border)));
2239
2239
  }
2240
2240
 
2241
2241
  .ui-calendar[data-bordered="true"] .ui-calendar-weekday {
@@ -2247,7 +2247,7 @@
2247
2247
  }
2248
2248
 
2249
2249
  .ui-calendar[data-bordered="true"] .ui-calendar-grid {
2250
- border-block-end: 1px solid var(--calendar-grid-border-color, hsl(var(--input) / 0.5));
2250
+ border-block-end: 1px solid var(--calendar-grid-border-color, hsl(var(--border)));
2251
2251
  }
2252
2252
 
2253
2253
  .ui-calendar[data-bordered="true"] .ui-calendar-day.invisible {
@@ -2268,8 +2268,8 @@
2268
2268
 
2269
2269
  .ui-calendar[data-bordered="true"] .ui-calendar-week-number,
2270
2270
  .ui-calendar[data-bordered="true"] .ui-calendar-week-number-header {
2271
- border-inline-start: 1px solid var(--calendar-grid-border-color, hsl(var(--input) / 0.5));
2272
- border-block-start: 1px solid var(--calendar-grid-border-color, hsl(var(--input) / 0.5));
2271
+ border-inline-start: 1px solid var(--calendar-grid-border-color, hsl(var(--border)));
2272
+ border-block-start: 1px solid var(--calendar-grid-border-color, hsl(var(--border)));
2273
2273
  }
2274
2274
 
2275
2275
  .ui-calendar[data-bordered="true"] .ui-calendar-day {
@@ -2317,7 +2317,6 @@
2317
2317
  position: relative;
2318
2318
  display: flex;
2319
2319
  flex-direction: column;
2320
- gap: var(--calendar-month-space-gap);
2321
2320
  }
2322
2321
 
2323
2322
  .ui-calendar-caption {
@@ -464,23 +464,23 @@
464
464
  place-items: center;
465
465
  border: 1px solid transparent;
466
466
  border-radius: var(--radius-pill);
467
- background: var(--timeline-dot-done-background, hsl(var(--success)));
468
- color: hsl(var(--success-foreground));
467
+ background: var(--timeline-dot-done-background, hsl(var(--primary)));
468
+ color: var(--timeline-dot-done-foreground, hsl(var(--primary-foreground)));
469
469
  font-size: var(--timeline-note-font-size);
470
470
  font-weight: var(--font-weight-medium);
471
471
  line-height: 1;
472
472
  }
473
473
 
474
474
  .ui-timeline-dot[data-status="done"] {
475
- background: var(--timeline-dot-done-background, hsl(var(--success)));
476
- color: hsl(var(--success-foreground));
475
+ background: var(--timeline-dot-done-background, hsl(var(--primary)));
476
+ color: var(--timeline-dot-done-foreground, hsl(var(--primary-foreground)));
477
477
  }
478
478
 
479
479
  .ui-timeline-dot[data-status="current"],
480
480
  .ui-timeline-dot[data-current="true"] {
481
481
  background: var(--timeline-dot-current-background, hsl(var(--primary)));
482
482
  color: hsl(var(--primary-foreground));
483
- box-shadow: 0 0 0 3px hsl(var(--primary) / 0.18);
483
+ box-shadow: 0 0 0 var(--timeline-dot-current-ring-width) hsl(var(--primary) / 0.2);
484
484
  }
485
485
 
486
486
  .ui-timeline-dot[data-status="pending"] {
@@ -1356,10 +1356,13 @@
1356
1356
  display: grid;
1357
1357
  grid-template-columns: repeat(var(--range-timeline-units, 1), minmax(0, 1fr));
1358
1358
  }
1359
+
1359
1360
  .ui-range-timeline-column {
1360
1361
  min-inline-size: 0;
1361
1362
  overflow: hidden;
1362
1363
  padding: var(--space-2);
1364
+ padding-inline-start: calc(var(--space-2) + var(--range-timeline-grid-width));
1365
+ text-align: center;
1363
1366
  border-inline-end: var(--range-timeline-grid-width) solid
1364
1367
  hsl(var(--range-timeline-border-color));
1365
1368
  }
@@ -1392,12 +1395,19 @@
1392
1395
  .ui-range-timeline[data-bordered="true"] .ui-range-timeline-column,
1393
1396
  .ui-range-timeline[data-bordered="true"] .ui-range-timeline-label,
1394
1397
  .ui-range-timeline[data-bordered="true"] .ui-range-timeline-grid-column {
1395
- border-inline-end-color: var(--range-timeline-grid-color, hsl(var(--input) / 0.5));
1398
+ border-inline-end-color: var(--range-timeline-grid-color, hsl(var(--border)));
1396
1399
  }
1397
1400
  .ui-range-timeline[data-bordered="true"] .ui-range-timeline-header + .ui-range-timeline-header,
1398
1401
  .ui-range-timeline[data-bordered="true"] .ui-range-timeline-row {
1399
1402
  border-block-start: var(--range-timeline-grid-width) solid
1400
- var(--range-timeline-grid-color, hsl(var(--input) / 0.5));
1403
+ var(--range-timeline-grid-color, hsl(var(--border)));
1404
+ }
1405
+
1406
+ .ui-range-timeline[data-density="compact"] {
1407
+ --range-timeline-unit-width: var(--range-timeline-unit-width-compact);
1408
+ }
1409
+ .ui-range-timeline[data-density="comfortable"] {
1410
+ --range-timeline-unit-width: var(--range-timeline-unit-width-comfortable);
1401
1411
  }
1402
1412
  .ui-range-timeline-outside {
1403
1413
  position: absolute;
@@ -1904,6 +1914,14 @@
1904
1914
  content: "";
1905
1915
  }
1906
1916
 
1917
+ .ui-tree[data-divided="true"] .ui-tree-node {
1918
+ border-block-start: var(--stroke-hairline) solid var(--tree-divider-color, hsl(var(--border)));
1919
+ }
1920
+
1921
+ .ui-tree[data-divided="true"] > .ui-tree-node:first-child {
1922
+ border-block-start-color: transparent;
1923
+ }
1924
+
1907
1925
  .ui-tree-loading {
1908
1926
  display: flex;
1909
1927
  align-items: center;