@godxjp/ui 33.10.1 → 33.11.2
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/DESIGN.md +1 -0
- package/README.md +2 -2
- package/agent/DESIGN.md +1 -0
- package/agent/START-HERE.md +4 -4
- package/agent/components/Cascader.json +1 -0
- package/agent/components/DatePicker.json +1 -0
- package/agent/components/Input.json +1 -0
- package/agent/components/NumberInput.json +1 -0
- package/agent/components/PasswordInput.json +1 -0
- package/agent/components/SearchInput.json +1 -0
- package/agent/components/Select.json +1 -0
- package/agent/components/TimePicker.json +1 -0
- package/agent/components/Topbar.json +8 -2
- package/agent/components/TopbarItem.json +7 -1
- package/agent/components/TreeSelect.json +1 -0
- package/agent/components.json +24 -3
- package/agent/index.json +4 -4
- package/agent/llms.txt +5 -5
- package/agent/tokens.json +19 -1
- package/dist/components/data-entry/input.js +16 -1
- package/dist/components/data-entry/search-input.js +1 -1
- package/dist/components/layout/topbar-item.d.ts +1 -0
- package/dist/components/layout/topbar-item.js +9 -4
- package/dist/components/layout/topbar.d.ts +1 -1
- package/dist/components/layout/topbar.js +25 -3
- package/dist/contracts/measurement.json +1 -1
- package/dist/props/components/layout.prop.d.ts +13 -0
- package/dist/props/registry.d.ts +9 -1
- package/dist/props/registry.js +10 -0
- package/dist/styles/control.css +131 -3
- package/dist/styles/layers.json +1 -1
- package/dist/styles/shell-layout.css +38 -0
- package/dist/styles.css +1 -1
- package/dist/tokens/components/control.css +4 -1
- package/dist/tokens/components/shell.css +3 -0
- package/docs/TOKENS.md +11 -0
- package/package.json +2 -2
- package/scripts/visual-audit.mjs +33 -3
|
@@ -11,6 +11,7 @@ function Topbar({
|
|
|
11
11
|
start,
|
|
12
12
|
center,
|
|
13
13
|
end,
|
|
14
|
+
identity,
|
|
14
15
|
className,
|
|
15
16
|
children,
|
|
16
17
|
height,
|
|
@@ -20,8 +21,10 @@ function Topbar({
|
|
|
20
21
|
...props
|
|
21
22
|
}) {
|
|
22
23
|
const barRef = React.useRef(null);
|
|
24
|
+
const controlsRef = React.useRef(null);
|
|
25
|
+
const hasIdentity = identity != null && children == null;
|
|
23
26
|
const foldable = overflow === "menu" && children == null;
|
|
24
|
-
const collapsed = useCollapsesToMenu(barRef, foldable);
|
|
27
|
+
const collapsed = useCollapsesToMenu(hasIdentity ? controlsRef : barRef, foldable);
|
|
25
28
|
const clusters = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
26
29
|
start != null ? /* @__PURE__ */ jsx("div", { "data-slot": "topbar-start", className: "ui-topbar-start", children: start }) : null,
|
|
27
30
|
center != null ? /* @__PURE__ */ jsx("div", { "data-slot": "topbar-center", className: "ui-topbar-center", children: center }) : null,
|
|
@@ -32,13 +35,26 @@ function Topbar({
|
|
|
32
35
|
{
|
|
33
36
|
ref: barRef,
|
|
34
37
|
"data-height": height,
|
|
38
|
+
"data-identity": hasIdentity ? "true" : void 0,
|
|
35
39
|
"data-overflow": overflow,
|
|
36
40
|
"data-collapsed": foldable ? String(collapsed) : void 0,
|
|
37
41
|
style: { ...style, ...padStyle(pad, void 0) },
|
|
38
42
|
"data-slot": "topbar",
|
|
39
43
|
className: cn("ui-topbar", className),
|
|
40
44
|
...props,
|
|
41
|
-
children: children ?? (
|
|
45
|
+
children: children ?? (hasIdentity ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
46
|
+
/* @__PURE__ */ jsx(
|
|
47
|
+
"div",
|
|
48
|
+
{
|
|
49
|
+
ref: controlsRef,
|
|
50
|
+
"data-slot": "topbar-controls",
|
|
51
|
+
"data-overflow": overflow,
|
|
52
|
+
className: "ui-topbar ui-topbar-controls",
|
|
53
|
+
children: collapsed ? /* @__PURE__ */ jsx(TopbarOverflowMenu, { children: clusters }) : clusters
|
|
54
|
+
}
|
|
55
|
+
),
|
|
56
|
+
/* @__PURE__ */ jsx("div", { "data-slot": "topbar-identity", className: "ui-topbar-identity", children: identity })
|
|
57
|
+
] }) : collapsed ? /* @__PURE__ */ jsx(TopbarOverflowMenu, { children: clusters }) : clusters)
|
|
42
58
|
}
|
|
43
59
|
);
|
|
44
60
|
}
|
|
@@ -69,7 +85,13 @@ function useCollapsesToMenu(ref, enabled) {
|
|
|
69
85
|
if (typeof ResizeObserver === "undefined") return void 0;
|
|
70
86
|
const observer = new ResizeObserver(update);
|
|
71
87
|
observer.observe(bar);
|
|
72
|
-
if (!collapsed)
|
|
88
|
+
if (!collapsed)
|
|
89
|
+
for (const cluster of bar.children) {
|
|
90
|
+
observer.observe(cluster);
|
|
91
|
+
if (cluster.getAttribute("data-slot") === "topbar-start") {
|
|
92
|
+
for (const cell of cluster.children) observer.observe(cell);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
73
95
|
return () => observer.disconnect();
|
|
74
96
|
}, [ref, enabled, collapsed]);
|
|
75
97
|
return enabled && collapsed;
|
|
@@ -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": "33.
|
|
3
|
+
"version": "33.11.2",
|
|
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,
|
|
@@ -1545,6 +1545,14 @@ export type TopbarProp = Omit<React.HTMLAttributes<HTMLDivElement>, "children">
|
|
|
1545
1545
|
center?: ReactNode;
|
|
1546
1546
|
/** Inline-end cluster — settings pickers, notifications, the user menu. */
|
|
1547
1547
|
end?: ReactNode;
|
|
1548
|
+
/**
|
|
1549
|
+
* Opt-in shared-device identity, pinned outside scrolling/overflow menus. Pass one
|
|
1550
|
+
* TopbarItem with `truncate` and an Avatar in `icon`; use a plain string name so its full
|
|
1551
|
+
* title is automatic. Never combine with hideBelow/labelHideBelow/iconHideFrom.
|
|
1552
|
+
* Capped by --topbar-identity-max-inline-size (40%); primary controls retain their floors.
|
|
1553
|
+
* At extreme widths only the other clusters scroll or move to the menu. Ignored with children.
|
|
1554
|
+
*/
|
|
1555
|
+
identity?: ReactNode;
|
|
1548
1556
|
/**
|
|
1549
1557
|
* What a bar that does not fit does with the cells that do not fit (gh#728).
|
|
1550
1558
|
*
|
|
@@ -1643,6 +1651,11 @@ export type TopbarItemProp = Omit<React.ButtonHTMLAttributes<HTMLButtonElement>,
|
|
|
1643
1651
|
* accessible name. Under `asChild` the child element's own children are the label.
|
|
1644
1652
|
*/
|
|
1645
1653
|
labelHideBelow?: BreakpointProp;
|
|
1654
|
+
/** Ellipse the label in the available width, keeping the icon and control minimum.
|
|
1655
|
+
* Same boolean vocabulary as Text.truncate. Overrides labelHideBelow; the complete text
|
|
1656
|
+
* remains the accessible name. String children automatically supply title (asChild too).
|
|
1657
|
+
*/
|
|
1658
|
+
truncate?: boolean;
|
|
1646
1659
|
/**
|
|
1647
1660
|
* Unread count OVERLAID on the cell's glyph — the notification-bell affordance the cell's own use
|
|
1648
1661
|
* cases name (gh#398). Pass the CONTENT ONLY, exactly like `SidebarItemProp.badge`: a number, a
|
package/dist/props/registry.d.ts
CHANGED
|
@@ -1433,7 +1433,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
|
|
|
1433
1433
|
readonly TopbarProp: {
|
|
1434
1434
|
readonly group: "layout";
|
|
1435
1435
|
readonly file: "components/layout.prop.ts";
|
|
1436
|
-
readonly vocabulary: readonly [
|
|
1436
|
+
readonly vocabulary: readonly [{
|
|
1437
|
+
readonly field: "identity";
|
|
1438
|
+
readonly local: true;
|
|
1439
|
+
readonly reason: "Reserved shared-device account slot; bounded and outside the overflow policy.";
|
|
1440
|
+
}, "ChildrenProp", {
|
|
1437
1441
|
readonly field: "overflow";
|
|
1438
1442
|
readonly local: true;
|
|
1439
1443
|
readonly reason: "The bar's overflow contract — `scroll` (default) keeps every cell reachable, `clip` is the pre-gh#728 slicing.";
|
|
@@ -1443,6 +1447,10 @@ export declare const COMPONENT_PROP_REGISTRY: {
|
|
|
1443
1447
|
readonly group: "layout";
|
|
1444
1448
|
readonly file: "components/layout.prop.ts";
|
|
1445
1449
|
readonly vocabulary: readonly ["ChildrenProp", "ClassNameProp", {
|
|
1450
|
+
readonly field: "truncate";
|
|
1451
|
+
readonly local: true;
|
|
1452
|
+
readonly reason: "Text.truncate boolean vocabulary applied to the bar cell label.";
|
|
1453
|
+
}, {
|
|
1446
1454
|
readonly field: "asChild";
|
|
1447
1455
|
readonly local: true;
|
|
1448
1456
|
readonly reason: "Radix Slot passthrough — merges onto the child";
|
package/dist/props/registry.js
CHANGED
|
@@ -1551,6 +1551,11 @@ const COMPONENT_PROP_REGISTRY = {
|
|
|
1551
1551
|
group: "layout",
|
|
1552
1552
|
file: "components/layout.prop.ts",
|
|
1553
1553
|
vocabulary: [
|
|
1554
|
+
{
|
|
1555
|
+
field: "identity",
|
|
1556
|
+
local: true,
|
|
1557
|
+
reason: "Reserved shared-device account slot; bounded and outside the overflow policy."
|
|
1558
|
+
},
|
|
1554
1559
|
"ChildrenProp",
|
|
1555
1560
|
{
|
|
1556
1561
|
field: "overflow",
|
|
@@ -1565,6 +1570,11 @@ const COMPONENT_PROP_REGISTRY = {
|
|
|
1565
1570
|
vocabulary: [
|
|
1566
1571
|
"ChildrenProp",
|
|
1567
1572
|
"ClassNameProp",
|
|
1573
|
+
{
|
|
1574
|
+
field: "truncate",
|
|
1575
|
+
local: true,
|
|
1576
|
+
reason: "Text.truncate boolean vocabulary applied to the bar cell label."
|
|
1577
|
+
},
|
|
1568
1578
|
{ field: "asChild", local: true, reason: "Radix Slot passthrough \u2014 merges onto the child" },
|
|
1569
1579
|
"BreakpointProp",
|
|
1570
1580
|
{
|
package/dist/styles/control.css
CHANGED
|
@@ -1232,7 +1232,10 @@
|
|
|
1232
1232
|
|
|
1233
1233
|
.ui-search-input-control {
|
|
1234
1234
|
padding-inline-start: var(--search-input-start-padding);
|
|
1235
|
-
padding-inline-end:
|
|
1235
|
+
padding-inline-end: max(
|
|
1236
|
+
var(--search-input-end-padding),
|
|
1237
|
+
var(--search-input-affix-min-padding, 0px)
|
|
1238
|
+
);
|
|
1236
1239
|
}
|
|
1237
1240
|
|
|
1238
1241
|
.ui-search-input-clear {
|
|
@@ -1263,8 +1266,8 @@
|
|
|
1263
1266
|
.ui-search-input-clear::after {
|
|
1264
1267
|
content: "";
|
|
1265
1268
|
position: absolute;
|
|
1266
|
-
inset-block: min(0px, calc((100% - var(--control-
|
|
1267
|
-
inset-inline: min(0px, calc((100% - var(--control-
|
|
1269
|
+
inset-block: min(0px, calc((100% - var(--control-affix-touch-target-size)) / 2));
|
|
1270
|
+
inset-inline: min(0px, calc((100% - var(--control-affix-touch-target-size)) / 2));
|
|
1268
1271
|
}
|
|
1269
1272
|
}
|
|
1270
1273
|
|
|
@@ -3767,3 +3770,128 @@
|
|
|
3767
3770
|
min-inline-size: var(--control-height-touch);
|
|
3768
3771
|
}
|
|
3769
3772
|
}
|
|
3773
|
+
|
|
3774
|
+
@layer components {
|
|
3775
|
+
@media (pointer: coarse) {
|
|
3776
|
+
.ui-control-inline-affix-action:not(.ui-badge-remove),
|
|
3777
|
+
.ui-control-affix-action,
|
|
3778
|
+
.ui-tree-select-clear,
|
|
3779
|
+
.ui-password-input-toggle,
|
|
3780
|
+
.ui-search-input-clear,
|
|
3781
|
+
.ui-number-input-step {
|
|
3782
|
+
min-inline-size: var(--control-affix-touch-target-size);
|
|
3783
|
+
min-block-size: var(--control-affix-touch-target-size);
|
|
3784
|
+
flex-shrink: 0;
|
|
3785
|
+
}
|
|
3786
|
+
|
|
3787
|
+
.ui-control-inline-affix-action:not(.ui-badge-remove)::after {
|
|
3788
|
+
inset: 0;
|
|
3789
|
+
translate: none;
|
|
3790
|
+
}
|
|
3791
|
+
|
|
3792
|
+
.ui-input-affix-wrapper:has(.ui-control-inline-affix-action) > .ui-input {
|
|
3793
|
+
min-block-size: var(--control-affix-touch-target-size);
|
|
3794
|
+
}
|
|
3795
|
+
|
|
3796
|
+
.ui-input--trailing-affix {
|
|
3797
|
+
padding-inline-end: max(
|
|
3798
|
+
var(--control-inline-affix-space-inline-end),
|
|
3799
|
+
calc(
|
|
3800
|
+
var(--input-trailing-measured-size, var(--control-affix-touch-target-size)) +
|
|
3801
|
+
var(--control-inline-affix-inset-inline) + var(--control-inline-affix-space-gap)
|
|
3802
|
+
)
|
|
3803
|
+
);
|
|
3804
|
+
}
|
|
3805
|
+
|
|
3806
|
+
.ui-control-trigger-affixed {
|
|
3807
|
+
min-block-size: var(--control-affix-touch-target-size);
|
|
3808
|
+
padding-inline-end: max(
|
|
3809
|
+
var(--control-trigger-space-inline-end),
|
|
3810
|
+
calc(
|
|
3811
|
+
var(--control-affix-touch-target-size) + var(--control-affix-inset-inline-end) +
|
|
3812
|
+
var(--control-inline-affix-space-gap)
|
|
3813
|
+
)
|
|
3814
|
+
);
|
|
3815
|
+
}
|
|
3816
|
+
|
|
3817
|
+
.ui-tree-select-trigger-affixed {
|
|
3818
|
+
min-block-size: var(--control-affix-touch-target-size);
|
|
3819
|
+
padding-inline-end: calc(
|
|
3820
|
+
var(--control-affix-touch-target-size) + var(--space-3) +
|
|
3821
|
+
var(--control-inline-affix-space-gap)
|
|
3822
|
+
);
|
|
3823
|
+
}
|
|
3824
|
+
|
|
3825
|
+
.ui-password-input-field {
|
|
3826
|
+
min-block-size: var(--control-affix-touch-target-size);
|
|
3827
|
+
padding-inline-end: calc(
|
|
3828
|
+
var(--control-affix-touch-target-size) + var(--control-inline-affix-space-gap)
|
|
3829
|
+
);
|
|
3830
|
+
}
|
|
3831
|
+
|
|
3832
|
+
.ui-number-input-steppers {
|
|
3833
|
+
flex-direction: row;
|
|
3834
|
+
align-items: center;
|
|
3835
|
+
inset-block: var(--control-border-width, var(--stroke-hairline));
|
|
3836
|
+
}
|
|
3837
|
+
|
|
3838
|
+
.ui-number-input-step {
|
|
3839
|
+
border: 0;
|
|
3840
|
+
background: transparent;
|
|
3841
|
+
box-shadow: none;
|
|
3842
|
+
}
|
|
3843
|
+
.ui-number-input-step:hover {
|
|
3844
|
+
background: hsl(var(--accent));
|
|
3845
|
+
color: hsl(var(--accent-foreground));
|
|
3846
|
+
}
|
|
3847
|
+
.ui-number-input-step::after {
|
|
3848
|
+
inset-block: calc((100% - var(--control-affix-touch-target-size)) / 2) auto;
|
|
3849
|
+
inset-inline: calc((100% - var(--control-affix-touch-target-size)) / 2) auto;
|
|
3850
|
+
inline-size: var(--control-affix-touch-target-size);
|
|
3851
|
+
block-size: var(--control-affix-touch-target-size);
|
|
3852
|
+
translate: none;
|
|
3853
|
+
}
|
|
3854
|
+
.ui-search-input-control {
|
|
3855
|
+
min-block-size: var(--control-affix-touch-target-size);
|
|
3856
|
+
|
|
3857
|
+
--search-input-affix-min-padding: max(
|
|
3858
|
+
var(--control-affix-touch-target-size),
|
|
3859
|
+
calc(
|
|
3860
|
+
var(--search-input-edge-inset) + var(--touch-target-min) / 2 +
|
|
3861
|
+
var(--control-affix-touch-target-size) / 2
|
|
3862
|
+
)
|
|
3863
|
+
);
|
|
3864
|
+
}
|
|
3865
|
+
[data-slot="textarea-affix-wrapper"]:has(.ui-textarea-clear) > textarea {
|
|
3866
|
+
min-block-size: calc(
|
|
3867
|
+
var(--control-affix-touch-target-size) + 2 * var(--textarea-clear-inset-block-start)
|
|
3868
|
+
);
|
|
3869
|
+
}
|
|
3870
|
+
.ui-search-input-clear {
|
|
3871
|
+
inset-inline-end: max(
|
|
3872
|
+
0px,
|
|
3873
|
+
calc(
|
|
3874
|
+
var(--search-input-edge-inset) + var(--touch-target-min) / 2 -
|
|
3875
|
+
var(--control-affix-touch-target-size) / 2
|
|
3876
|
+
)
|
|
3877
|
+
);
|
|
3878
|
+
}
|
|
3879
|
+
.ui-number-input-field {
|
|
3880
|
+
min-block-size: calc(
|
|
3881
|
+
var(--control-affix-touch-target-size) + 2 *
|
|
3882
|
+
var(--control-border-width, var(--stroke-hairline))
|
|
3883
|
+
);
|
|
3884
|
+
padding-inline-end: calc(2 * var(--control-affix-touch-target-size) + var(--space-2));
|
|
3885
|
+
}
|
|
3886
|
+
.ui-number-input:not([data-controls="off"]) [data-slot="number-input-suffix"] {
|
|
3887
|
+
inset-inline-end: calc(2 * var(--control-affix-touch-target-size) + var(--space-2));
|
|
3888
|
+
}
|
|
3889
|
+
.ui-number-input:not([data-controls="off"]):has([data-slot="number-input-suffix"])
|
|
3890
|
+
.ui-number-input-field {
|
|
3891
|
+
padding-inline-end: calc(
|
|
3892
|
+
2 * var(--control-affix-touch-target-size) + var(--space-2) +
|
|
3893
|
+
var(--control-inline-affix-size)
|
|
3894
|
+
);
|
|
3895
|
+
}
|
|
3896
|
+
}
|
|
3897
|
+
}
|
package/dist/styles/layers.json
CHANGED
|
@@ -2272,6 +2272,44 @@
|
|
|
2272
2272
|
overflow: visible;
|
|
2273
2273
|
}
|
|
2274
2274
|
|
|
2275
|
+
.ui-topbar[data-identity="true"] {
|
|
2276
|
+
overflow: clip;
|
|
2277
|
+
}
|
|
2278
|
+
.ui-topbar-controls {
|
|
2279
|
+
padding-inline: 0;
|
|
2280
|
+
height: auto;
|
|
2281
|
+
background: none;
|
|
2282
|
+
backdrop-filter: none;
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2285
|
+
.ui-topbar-controls > .ui-topbar-start {
|
|
2286
|
+
display: contents;
|
|
2287
|
+
}
|
|
2288
|
+
.ui-topbar-identity {
|
|
2289
|
+
display: flex;
|
|
2290
|
+
align-self: stretch;
|
|
2291
|
+
flex: 0 0 auto;
|
|
2292
|
+
min-inline-size: 0;
|
|
2293
|
+
max-inline-size: var(--topbar-identity-max-inline-size);
|
|
2294
|
+
margin-inline-start: auto;
|
|
2295
|
+
}
|
|
2296
|
+
.ui-topbar-item[data-truncate="true"] {
|
|
2297
|
+
flex: 0 1 auto;
|
|
2298
|
+
min-inline-size: var(--topbar-item-min-width);
|
|
2299
|
+
max-inline-size: 100%;
|
|
2300
|
+
}
|
|
2301
|
+
.ui-topbar-item[data-truncate="true"] > .ui-topbar-item-label {
|
|
2302
|
+
min-inline-size: 0;
|
|
2303
|
+
|
|
2304
|
+
line-height: var(--line-height-normal);
|
|
2305
|
+
overflow: hidden;
|
|
2306
|
+
text-overflow: ellipsis;
|
|
2307
|
+
white-space: nowrap;
|
|
2308
|
+
}
|
|
2309
|
+
.ui-topbar-identity .ui-topbar-item[data-truncate="true"] > .ui-topbar-item-label {
|
|
2310
|
+
min-inline-size: var(--topbar-identity-min-text-inline-size);
|
|
2311
|
+
}
|
|
2312
|
+
|
|
2275
2313
|
.ui-topbar-item {
|
|
2276
2314
|
display: inline-flex;
|
|
2277
2315
|
min-width: var(--topbar-item-min-width);
|