@godxjp/ui 27.8.0 → 27.10.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.
- package/dist/components/data-display/range-timeline.d.ts +19 -0
- package/dist/components/data-display/range-timeline.js +2 -0
- package/dist/components/data-display/tree.js +2 -0
- package/dist/components/data-entry/upload.d.ts +1 -1
- package/dist/components/data-entry/upload.js +19 -16
- package/dist/components/general/button.d.ts +1 -0
- package/dist/components/general/button.js +10 -2
- package/dist/components/layout/app-shell.d.ts +1 -1
- package/dist/components/layout/app-shell.js +8 -2
- package/dist/components/layout/page-container.d.ts +1 -1
- package/dist/components/layout/page-container.js +12 -2
- package/dist/components/layout/topbar.d.ts +1 -1
- package/dist/components/layout/topbar.js +2 -0
- package/dist/components/ui/toggle-group.d.ts +4 -0
- package/dist/components/ui/toggle-group.js +10 -2
- package/dist/components/ui/toggle.d.ts +4 -2
- package/dist/components/ui/toggle.js +22 -3
- package/dist/contracts/measurement.json +1 -1
- package/dist/props/components/data-display.prop.d.ts +11 -0
- package/dist/props/components/data-entry.prop.d.ts +22 -3
- package/dist/props/components/general.prop.d.ts +12 -0
- package/dist/props/components/index.d.ts +1 -1
- package/dist/props/components/layout.prop.d.ts +60 -1
- package/dist/props/registry.d.ts +27 -6
- package/dist/props/registry.js +42 -3
- package/dist/styles/control.css +17 -7
- package/dist/styles/data-display-layout.css +25 -7
- package/dist/styles/data-entry-layout.css +13 -0
- package/dist/styles/layout.css +8 -0
- package/dist/styles/shell-layout.css +43 -1
- package/dist/styles/toggle.css +5 -0
- package/dist/tokens/components/control.css +5 -2
- package/dist/tokens/components/data-display.css +10 -1
- package/dist/tokens/components/shell.css +3 -0
- package/dist/tokens/components/toggle.css +7 -0
- package/dist/tokens/components/tree.css +2 -0
- package/docs/DESIGN-AUTHORITY.md +20 -0
- package/docs/FRAME-COVERAGE-REPORT.md +1 -1
- package/docs/data-display/timeline.tsx +77 -1
- package/docs/data-display/tree.tsx +94 -0
- package/docs/data-entry/calendar.tsx +3 -2
- package/docs/data-entry/toggle-count.tsx +51 -0
- package/docs/data-entry/toggle-group.tsx +40 -2
- package/docs/data-entry/toggle.tsx +54 -2
- package/docs/data-entry/upload.tsx +44 -0
- package/docs/general/button/index.tsx +18 -6
- package/docs/general/icon.tsx +3 -1
- package/docs/layout/app-shell-narrow-bar.tsx +205 -0
- package/docs/layout/app-shell.tsx +10 -0
- package/docs/layout/page-container.tsx +67 -1
- package/docs/layout/topbar.tsx +11 -1
- package/package.json +2 -2
- 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)
|
|
@@ -4,4 +4,4 @@ export type { UploadProp, UploadProp as UploadProps, UploadFileItemProp, UploadV
|
|
|
4
4
|
export type { UploadFileItem, UploadVariant, UploadCommitAction } from "./upload-types.js";
|
|
5
5
|
export { collectUploadCommitActions, createUploadItem, UPLOAD_LIST_IGNORE } from "./upload-types.js";
|
|
6
6
|
export { useUploadDraft } from "./use-upload-draft.js";
|
|
7
|
-
export declare function Upload({ variant, listType, triggerSize, triggerVariant, value, defaultValue, onValueChange, accept: acceptProp, multiple: multipleProp, maxCount: maxCountProp, maxSizeBytes, disabled: disabledProp, readOnly, directory, pastable, openFileDialogOnClick, name, action, method, headers, data, withCredentials, beforeUpload, onReject, onRemove, onPreview, onDownload, previewFile, onDrop, showUploadList, itemRender, removable, onUpload, id, className, children, ...ariaProps }: UploadProp): React.JSX.Element;
|
|
7
|
+
export declare function Upload({ variant, listType, triggerSize, triggerVariant, triggerIcon: TriggerIcon, value, defaultValue, onValueChange, accept: acceptProp, multiple: multipleProp, maxCount: maxCountProp, maxSizeBytes, disabled: disabledProp, readOnly, directory, pastable, openFileDialogOnClick, name, action, method, headers, data, withCredentials, beforeUpload, onReject, onRemove, onPreview, onDownload, previewFile, onDrop, showUploadList, itemRender, removable, onUpload, id, className, children, ...ariaProps }: UploadProp): React.JSX.Element;
|
|
@@ -70,6 +70,7 @@ function Upload({
|
|
|
70
70
|
listType,
|
|
71
71
|
triggerSize,
|
|
72
72
|
triggerVariant = "outline",
|
|
73
|
+
triggerIcon: TriggerIcon = UploadIcon,
|
|
73
74
|
value,
|
|
74
75
|
defaultValue,
|
|
75
76
|
onValueChange,
|
|
@@ -498,7 +499,7 @@ function Upload({
|
|
|
498
499
|
"aria-label": triggerAriaLabel,
|
|
499
500
|
children: [
|
|
500
501
|
/* @__PURE__ */ jsx(
|
|
501
|
-
|
|
502
|
+
TriggerIcon,
|
|
502
503
|
{
|
|
503
504
|
className: "ui-upload-trigger-icon",
|
|
504
505
|
"data-with-label": iconOnly ? void 0 : "",
|
|
@@ -772,21 +773,23 @@ function UploadFileList({
|
|
|
772
773
|
] }),
|
|
773
774
|
item.status === "uploading" && /* @__PURE__ */ jsx(Progress, { value: item.percent ?? 0, "aria-label": t("dataEntry.upload.uploading") })
|
|
774
775
|
] }),
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
776
|
+
/* @__PURE__ */ jsxs("div", { className: "ui-upload-row-actions", children: [
|
|
777
|
+
onPreview && (hasCustomPreview || item.previewUrl) && /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => onPreview(item), children: t("dataEntry.upload.preview") }),
|
|
778
|
+
onDownload && /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => onDownload(item), children: t("dataEntry.upload.download") }),
|
|
779
|
+
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") }),
|
|
780
|
+
onCancel && item.status === "uploading" && /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "ghost", onClick: () => onCancel(item.uid), children: t("dataEntry.upload.cancel") }),
|
|
781
|
+
onRemove && /* @__PURE__ */ jsx(
|
|
782
|
+
Button,
|
|
783
|
+
{
|
|
784
|
+
type: "button",
|
|
785
|
+
size: "sm",
|
|
786
|
+
variant: "ghost",
|
|
787
|
+
"aria-label": t("dataEntry.upload.removeFile", { name: item.name }),
|
|
788
|
+
onClick: () => onRemove(item.uid),
|
|
789
|
+
children: /* @__PURE__ */ jsx(X, { className: "ui-upload-row-icon", "aria-hidden": "true" })
|
|
790
|
+
}
|
|
791
|
+
)
|
|
792
|
+
] })
|
|
790
793
|
] });
|
|
791
794
|
return /* @__PURE__ */ jsx("li", { children: itemRender ? itemRender(node, item, items, {
|
|
792
795
|
remove: () => onRemove?.(item.uid),
|
|
@@ -71,6 +71,7 @@ const Button = React.forwardRef(
|
|
|
71
71
|
count,
|
|
72
72
|
overflowCount = 99,
|
|
73
73
|
showZero = true,
|
|
74
|
+
countLabel,
|
|
74
75
|
disabled,
|
|
75
76
|
type,
|
|
76
77
|
children,
|
|
@@ -84,8 +85,14 @@ const Button = React.forwardRef(
|
|
|
84
85
|
loadingText ?? children
|
|
85
86
|
] }) : children;
|
|
86
87
|
const showCount = !asChild && count != null && (count !== 0 || showZero);
|
|
87
|
-
const
|
|
88
|
-
const
|
|
88
|
+
const countText = showCount && count != null && count > overflowCount ? `${numberFormat(locale).format(overflowCount)}+` : count != null ? numberFormat(locale).format(count) : "";
|
|
89
|
+
const spokenCount = countLabel ? `${countText} ${countLabel}` : countText;
|
|
90
|
+
const ariaLabel = props["aria-label"];
|
|
91
|
+
const foldedAriaLabel = showCount && ariaLabel != null ? { "aria-label": `${ariaLabel}, ${spokenCount}` } : null;
|
|
92
|
+
const countNode = showCount ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
93
|
+
/* @__PURE__ */ jsx("span", { "data-slot": "button-count", className: "ui-button-count", "aria-hidden": "true", children: countText }),
|
|
94
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: `, ${spokenCount}` })
|
|
95
|
+
] }) : null;
|
|
89
96
|
return /* @__PURE__ */ jsx(
|
|
90
97
|
Comp,
|
|
91
98
|
{
|
|
@@ -109,6 +116,7 @@ const Button = React.forwardRef(
|
|
|
109
116
|
),
|
|
110
117
|
ref,
|
|
111
118
|
...props,
|
|
119
|
+
...foldedAriaLabel,
|
|
112
120
|
children: asChild ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
113
121
|
content,
|
|
114
122
|
countNode
|
|
@@ -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:
|
|
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:
|
|
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 })
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PageContainerProp, PageInsetProp } from "../../props/components/layout.prop.js";
|
|
2
|
-
export type { PageContainerProp, PageContainerProp as PageContainerProps, } from "../../props/components/layout.prop.js";
|
|
2
|
+
export type { PageContainerProp, PageContainerProp as PageContainerProps, PageContainerExtraProp, } from "../../props/components/layout.prop.js";
|
|
3
3
|
export type { BreadcrumbItemProp, BreadcrumbItemProp as BreadcrumbItem, } from "../../props/vocabulary/navigation.prop.js";
|
|
4
4
|
export declare function PageContainerInset({ className, children, ...props }: PageInsetProp): import("react").JSX.Element;
|
|
5
5
|
declare function PageContainerRoot({ title, subtitle, status, extra, toolbar, footer, toolbarPad, footerPad, breadcrumb, breadcrumbLabel, breadcrumbAriaLabel, linkComponent: LinkComponent, headerLoading, density, variant, preset, headerLayout, headerScale, measure, stickyFooter, footerReveal, fill, children, className, }: PageContainerProp): import("react").JSX.Element;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useEffect, useRef, useState } from "react";
|
|
3
|
+
import { isValidElement, useEffect, useRef, useState } from "react";
|
|
4
4
|
import { ChevronRight } from "lucide-react";
|
|
5
5
|
import { useTranslation } from "../../i18n/use-translation.js";
|
|
6
6
|
import { cn } from "../../lib/utils.js";
|
|
@@ -33,6 +33,12 @@ function useFooterReveal(enabled) {
|
|
|
33
33
|
function PageContainerInset({ className, children, ...props }) {
|
|
34
34
|
return /* @__PURE__ */ jsx("div", { className: cn("ui-page-container-inset", className), ...props, children });
|
|
35
35
|
}
|
|
36
|
+
function resolvePageExtra(extra) {
|
|
37
|
+
if (extra === void 0 || extra === null || extra === false) return {};
|
|
38
|
+
const isSlotMap = typeof extra === "object" && !isValidElement(extra) && !Array.isArray(extra);
|
|
39
|
+
if (isSlotMap) return extra;
|
|
40
|
+
return { start: extra };
|
|
41
|
+
}
|
|
36
42
|
function footerPadStyle(footerPad) {
|
|
37
43
|
const style = padStyle(footerPad, void 0);
|
|
38
44
|
const end = style?.paddingInlineEnd ?? style?.padding;
|
|
@@ -68,6 +74,7 @@ function PageContainerRoot({
|
|
|
68
74
|
const reveal = stickyFooter && footer != null && footerReveal === "onScroll";
|
|
69
75
|
const { headerRef, revealed } = useFooterReveal(reveal);
|
|
70
76
|
const { t } = useTranslation();
|
|
77
|
+
const { start: extraStart, end: extraEnd } = resolvePageExtra(extra);
|
|
71
78
|
return /* @__PURE__ */ jsxs(
|
|
72
79
|
"div",
|
|
73
80
|
{
|
|
@@ -149,7 +156,10 @@ function PageContainerRoot({
|
|
|
149
156
|
)
|
|
150
157
|
) : subtitle && /* @__PURE__ */ jsx("p", { className: "ui-page-subtitle", children: subtitle })
|
|
151
158
|
] }),
|
|
152
|
-
|
|
159
|
+
(extraStart != null || extraEnd != null) && /* @__PURE__ */ jsxs("div", { className: "ui-page-header-extra", children: [
|
|
160
|
+
extraStart,
|
|
161
|
+
extraEnd
|
|
162
|
+
] })
|
|
153
163
|
] })
|
|
154
164
|
]
|
|
155
165
|
}
|
|
@@ -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),
|
|
@@ -2,9 +2,11 @@ import * as React from "react";
|
|
|
2
2
|
import { type ToggleCountFields, type ToggleProp } from "./toggle.js";
|
|
3
3
|
type ToggleGroupVariant = ToggleProp["variant"];
|
|
4
4
|
type ToggleGroupSize = ToggleProp["size"];
|
|
5
|
+
type ToggleGroupShape = ToggleProp["shape"];
|
|
5
6
|
type ToggleGroupBaseProp = Omit<React.ComponentPropsWithoutRef<"div">, "defaultValue" | "dir"> & {
|
|
6
7
|
variant?: ToggleGroupVariant;
|
|
7
8
|
size?: ToggleGroupSize;
|
|
9
|
+
shape?: ToggleGroupShape;
|
|
8
10
|
/** Disable every item at once — RAC `isDisabled`. */
|
|
9
11
|
disabled?: boolean;
|
|
10
12
|
/** Which way the arrow keys walk the group. */
|
|
@@ -51,6 +53,7 @@ export type ToggleGroupItemProp = Omit<React.ComponentPropsWithoutRef<"button">,
|
|
|
51
53
|
value: string;
|
|
52
54
|
variant?: ToggleGroupVariant;
|
|
53
55
|
size?: ToggleGroupSize;
|
|
56
|
+
shape?: ToggleGroupShape;
|
|
54
57
|
};
|
|
55
58
|
export type ToggleGroupItemProps = ToggleGroupItemProp;
|
|
56
59
|
export declare const ToggleGroupItem: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref">, "value"> & ToggleCountFields & {
|
|
@@ -61,5 +64,6 @@ export declare const ToggleGroupItem: React.ForwardRefExoticComponent<Omit<Omit<
|
|
|
61
64
|
value: string;
|
|
62
65
|
variant?: ToggleGroupVariant;
|
|
63
66
|
size?: ToggleGroupSize;
|
|
67
|
+
shape?: ToggleGroupShape;
|
|
64
68
|
} & React.RefAttributes<HTMLButtonElement>>;
|
|
65
69
|
export {};
|
|
@@ -31,6 +31,7 @@ const ToggleGroup = React.forwardRef(
|
|
|
31
31
|
className,
|
|
32
32
|
variant,
|
|
33
33
|
size,
|
|
34
|
+
shape,
|
|
34
35
|
children,
|
|
35
36
|
type,
|
|
36
37
|
value,
|
|
@@ -40,7 +41,7 @@ const ToggleGroup = React.forwardRef(
|
|
|
40
41
|
loop: _loop,
|
|
41
42
|
...props
|
|
42
43
|
}, ref) => {
|
|
43
|
-
const context = React.useMemo(() => ({ variant, size }), [variant, size]);
|
|
44
|
+
const context = React.useMemo(() => ({ variant, size, shape }), [variant, size, shape]);
|
|
44
45
|
const selectedKeys = React.useMemo(() => toSelectedKeys(value), [value]);
|
|
45
46
|
const defaultSelectedKeys = React.useMemo(() => toSelectedKeys(defaultValue), [defaultValue]);
|
|
46
47
|
const handleSelectionChange = (keys) => {
|
|
@@ -58,6 +59,7 @@ const ToggleGroup = React.forwardRef(
|
|
|
58
59
|
"data-slot": "toggle-group",
|
|
59
60
|
"data-variant": variant,
|
|
60
61
|
"data-size": size,
|
|
62
|
+
"data-shape": shape,
|
|
61
63
|
className: cn("ui-toggle-group", className),
|
|
62
64
|
...props,
|
|
63
65
|
selectionMode: type,
|
|
@@ -77,6 +79,7 @@ const ToggleGroupItem = React.forwardRef(
|
|
|
77
79
|
className,
|
|
78
80
|
variant,
|
|
79
81
|
size,
|
|
82
|
+
shape,
|
|
80
83
|
count,
|
|
81
84
|
overflowCount,
|
|
82
85
|
showZero,
|
|
@@ -90,6 +93,7 @@ const ToggleGroupItem = React.forwardRef(
|
|
|
90
93
|
const context = React.useContext(ToggleGroupContext);
|
|
91
94
|
const resolvedVariant = variant ?? context.variant;
|
|
92
95
|
const resolvedSize = size ?? context.size;
|
|
96
|
+
const resolvedShape = shape ?? context.shape;
|
|
93
97
|
const { pill, resolvedAriaLabel } = useCounterPill({
|
|
94
98
|
count,
|
|
95
99
|
overflowCount,
|
|
@@ -107,8 +111,12 @@ const ToggleGroupItem = React.forwardRef(
|
|
|
107
111
|
"data-state": isPressed ? "on" : "off",
|
|
108
112
|
"data-variant": resolvedVariant,
|
|
109
113
|
"data-size": resolvedSize,
|
|
114
|
+
"data-shape": resolvedShape,
|
|
110
115
|
"aria-label": resolvedAriaLabel,
|
|
111
|
-
className: cn(
|
|
116
|
+
className: cn(
|
|
117
|
+
toggleVariants({ variant: resolvedVariant, size: resolvedSize, shape: resolvedShape }),
|
|
118
|
+
className
|
|
119
|
+
),
|
|
112
120
|
...props,
|
|
113
121
|
id: value,
|
|
114
122
|
isDisabled: disabled,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type VariantProps } from "class-variance-authority";
|
|
3
3
|
declare const toggleVariants: (props?: ({
|
|
4
|
-
variant?: "default" | "outline" | null | undefined;
|
|
4
|
+
variant?: "default" | "outline" | "soft" | null | undefined;
|
|
5
5
|
size?: "lg" | "md" | "sm" | "xs" | null | undefined;
|
|
6
|
+
shape?: "default" | "pill" | "sharp" | null | undefined;
|
|
6
7
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
8
|
/**
|
|
8
9
|
* Not exported on its own — it is folded into `ToggleProp` and `ToggleGroupItemProp` so there is
|
|
@@ -68,8 +69,9 @@ declare function restoreDomProps<P extends {
|
|
|
68
69
|
export type ToggleProp = React.ComponentPropsWithoutRef<"button"> & TogglePressedFields & VariantProps<typeof toggleVariants> & ToggleCountFields;
|
|
69
70
|
export type ToggleProps = ToggleProp;
|
|
70
71
|
export declare const Toggle: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & TogglePressedFields & VariantProps<(props?: ({
|
|
71
|
-
variant?: "default" | "outline" | null | undefined;
|
|
72
|
+
variant?: "default" | "outline" | "soft" | null | undefined;
|
|
72
73
|
size?: "lg" | "md" | "sm" | "xs" | null | undefined;
|
|
74
|
+
shape?: "default" | "pill" | "sharp" | null | undefined;
|
|
73
75
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string> & ToggleCountFields & React.RefAttributes<HTMLButtonElement>>;
|
|
74
76
|
export { toggleVariants, useCounterPill, restoreDomProps };
|
|
75
77
|
export type { ToggleCountFields, TogglePressedFields };
|
|
@@ -10,7 +10,15 @@ const toggleVariants = cva("ui-toggle", {
|
|
|
10
10
|
variants: {
|
|
11
11
|
variant: {
|
|
12
12
|
default: "ui-toggle-default",
|
|
13
|
-
outline: "ui-toggle-outline"
|
|
13
|
+
outline: "ui-toggle-outline",
|
|
14
|
+
// The REST FILL (gh#734). `default` is a 1px TRANSPARENT border and `outline` a hairline on
|
|
15
|
+
// `--background`, so neither draws a chip that reads as filled before it is pressed — which
|
|
16
|
+
// is why a consumer building a tag-filter panel reported its tags "look transparent" and
|
|
17
|
+
// fell back to `Button variant="secondary" shape="pill" aria-pressed`, a control that paints
|
|
18
|
+
// no pressed state at all. `soft` is antd `Tag`'s resting surface, on the SAME
|
|
19
|
+
// `hsl(var(--secondary))` fill `Badge variant="secondary"` and `Button variant="secondary"`
|
|
20
|
+
// already paint, so a chip, a badge and a button on one row are one family.
|
|
21
|
+
soft: "ui-toggle-soft"
|
|
14
22
|
},
|
|
15
23
|
size: {
|
|
16
24
|
// The fourth step of the shared control ladder (gh#716): 24px, `--control-height-xs`, the
|
|
@@ -20,11 +28,21 @@ const toggleVariants = cva("ui-toggle", {
|
|
|
20
28
|
sm: "ui-toggle-sm",
|
|
21
29
|
md: "ui-toggle-default-size",
|
|
22
30
|
lg: "ui-toggle-lg"
|
|
31
|
+
},
|
|
32
|
+
// Corner shape at parity with `Button` and `Badge` — the same three values mapped to the same
|
|
33
|
+
// two radius tokens, so `shape="pill"` means one thing across the library. `default` is empty
|
|
34
|
+
// on purpose: it leaves `.ui-toggle`'s own `--radius-md` in place instead of restating it,
|
|
35
|
+
// exactly as `badgeVariants` does.
|
|
36
|
+
shape: {
|
|
37
|
+
default: "",
|
|
38
|
+
pill: "rounded-[var(--radius-pill)]",
|
|
39
|
+
sharp: "rounded-[var(--radius-sharp)]"
|
|
23
40
|
}
|
|
24
41
|
},
|
|
25
42
|
defaultVariants: {
|
|
26
43
|
variant: "default",
|
|
27
|
-
size: "md"
|
|
44
|
+
size: "md",
|
|
45
|
+
shape: "default"
|
|
28
46
|
}
|
|
29
47
|
});
|
|
30
48
|
function useCounterPill({
|
|
@@ -82,6 +100,7 @@ const Toggle = React.forwardRef(
|
|
|
82
100
|
className,
|
|
83
101
|
variant,
|
|
84
102
|
size,
|
|
103
|
+
shape,
|
|
85
104
|
count,
|
|
86
105
|
overflowCount,
|
|
87
106
|
showZero,
|
|
@@ -113,7 +132,7 @@ const Toggle = React.forwardRef(
|
|
|
113
132
|
"data-slot": "toggle",
|
|
114
133
|
"data-state": isPressed ? "on" : "off",
|
|
115
134
|
"aria-label": resolvedAriaLabel,
|
|
116
|
-
className: cn(toggleVariants({ variant, size }), className),
|
|
135
|
+
className: cn(toggleVariants({ variant, size, shape }), className),
|
|
117
136
|
...props,
|
|
118
137
|
isSelected: isPressed,
|
|
119
138
|
onChange: onSelectionChange,
|
|
@@ -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.
|
|
3
|
+
"version": "27.10.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
|
|
749
|
-
*
|
|
750
|
-
*
|
|
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 */
|
|
@@ -1543,6 +1546,22 @@ export type UploadProp = FieldA11yProps & {
|
|
|
1543
1546
|
* @see Button — same variant scale
|
|
1544
1547
|
*/
|
|
1545
1548
|
triggerVariant?: "default" | "destructive" | "outline" | "dashed" | "secondary" | "ghost" | "link";
|
|
1549
|
+
/**
|
|
1550
|
+
* `variant="button"` only — the glyph COMPONENT the trigger draws, `triggerIcon={Plus}` rather
|
|
1551
|
+
* than `<Plus />`. Defaults to the upload arrow.
|
|
1552
|
+
*
|
|
1553
|
+
* It exists because the glyph was hard-coded and `triggerVariant` only moves emphasis, so a
|
|
1554
|
+
* "create new" action that HAPPENS to be an upload could not carry a plus and had to announce
|
|
1555
|
+
* itself as an upload (gh#734). The component is rendered onto the `<svg>` itself, at the same
|
|
1556
|
+
* `--upload-row-icon-size` the built-in glyph uses, so a swapped icon cannot change the
|
|
1557
|
+
* trigger's metrics.
|
|
1558
|
+
*
|
|
1559
|
+
* Typed as the widened glyph component (SVG props + ref) rather than the narrower `IconProp`,
|
|
1560
|
+
* for the reason `IconGlyphProp.as` already records: the library hands the glyph its class, its
|
|
1561
|
+
* `aria-hidden` and its label-spacing attribute, none of which `IconProp` can accept. Every
|
|
1562
|
+
* `lucide-react` icon and every `Icon`-compatible component qualifies.
|
|
1563
|
+
*/
|
|
1564
|
+
triggerIcon?: React.ComponentType<React.SVGProps<SVGSVGElement> & React.RefAttributes<SVGSVGElement>>;
|
|
1546
1565
|
className?: ClassNameProp;
|
|
1547
1566
|
children?: React.ReactNode;
|
|
1548
1567
|
};
|
|
@@ -269,6 +269,18 @@ export type ButtonProp = React.ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
|
269
269
|
* `true` (a `0` pill shows); pass `false` to hide the pill at zero.
|
|
270
270
|
*/
|
|
271
271
|
showZero?: boolean;
|
|
272
|
+
/**
|
|
273
|
+
* Localized description of what the count MEANS, folded into the accessible name so the control
|
|
274
|
+
* never announces as a bare digit run. The SAME prop and the same contract `Toggle` has carried
|
|
275
|
+
* since gh#312 — without it a counted button measured `"Git3"` in the accessibility tree, not
|
|
276
|
+
* "Git, 3 pages" (gh#734).
|
|
277
|
+
*
|
|
278
|
+
* The pill itself is `aria-hidden` and the spoken form is an `sr-only` sibling, so the name
|
|
279
|
+
* reads `"<label>, <count> <countLabel>"` from the contents; with an explicit `aria-label`
|
|
280
|
+
* (an icon-only counted button) the same clause is folded into that instead. Pass a
|
|
281
|
+
* `t()`-resolved string — the library does not own this wording.
|
|
282
|
+
*/
|
|
283
|
+
countLabel?: string;
|
|
272
284
|
};
|
|
273
285
|
/**
|
|
274
286
|
* @see Reveal — entrance-motion primitive (staggered fade-up). Wraps content in a real element
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { AppLauncherApp, AppLauncherGroup, AppLauncherLabels, AppLauncherProp, AppShellProp, AuthFooterProp, AuthIdentityProp, OrgSwitcherLabels, OrgSwitcherOrganization, OrgSwitcherProp, DragAxisProp, DragBoundsProp, DraggablePanelLabels, DraggablePanelPlacementProp, DraggablePanelPositionProp, DraggablePanelProp, PageContainerProp, PageInsetProp, SidebarItemProp, SidebarProductProp, SidebarProp, SidebarSectionProp, TopbarProp, } from "./layout.prop.js";
|
|
1
|
+
export type { AppLauncherApp, AppLauncherGroup, AppLauncherLabels, AppLauncherProp, AppShellProp, AuthFooterProp, AuthIdentityProp, OrgSwitcherLabels, OrgSwitcherOrganization, OrgSwitcherProp, DragAxisProp, DragBoundsProp, DraggablePanelLabels, DraggablePanelPlacementProp, DraggablePanelPositionProp, DraggablePanelProp, PageContainerExtraProp, PageContainerProp, PageInsetProp, SidebarItemProp, SidebarProductProp, SidebarProp, SidebarSectionProp, TopbarProp, } from "./layout.prop.js";
|
|
2
2
|
export type { ButtonProp } from "./general.prop.js";
|
|
3
3
|
export type { CommandProp, InputProp, TextareaProp, FormFieldProp, SearchInputProp, CheckboxProp, CheckboxGroupProp, ChoiceOptionProp, RadioProp, RadioGroupProp, SwitchProp, SliderProp, CalendarProp, DatePickerProp, TimePickerProp, ColorPickerProp, UploadProp, UploadFileItemProp, UploadVariantProp, TreeOptionProp, TreeFieldNamesProp, CascaderProp, TreeSelectProp, ShowCheckedStrategyProp, TransferProp, TransferItemProp, } from "./data-entry.prop.js";
|
|
4
4
|
export type { AvatarProp, EmptyStateProp, DescriptionsProp, DescriptionsItemProp, BadgeProp, DataTableProp, QrCodeProp, } from "./data-display.prop.js";
|
|
@@ -22,6 +22,24 @@ export type PageContainerMeasureProp = "default" | "narrow" | "medium";
|
|
|
22
22
|
* `document` (default) — the row is the page's TITLE: a record, a form, a collection, a report.
|
|
23
23
|
*/
|
|
24
24
|
export type PageContainerHeaderScaleProp = "document" | "chrome";
|
|
25
|
+
/**
|
|
26
|
+
* @see PageContainer — the header's trailing slot, one node or two named sub-slots.
|
|
27
|
+
*
|
|
28
|
+
* The bare node is the shape every page already passes and stays the whole API for a single
|
|
29
|
+
* action cluster. `{ start, end }` splits that cluster in two so a page can put something AFTER
|
|
30
|
+
* the actions: the convention a consumer's four record screens share is identity → actions →
|
|
31
|
+
* pager LAST, and with one slot the pager had to live in a second header band inside the body,
|
|
32
|
+
* so the app carried two header shapes (gh#734).
|
|
33
|
+
*
|
|
34
|
+
* The shape is `TabsExtraProp`'s, deliberately — `Tabs.extra` already accepts exactly this union
|
|
35
|
+
* for exactly this reason, and a second spelling of one axis is what `check:prop-vocabulary`
|
|
36
|
+
* exists to prevent. Logical inline names (`start`/`end`, never `left`/`right`), so the slots
|
|
37
|
+
* swap sides under `dir="rtl"` with no second code path.
|
|
38
|
+
*/
|
|
39
|
+
export type PageContainerExtraProp = ExtraProp | {
|
|
40
|
+
start?: ReactNode;
|
|
41
|
+
end?: ReactNode;
|
|
42
|
+
};
|
|
25
43
|
/** @see PageContainer */
|
|
26
44
|
export type PageContainerProp = {
|
|
27
45
|
toolbarPad?: PadProp;
|
|
@@ -40,7 +58,8 @@ export type PageContainerProp = {
|
|
|
40
58
|
* violation) so the page's heading outline never disappears mid-load.
|
|
41
59
|
*/
|
|
42
60
|
headerLoading?: boolean;
|
|
43
|
-
|
|
61
|
+
/** @see PageContainerExtraProp */
|
|
62
|
+
extra?: PageContainerExtraProp;
|
|
44
63
|
/**
|
|
45
64
|
* FIXED chrome band between the page header and the scrolling body — a filter strip, a status
|
|
46
65
|
* bar, a "channel workflow" rail. It is a first-class page-chrome slot precisely because the
|
|
@@ -353,6 +372,28 @@ export type AppShellProp = {
|
|
|
353
372
|
topbarLeft?: ReactNode;
|
|
354
373
|
topbarRight?: ReactNode;
|
|
355
374
|
logo?: ReactNode;
|
|
375
|
+
/**
|
|
376
|
+
* The brand node a NARROW bar gets instead of `logo` — a mark without the wordmark, a shorter
|
|
377
|
+
* lockup, a different `viewBox` (gh#728).
|
|
378
|
+
*
|
|
379
|
+
* The brand cell shrinks without this prop: below the `sm` step it is capped at
|
|
380
|
+
* `--app-shell-brand-compact-max-inline-size` and anything past the cap is cropped from the
|
|
381
|
+
* inline-end. A CROP is all a stylesheet can do to artwork it did not author — `viewBox` is an
|
|
382
|
+
* attribute, which is why consumers were re-cropping their own SVG through a media-query hook.
|
|
383
|
+
* Passing a node here is how you CHOOSE what the narrow bar shows instead.
|
|
384
|
+
*
|
|
385
|
+
* Both nodes are rendered; the breakpoint drops one with `display: none`, so exactly one brand
|
|
386
|
+
* is ever in the accessibility tree. Applies to the brand IN THE BAR only: under the default
|
|
387
|
+
* `topbarSpan="content"` with a sidebar the brand sits at the head of the rail, which the
|
|
388
|
+
* responsive shell has already replaced with the drawer at that width.
|
|
389
|
+
*/
|
|
390
|
+
logoCompact?: ReactNode;
|
|
391
|
+
/**
|
|
392
|
+
* The step at which `logoCompact` takes over — `Flex hideBelow`'s own vocabulary and the same
|
|
393
|
+
* canonical scale (sm 40rem · md 48rem · lg 64rem · xl 80rem). Defaults to `"sm"`, the step the
|
|
394
|
+
* brand cap uses. Ignored without `logoCompact`.
|
|
395
|
+
*/
|
|
396
|
+
logoCompactBelow?: BreakpointProp;
|
|
356
397
|
breadcrumb?: ReactNode;
|
|
357
398
|
footer?: ReactNode;
|
|
358
399
|
sidebarCollapsed?: boolean;
|
|
@@ -1318,6 +1359,24 @@ export type TopbarProp = Omit<React.HTMLAttributes<HTMLDivElement>, "children">
|
|
|
1318
1359
|
center?: ReactNode;
|
|
1319
1360
|
/** Inline-end cluster — settings pickers, notifications, the user menu. */
|
|
1320
1361
|
end?: ReactNode;
|
|
1362
|
+
/**
|
|
1363
|
+
* What a bar that does not fit does with the cells that do not fit (gh#728).
|
|
1364
|
+
*
|
|
1365
|
+
* - `"scroll"` (default) — the BAR scrolls on the inline axis while the `start` and `end`
|
|
1366
|
+
* clusters keep their cells whole (`start` floors at one cell, `end` at its content), so what
|
|
1367
|
+
* does not fit is off-port rather than half-painted. Every cell stays in the DOM and in the
|
|
1368
|
+
* accessibility tree, Tab reaches each one in order, and the browser scrolls a focused cell
|
|
1369
|
+
* fully into view; the scrollbar is suppressed (a horizontal bar inside a 48px chrome row
|
|
1370
|
+
* would eat the height that caused the deficit) so the pointer affordance is drag/wheel.
|
|
1371
|
+
* - `"clip"` — the pre-gh#728 behaviour: a cell past the cluster's edge is simply not painted.
|
|
1372
|
+
* Still focusable, still announced, invisible and unreachable by pointer. Choose it only for a
|
|
1373
|
+
* bar you have measured as never overflowing.
|
|
1374
|
+
*
|
|
1375
|
+
* Independent of `TopbarItem hideBelow`, which REMOVES a cell at a step: dropping a cell is the
|
|
1376
|
+
* consumer saying it does not belong on a phone, and that remains the way to spend the budget
|
|
1377
|
+
* deliberately. This prop is only about what happens once there is no budget left.
|
|
1378
|
+
*/
|
|
1379
|
+
overflow?: "scroll" | "clip";
|
|
1321
1380
|
/** Escape hatch — render fully custom bar content instead of the three slots. */
|
|
1322
1381
|
children?: ReactNode;
|
|
1323
1382
|
};
|