@godxjp/ui 27.8.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 (34) 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.d.ts +1 -1
  8. package/dist/components/layout/topbar.js +2 -0
  9. package/dist/contracts/measurement.json +1 -1
  10. package/dist/props/components/data-display.prop.d.ts +11 -0
  11. package/dist/props/components/data-entry.prop.d.ts +6 -3
  12. package/dist/props/components/layout.prop.d.ts +40 -0
  13. package/dist/props/registry.d.ts +20 -4
  14. package/dist/props/registry.js +32 -3
  15. package/dist/styles/control.css +6 -7
  16. package/dist/styles/data-display-layout.css +25 -7
  17. package/dist/styles/data-entry-layout.css +13 -0
  18. package/dist/styles/layout.css +8 -0
  19. package/dist/styles/shell-layout.css +43 -1
  20. package/dist/tokens/components/control.css +5 -2
  21. package/dist/tokens/components/data-display.css +10 -1
  22. package/dist/tokens/components/shell.css +3 -0
  23. package/dist/tokens/components/tree.css +2 -0
  24. package/docs/DESIGN-AUTHORITY.md +20 -0
  25. package/docs/FRAME-COVERAGE-REPORT.md +1 -1
  26. package/docs/data-display/timeline.tsx +77 -1
  27. package/docs/data-display/tree.tsx +94 -0
  28. package/docs/data-entry/calendar.tsx +3 -2
  29. package/docs/general/icon.tsx +3 -1
  30. package/docs/layout/app-shell-narrow-bar.tsx +205 -0
  31. package/docs/layout/app-shell.tsx +10 -0
  32. package/docs/layout/topbar.tsx +11 -1
  33. package/package.json +2 -2
  34. 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 })
@@ -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.8.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
  };
@@ -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";
@@ -2816,7 +2828,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
2816
2828
  readonly TreeProp: {
2817
2829
  readonly group: "data-display";
2818
2830
  readonly file: "components/data-display.prop.ts";
2819
- 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
+ }];
2820
2836
  };
2821
2837
  readonly CardProp: {
2822
2838
  readonly group: "data-display";
@@ -2943,7 +2959,7 @@ export declare const COMPONENT_PROP_REGISTRY: {
2943
2959
  readonly RangeTimelineProp: {
2944
2960
  readonly group: "data-display";
2945
2961
  readonly file: "components/data-display/range-timeline.tsx";
2946
- readonly vocabulary: readonly ["LabelProp", {
2962
+ readonly vocabulary: readonly ["LabelProp", "DensityProp", {
2947
2963
  readonly field: "columns";
2948
2964
  readonly local: true;
2949
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",
@@ -3307,7 +3327,12 @@ const COMPONENT_PROP_REGISTRY = {
3307
3327
  "DisabledProp",
3308
3328
  "SizeProp",
3309
3329
  "ClassNameProp",
3310
- "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
+ }
3311
3336
  ]
3312
3337
  },
3313
3338
  CardProp: {
@@ -3453,6 +3478,10 @@ const COMPONENT_PROP_REGISTRY = {
3453
3478
  file: "components/data-display/range-timeline.tsx",
3454
3479
  vocabulary: [
3455
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",
3456
3485
  {
3457
3486
  field: "columns",
3458
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;
@@ -448,6 +448,7 @@
448
448
 
449
449
  .ui-upload-row {
450
450
  display: flex;
451
+ flex-wrap: wrap;
451
452
  align-items: center;
452
453
  gap: var(--upload-row-space-gap);
453
454
  padding-inline: var(--upload-row-space-inline);
@@ -462,6 +463,18 @@
462
463
  flex: 1 1 0%;
463
464
  }
464
465
 
466
+ .ui-upload-row-actions {
467
+ display: flex;
468
+ flex-wrap: wrap;
469
+ align-items: center;
470
+ gap: var(--upload-row-space-gap);
471
+ margin-inline-start: auto;
472
+ }
473
+
474
+ .ui-upload-row-actions:empty {
475
+ display: none;
476
+ }
477
+
465
478
  .ui-upload-row-icon {
466
479
  inline-size: var(--upload-row-icon-size);
467
480
  block-size: var(--upload-row-icon-size);
@@ -1450,6 +1450,7 @@
1450
1450
 
1451
1451
  @media (width < 40rem) {
1452
1452
  .ui-flex[data-hide-below="sm"],
1453
+ .app-topbar-brand[data-hide-below="sm"],
1453
1454
  .ui-topbar-item[data-hide-below="sm"],
1454
1455
  [data-slot="table-head"][data-hide-below="sm"],
1455
1456
  [data-slot="table-cell"][data-hide-below="sm"] {
@@ -1459,6 +1460,7 @@
1459
1460
 
1460
1461
  @media (width < 48rem) {
1461
1462
  .ui-flex[data-hide-below="md"],
1463
+ .app-topbar-brand[data-hide-below="md"],
1462
1464
  .ui-topbar-item[data-hide-below="md"],
1463
1465
  [data-slot="table-head"][data-hide-below="md"],
1464
1466
  [data-slot="table-cell"][data-hide-below="md"] {
@@ -1468,6 +1470,7 @@
1468
1470
 
1469
1471
  @media (width < 64rem) {
1470
1472
  .ui-flex[data-hide-below="lg"],
1473
+ .app-topbar-brand[data-hide-below="lg"],
1471
1474
  .ui-topbar-item[data-hide-below="lg"],
1472
1475
  [data-slot="table-head"][data-hide-below="lg"],
1473
1476
  [data-slot="table-cell"][data-hide-below="lg"] {
@@ -1477,6 +1480,7 @@
1477
1480
 
1478
1481
  @media (width < 80rem) {
1479
1482
  .ui-flex[data-hide-below="xl"],
1483
+ .app-topbar-brand[data-hide-below="xl"],
1480
1484
  .ui-topbar-item[data-hide-below="xl"],
1481
1485
  [data-slot="table-head"][data-hide-below="xl"],
1482
1486
  [data-slot="table-cell"][data-hide-below="xl"] {
@@ -1486,6 +1490,7 @@
1486
1490
 
1487
1491
  @media (width >= 40rem) {
1488
1492
  .ui-flex[data-hide-from="sm"],
1493
+ .app-topbar-brand[data-hide-from="sm"],
1489
1494
  .ui-topbar-item-icon[data-hide-from="sm"] {
1490
1495
  display: none;
1491
1496
  }
@@ -1493,6 +1498,7 @@
1493
1498
 
1494
1499
  @media (width >= 48rem) {
1495
1500
  .ui-flex[data-hide-from="md"],
1501
+ .app-topbar-brand[data-hide-from="md"],
1496
1502
  .ui-topbar-item-icon[data-hide-from="md"] {
1497
1503
  display: none;
1498
1504
  }
@@ -1500,6 +1506,7 @@
1500
1506
 
1501
1507
  @media (width >= 64rem) {
1502
1508
  .ui-flex[data-hide-from="lg"],
1509
+ .app-topbar-brand[data-hide-from="lg"],
1503
1510
  .ui-topbar-item-icon[data-hide-from="lg"] {
1504
1511
  display: none;
1505
1512
  }
@@ -1507,6 +1514,7 @@
1507
1514
 
1508
1515
  @media (width >= 80rem) {
1509
1516
  .ui-flex[data-hide-from="xl"],
1517
+ .app-topbar-brand[data-hide-from="xl"],
1510
1518
  .ui-topbar-item-icon[data-hide-from="xl"] {
1511
1519
  display: none;
1512
1520
  }