@jonmilner/ui 0.8.0 → 0.8.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/dist/Menu/Menu.css +1 -1
- package/dist/Menu/Menu.css.mjs +2 -2
- package/dist/Menu/client.d.mts +17 -2
- package/dist/Menu/client.mjs +70 -27
- package/dist/Menu/index.d.mts +7 -4
- package/dist/Menu/index.mjs +75 -63
- package/dist/MultiSelect/MultiSelect.css +1 -1
- package/dist/MultiSelect/client.d.mts +1 -0
- package/dist/MultiSelect/client.mjs +5 -4
- package/dist/MultiSelect/index.d.mts +2 -1
- package/dist/MultiSelect/index.mjs +12 -10
- package/dist/docs/Menu.md +41 -5
- package/dist/docs/MultiSelect.md +4 -2
- package/dist/docs/manifest.json +43 -1
- package/package.json +1 -1
package/dist/Menu/Menu.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
@layer tokens, reset, atoms, components.box, components.checkbox, components.clickable, components.icon, components.icon-button, components.inline, components.stack, components.text, components.avatar, components.badge, components.button, components.chip, components.field, components.color-field, components.heading, components.dialog, components.alert-dialog, components.menu, components.multiselect, components.search-field, components.tabs, components.tag, components.text-field, components.toast, components.visually-hidden;
|
|
2
|
-
@layer components.menu{._393eil1{border:var(--space-1) solid var(--color-border);transform-origin:var(--transform-origin);transition:opacity var(--duration-fast) var(--easing-standard), scale var(--duration-fast) var(--easing-enter)}._393eil1:focus-visible{outline:var(--space-2) solid var(--color-focus);outline-offset:var(--space-2)}._393eil1[data-starting-style],._393eil1[data-ending-style]{opacity:0;scale:calc(1 - var(--scale-med))}._393eil2{cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;user-select:none}._393eil2:focus-visible{outline:var(--space-2) solid var(--color-focus);outline-offset:var(--space-2)}._393eil2[data-highlighted]{background-color:light-dark(var(--color-bg-muted),color-mix(in srgb, var(--color-fg) 10%, var(--color-bg-raised)))}._393eil2[aria-disabled=true]{color:var(--color-fg-muted);cursor:not-allowed}._393eil3{text-decoration:none}.
|
|
2
|
+
@layer components.menu{._393eil1{border:var(--space-1) solid var(--color-border);max-inline-size:var(--available-width);transform-origin:var(--transform-origin);transition:opacity var(--duration-fast) var(--easing-standard), scale var(--duration-fast) var(--easing-enter)}._393eil1:focus-visible{outline:var(--space-2) solid var(--color-focus);outline-offset:var(--space-2)}._393eil1[data-starting-style],._393eil1[data-ending-style]{opacity:0;scale:calc(1 - var(--scale-med))}._393eil2{cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;user-select:none}._393eil2:focus-visible{outline:var(--space-2) solid var(--color-focus);outline-offset:calc(-1 * var(--space-2))}._393eil2[data-highlighted]{background-color:light-dark(var(--color-bg-muted),color-mix(in srgb, var(--color-fg) 10%, var(--color-bg-raised)))}._393eil2[aria-disabled=true]{color:var(--color-fg-muted);cursor:not-allowed}._393eil3{color:var(--color-fg-muted)}._393eil4{text-decoration:none}._393eil5{border-block-start-color:var(--color-border)}._393eil5:before{content:"";border-block-start:var(--space-1) solid;border-block-start-color:inherit;display:block}@media (forced-colors:active){._393eil2[data-highlighted]:not([aria-disabled=true]){forced-color-adjust:none;color:highlighttext;background-color:highlight}._393eil2[data-highlighted]:not([aria-disabled=true]):focus-visible{color:canvastext;background-color:canvas}._393eil2[aria-disabled=true]{color:graytext}._393eil3{color:inherit}}}
|
package/dist/Menu/Menu.css.mjs
CHANGED
|
@@ -3,6 +3,6 @@ import "./Menu.css";
|
|
|
3
3
|
/* empty css */
|
|
4
4
|
/* empty css */
|
|
5
5
|
//#region src/Menu/Menu.css.ts
|
|
6
|
-
var e = "_393eil0", t = "_393eil1", n = "_393eil2", r = "_393eil3", i = "_393eil4";
|
|
6
|
+
var e = "_393eil0", t = "_393eil1", n = "_393eil2", r = "_393eil3", i = "_393eil4", a = "_393eil5";
|
|
7
7
|
//#endregion
|
|
8
|
-
export { n as item,
|
|
8
|
+
export { r as description, n as item, i as linkItem, t as popup, e as positioner, a as separator };
|
package/dist/Menu/client.d.mts
CHANGED
|
@@ -1,9 +1,24 @@
|
|
|
1
|
+
import { IconProps } from "../Icon/index.mjs";
|
|
1
2
|
import { TriggerElementProps, TriggerLookProps } from "../popup/client.mjs";
|
|
2
3
|
import "./index.mjs";
|
|
4
|
+
import { ComponentType, ReactNode } from "react";
|
|
3
5
|
import { Menu } from "@base-ui/react/menu";
|
|
4
6
|
//#region src/Menu/client.d.ts
|
|
5
7
|
type TriggerOwnProps = Omit<Menu.Trigger.Props, "render" | "className" | "style" | "nativeButton">;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
type TriggerIconForm = {
|
|
9
|
+
"aria-label"?: never;
|
|
10
|
+
"aria-labelledby"?: never;
|
|
11
|
+
children?: never;
|
|
12
|
+
icon: ComponentType<IconProps>;
|
|
13
|
+
iconEnd?: never;
|
|
14
|
+
iconStart?: never;
|
|
15
|
+
label: string;
|
|
16
|
+
};
|
|
17
|
+
type TriggerTextForm = {
|
|
18
|
+
icon?: never;
|
|
19
|
+
label?: never;
|
|
20
|
+
};
|
|
21
|
+
export type MenuTriggerProps = TriggerOwnProps & TriggerLookProps & Omit<TriggerElementProps, keyof TriggerLookProps | keyof TriggerOwnProps> & (TriggerIconForm | TriggerTextForm);
|
|
22
|
+
export declare function MenuTrigger({ disabled, openOnHover, delay, closeDelay, handle, payload, icon, label, ...props }: MenuTriggerProps): import("react").JSX.Element;
|
|
8
23
|
//#endregion
|
|
9
24
|
export {};
|
package/dist/Menu/client.mjs
CHANGED
|
@@ -2,47 +2,90 @@
|
|
|
2
2
|
import { join as e } from "../styles/join.mjs";
|
|
3
3
|
import { splitStyleProps as t } from "../styles/split-style-props.mjs";
|
|
4
4
|
import { Box as n } from "../Box/index.mjs";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
5
|
+
import { Text as r } from "../Text/index.mjs";
|
|
6
|
+
import { PopupScope as i, triggerElement as a, useClosingRule as o, usePopupScope as s, useRecordOpenChange as c } from "../popup/client.mjs";
|
|
7
|
+
import { IconButton as l } from "../IconButton/index.mjs";
|
|
8
|
+
import { description as u, positioner as d } from "./Menu.css.mjs";
|
|
9
|
+
import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
10
|
+
import { useId as h } from "react";
|
|
11
|
+
import { Menu as g } from "@base-ui/react/menu";
|
|
9
12
|
//#region src/Menu/client.tsx
|
|
10
|
-
function
|
|
11
|
-
let { ref:
|
|
12
|
-
return /* @__PURE__ */
|
|
13
|
+
function _({ disabled: e = !1, openOnHover: t, delay: n, closeDelay: r, handle: i, payload: o, icon: c, label: u, ...d }) {
|
|
14
|
+
let { ref: f } = s();
|
|
15
|
+
return /* @__PURE__ */ p(g.Trigger, {
|
|
13
16
|
disabled: e,
|
|
14
17
|
openOnHover: t,
|
|
15
18
|
delay: n,
|
|
16
19
|
closeDelay: r,
|
|
17
|
-
handle:
|
|
18
|
-
payload:
|
|
19
|
-
ref:
|
|
20
|
-
render:
|
|
20
|
+
handle: i,
|
|
21
|
+
payload: o,
|
|
22
|
+
ref: f,
|
|
23
|
+
render: c ? /* @__PURE__ */ p(l, {
|
|
24
|
+
...d,
|
|
25
|
+
icon: c,
|
|
26
|
+
label: u
|
|
27
|
+
}) : a(d)
|
|
21
28
|
});
|
|
22
29
|
}
|
|
23
|
-
function
|
|
24
|
-
let
|
|
25
|
-
return
|
|
30
|
+
function v(e, t, i) {
|
|
31
|
+
let a = h();
|
|
32
|
+
return t === void 0 ? { content: e } : {
|
|
33
|
+
aria: { "aria-describedby": i ? `${a} ${i}` : a },
|
|
34
|
+
content: /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(n, {
|
|
35
|
+
alignItems: "center",
|
|
36
|
+
as: "span",
|
|
37
|
+
display: "flex",
|
|
38
|
+
gap: "8",
|
|
39
|
+
children: e
|
|
40
|
+
}), /* @__PURE__ */ p(r, {
|
|
41
|
+
"aria-hidden": !0,
|
|
42
|
+
as: "span",
|
|
43
|
+
className: u,
|
|
44
|
+
id: a,
|
|
45
|
+
size: "xs",
|
|
46
|
+
children: t
|
|
47
|
+
})] })
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function y({ description: e, children: t, ...n }) {
|
|
51
|
+
let { aria: r, content: i } = v(t, e, n["aria-describedby"]);
|
|
52
|
+
return /* @__PURE__ */ p(g.Item, {
|
|
53
|
+
...n,
|
|
54
|
+
...r,
|
|
55
|
+
children: i
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
function b({ description: e, children: t, ...n }) {
|
|
59
|
+
let { aria: r, content: i } = v(t, e, n["aria-describedby"]);
|
|
60
|
+
return /* @__PURE__ */ p(g.LinkItem, {
|
|
61
|
+
...n,
|
|
62
|
+
...r,
|
|
63
|
+
children: i
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function x({ children: e }) {
|
|
67
|
+
let { container: t } = s();
|
|
68
|
+
return /* @__PURE__ */ p(g.Portal, {
|
|
26
69
|
container: t,
|
|
27
70
|
children: e
|
|
28
71
|
});
|
|
29
72
|
}
|
|
30
|
-
function
|
|
31
|
-
return /* @__PURE__ */
|
|
73
|
+
function S(e) {
|
|
74
|
+
return /* @__PURE__ */ p(i, { children: /* @__PURE__ */ p(C, { ...e }) });
|
|
32
75
|
}
|
|
33
|
-
function
|
|
34
|
-
return /* @__PURE__ */
|
|
76
|
+
function C({ onOpenChange: e, ...t }) {
|
|
77
|
+
return /* @__PURE__ */ p(g.Root, {
|
|
35
78
|
...t,
|
|
36
|
-
onOpenChange:
|
|
79
|
+
onOpenChange: c(e)
|
|
37
80
|
});
|
|
38
81
|
}
|
|
39
|
-
function
|
|
40
|
-
return /* @__PURE__ */
|
|
82
|
+
function w({ finalFocus: e, ...n }) {
|
|
83
|
+
return /* @__PURE__ */ p(g.Positioner, {
|
|
41
84
|
...n,
|
|
42
85
|
collisionPadding: 8,
|
|
43
86
|
render: (n, { open: r }) => {
|
|
44
87
|
let [, i] = t(n);
|
|
45
|
-
return /* @__PURE__ */
|
|
88
|
+
return /* @__PURE__ */ p(T, {
|
|
46
89
|
...i,
|
|
47
90
|
finalFocus: e,
|
|
48
91
|
open: r
|
|
@@ -51,16 +94,16 @@ function h({ finalFocus: e, ...n }) {
|
|
|
51
94
|
sideOffset: 4
|
|
52
95
|
});
|
|
53
96
|
}
|
|
54
|
-
function
|
|
55
|
-
return /* @__PURE__ */
|
|
97
|
+
function T({ open: t, finalFocus: r, ref: i, className: a, ...s }) {
|
|
98
|
+
return /* @__PURE__ */ p(n, {
|
|
56
99
|
...s,
|
|
57
|
-
...
|
|
100
|
+
...o(i, {
|
|
58
101
|
finalFocus: r,
|
|
59
102
|
open: t
|
|
60
103
|
}),
|
|
61
|
-
className: e(
|
|
104
|
+
className: e(d, a),
|
|
62
105
|
zIndex: "popover"
|
|
63
106
|
});
|
|
64
107
|
}
|
|
65
108
|
//#endregion
|
|
66
|
-
export {
|
|
109
|
+
export { y as MenuItemPart, b as MenuLinkItemPart, x as MenuPortal, w as MenuPositioner, S as MenuRootScope, _ as MenuTrigger };
|
package/dist/Menu/index.d.mts
CHANGED
|
@@ -11,10 +11,13 @@ export type MenuProps = Pick<Menu$1.Root.Props, "open" | "defaultOpen" | "onOpen
|
|
|
11
11
|
children?: ReactNode;
|
|
12
12
|
};
|
|
13
13
|
export type MenuPopupProps = PartProps<Menu$1.Popup.Props> & Pick<Menu$1.Positioner.Props, "side" | "align">;
|
|
14
|
-
|
|
14
|
+
type ItemDescription = {
|
|
15
|
+
description?: ReactNode;
|
|
16
|
+
};
|
|
17
|
+
export type MenuItemProps = PartProps<Menu$1.Item.Props> & ItemDescription & {
|
|
15
18
|
variant?: "neutral" | "danger";
|
|
16
19
|
};
|
|
17
|
-
export type MenuLinkItemProps = PartProps<Menu$1.LinkItem.Props> & {
|
|
20
|
+
export type MenuLinkItemProps = PartProps<Menu$1.LinkItem.Props> & ItemDescription & {
|
|
18
21
|
disabled?: boolean;
|
|
19
22
|
href: string;
|
|
20
23
|
};
|
|
@@ -24,8 +27,8 @@ export type MenuGroupProps = PartProps<Menu$1.Group.Props> & {
|
|
|
24
27
|
};
|
|
25
28
|
declare function MenuRoot(props: MenuProps): import("react").JSX.Element;
|
|
26
29
|
declare function MenuPopup({ side, align, backgroundColor, borderRadius, boxShadow, padding, className, style, ...props }: MenuPopupProps): import("react").JSX.Element;
|
|
27
|
-
declare function MenuItem({ variant,
|
|
28
|
-
declare function MenuLinkItem({ href, disabled, closeOnClick, onClick,
|
|
30
|
+
declare function MenuItem({ variant, description, display, minBlockSize, paddingInline, borderRadius, color, className, style, children, ...props }: MenuItemProps): import("react").JSX.Element;
|
|
31
|
+
declare function MenuLinkItem({ href, disabled, closeOnClick, onClick, description, display, minBlockSize, paddingInline, borderRadius, color, className, style, children, ...props }: MenuLinkItemProps): import("react").JSX.Element;
|
|
29
32
|
declare function MenuSeparator({ paddingBlock, paddingInline, className, style, ...props }: MenuSeparatorProps): import("react").JSX.Element;
|
|
30
33
|
declare function MenuGroup({ label, className, style, children, ...props }: MenuGroupProps): import("react").JSX.Element;
|
|
31
34
|
export declare const Menu: typeof MenuRoot & {
|
package/dist/Menu/index.mjs
CHANGED
|
@@ -3,90 +3,102 @@ import { splitStyleProps as t } from "../styles/split-style-props.mjs";
|
|
|
3
3
|
import { Box as n } from "../Box/index.mjs";
|
|
4
4
|
import { Text as r } from "../Text/index.mjs";
|
|
5
5
|
import { item as i, linkItem as a, popup as o, separator as s } from "./Menu.css.mjs";
|
|
6
|
-
import {
|
|
7
|
-
import { jsx as
|
|
8
|
-
import { Children as
|
|
9
|
-
import { Menu as
|
|
6
|
+
import { MenuItemPart as c, MenuLinkItemPart as l, MenuPortal as u, MenuPositioner as d, MenuRootScope as f, MenuTrigger as p } from "./client.mjs";
|
|
7
|
+
import { jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
8
|
+
import { Children as g } from "react";
|
|
9
|
+
import { Menu as _ } from "@base-ui/react/menu";
|
|
10
10
|
//#region src/Menu/index.tsx
|
|
11
|
-
function
|
|
12
|
-
return /* @__PURE__ */ f
|
|
11
|
+
function v(e) {
|
|
12
|
+
return /* @__PURE__ */ m(f, { ...e });
|
|
13
13
|
}
|
|
14
|
-
function
|
|
15
|
-
let [
|
|
16
|
-
return /* @__PURE__ */
|
|
14
|
+
function y({ side: r = "bottom", align: i = "start", backgroundColor: a = "bgRaised", borderRadius: s = "med", boxShadow: c = "med", padding: l = "4", className: f, style: p, ...h }) {
|
|
15
|
+
let [g, v] = t(h);
|
|
16
|
+
return /* @__PURE__ */ m(u, { children: /* @__PURE__ */ m(d, {
|
|
17
17
|
align: i,
|
|
18
18
|
finalFocus: v.finalFocus !== void 0 && v.finalFocus !== !0,
|
|
19
19
|
side: r,
|
|
20
|
-
children: /* @__PURE__ */
|
|
20
|
+
children: /* @__PURE__ */ m(_.Popup, {
|
|
21
21
|
...v,
|
|
22
|
-
render: /* @__PURE__ */
|
|
22
|
+
render: /* @__PURE__ */ m(n, {
|
|
23
23
|
backgroundColor: a,
|
|
24
24
|
borderRadius: s,
|
|
25
|
-
boxShadow:
|
|
26
|
-
padding:
|
|
27
|
-
...
|
|
28
|
-
className: e(o,
|
|
29
|
-
style:
|
|
25
|
+
boxShadow: c,
|
|
26
|
+
padding: l,
|
|
27
|
+
...g,
|
|
28
|
+
className: e(o, f),
|
|
29
|
+
style: p
|
|
30
30
|
})
|
|
31
31
|
})
|
|
32
32
|
}) });
|
|
33
33
|
}
|
|
34
|
-
function
|
|
35
|
-
return
|
|
34
|
+
function b(e) {
|
|
35
|
+
return g.map(e, (e) => typeof e == "string" || typeof e == "number" ? /* @__PURE__ */ m(r, {
|
|
36
36
|
as: "span",
|
|
37
37
|
font: "label",
|
|
38
38
|
size: "sm",
|
|
39
39
|
children: e
|
|
40
40
|
}) : e);
|
|
41
41
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
var x = (e) => e == null || e === !1 || e === "" ? void 0 : e, S = (e, t) => t !== void 0 && (typeof e == "string" || typeof e == "number") ? String(e) : void 0, C = (e) => e ? {
|
|
43
|
+
flexDirection: "column",
|
|
44
|
+
alignItems: "stretch",
|
|
45
|
+
justifyContent: "center",
|
|
46
|
+
gap: "4",
|
|
47
|
+
paddingBlock: "8"
|
|
48
|
+
} : {
|
|
49
|
+
alignItems: "center",
|
|
50
|
+
gap: "8"
|
|
51
|
+
};
|
|
52
|
+
function w({ variant: r = "neutral", description: a, display: o = "flex", minBlockSize: s = "sm", paddingInline: l = "12", borderRadius: u = "sm", color: d = r === "danger" ? "danger" : "fg", className: f, style: p, children: h, ...g }) {
|
|
53
|
+
let [_, v] = t(g), y = x(a);
|
|
54
|
+
return /* @__PURE__ */ m(c, {
|
|
55
|
+
label: S(h, y),
|
|
56
|
+
...v,
|
|
57
|
+
description: y,
|
|
58
|
+
render: /* @__PURE__ */ m(n, {
|
|
59
|
+
...C(y !== void 0),
|
|
60
|
+
display: o,
|
|
61
|
+
minBlockSize: s,
|
|
51
62
|
paddingInline: l,
|
|
52
63
|
borderRadius: u,
|
|
53
64
|
color: d,
|
|
54
|
-
...
|
|
55
|
-
className: e(i,
|
|
56
|
-
style:
|
|
65
|
+
..._,
|
|
66
|
+
className: e(i, f),
|
|
67
|
+
style: p
|
|
57
68
|
}),
|
|
58
|
-
children:
|
|
69
|
+
children: b(h)
|
|
59
70
|
});
|
|
60
71
|
}
|
|
61
|
-
function
|
|
62
|
-
let [
|
|
63
|
-
return /* @__PURE__ */
|
|
64
|
-
|
|
72
|
+
function T({ href: r, disabled: o = !1, closeOnClick: s = !0, onClick: c, description: u, display: d = "flex", minBlockSize: f = "sm", paddingInline: p = "12", borderRadius: h = "sm", color: g = "fg", className: _, style: v, children: y, ...w }) {
|
|
73
|
+
let [T, E] = t(w), D = x(u);
|
|
74
|
+
return /* @__PURE__ */ m(l, {
|
|
75
|
+
label: S(y, D),
|
|
76
|
+
...E,
|
|
65
77
|
"aria-disabled": o || void 0,
|
|
66
78
|
closeOnClick: !o && s,
|
|
79
|
+
description: D,
|
|
67
80
|
href: o ? void 0 : r,
|
|
68
81
|
onClick: o ? void 0 : c,
|
|
69
|
-
render: /* @__PURE__ */
|
|
82
|
+
render: /* @__PURE__ */ m(n, {
|
|
70
83
|
as: "a",
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
style: b
|
|
84
|
+
...C(D !== void 0),
|
|
85
|
+
display: d,
|
|
86
|
+
minBlockSize: f,
|
|
87
|
+
paddingInline: p,
|
|
88
|
+
borderRadius: h,
|
|
89
|
+
color: g,
|
|
90
|
+
...T,
|
|
91
|
+
className: e(i, a, _),
|
|
92
|
+
style: v
|
|
81
93
|
}),
|
|
82
|
-
children:
|
|
94
|
+
children: b(y)
|
|
83
95
|
});
|
|
84
96
|
}
|
|
85
|
-
function
|
|
97
|
+
function E({ paddingBlock: r = "4", paddingInline: i = "8", className: a, style: o, ...c }) {
|
|
86
98
|
let [l, u] = t(c);
|
|
87
|
-
return /* @__PURE__ */
|
|
99
|
+
return /* @__PURE__ */ m(_.Separator, {
|
|
88
100
|
...u,
|
|
89
|
-
render: /* @__PURE__ */
|
|
101
|
+
render: /* @__PURE__ */ m(n, {
|
|
90
102
|
paddingBlock: r,
|
|
91
103
|
paddingInline: i,
|
|
92
104
|
...l,
|
|
@@ -95,17 +107,17 @@ function x({ paddingBlock: r = "4", paddingInline: i = "8", className: a, style:
|
|
|
95
107
|
})
|
|
96
108
|
});
|
|
97
109
|
}
|
|
98
|
-
function
|
|
110
|
+
function D({ label: e, className: i, style: a, children: o, ...s }) {
|
|
99
111
|
let [c, l] = t(s);
|
|
100
|
-
return /* @__PURE__ */
|
|
112
|
+
return /* @__PURE__ */ h(_.Group, {
|
|
101
113
|
...l,
|
|
102
|
-
render: /* @__PURE__ */
|
|
114
|
+
render: /* @__PURE__ */ m(n, {
|
|
103
115
|
...c,
|
|
104
116
|
className: i,
|
|
105
117
|
style: a
|
|
106
118
|
}),
|
|
107
|
-
children: [/* @__PURE__ */
|
|
108
|
-
render: /* @__PURE__ */
|
|
119
|
+
children: [/* @__PURE__ */ m(_.GroupLabel, {
|
|
120
|
+
render: /* @__PURE__ */ m(r, {
|
|
109
121
|
as: "div",
|
|
110
122
|
color: "fgMuted",
|
|
111
123
|
font: "label",
|
|
@@ -117,13 +129,13 @@ function S({ label: e, className: i, style: a, children: o, ...s }) {
|
|
|
117
129
|
}), o]
|
|
118
130
|
});
|
|
119
131
|
}
|
|
120
|
-
var
|
|
121
|
-
Trigger:
|
|
122
|
-
Popup:
|
|
123
|
-
Item:
|
|
124
|
-
LinkItem:
|
|
125
|
-
Separator:
|
|
126
|
-
Group:
|
|
132
|
+
var O = Object.assign(v, {
|
|
133
|
+
Trigger: p,
|
|
134
|
+
Popup: y,
|
|
135
|
+
Item: w,
|
|
136
|
+
LinkItem: T,
|
|
137
|
+
Separator: E,
|
|
138
|
+
Group: D
|
|
127
139
|
});
|
|
128
140
|
//#endregion
|
|
129
|
-
export {
|
|
141
|
+
export { O as Menu };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
@layer tokens, reset, atoms, components.box, components.checkbox, components.clickable, components.icon, components.icon-button, components.inline, components.stack, components.text, components.avatar, components.badge, components.button, components.chip, components.field, components.color-field, components.heading, components.dialog, components.alert-dialog, components.menu, components.multiselect, components.search-field, components.tabs, components.tag, components.text-field, components.toast, components.visually-hidden;
|
|
2
|
-
@layer components.multiselect{._1seauxl0{text-align:start;justify-content:stretch}:where(._1seauxl0) ._1gwwloa0{flex:auto;justify-items:stretch;min-inline-size:0}:where(._1seauxl0) ._1gwwloa1{min-inline-size:0}:where(._1seauxl0) ._1gwwloa2{flex:auto;min-inline-size:0}._1seauxl1{min-inline-size:0;display:block}._1seauxl1[data-placeholder]{color:var(--color-fg-muted)}._1seauxl2{min-inline-size:0;display:grid}._1seauxl3{grid-area:1/1}._1seauxl3[aria-hidden=true]{visibility:hidden}._1seauxl4{grid-area:1/1}._1seauxl5{border:var(--space-1) solid var(--color-border);min-inline-size:var(--anchor-width);max-block-size:var(--available-height);transform-origin:var(--transform-origin);transition:opacity var(--duration-fast) var(--easing-standard), scale var(--duration-fast) var(--easing-enter);overflow-y:auto}._1seauxl5:focus-visible{outline:var(--space-2) solid var(--color-focus);outline-offset:var(--space-2)}._1seauxl5[data-starting-style],._1seauxl5[data-ending-style]{opacity:0;scale:calc(1 - var(--scale-med))}._1seauxl6{cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;user-select:none}._1seauxl6:focus-visible{outline:var(--space-2) solid var(--color-focus);outline-offset:var(--space-2)}._1seauxl6[data-highlighted]{background-color:light-dark(var(--color-bg-muted),color-mix(in srgb, var(--color-fg) 10%, var(--color-bg-raised)))}._1seauxl6[aria-disabled=true]{color:var(--color-fg-muted);cursor:not-allowed}._1seauxl7{visibility:hidden;flex-shrink:0}._1seauxl6[aria-selected=true] ._1seauxl7{visibility:visible}@media (forced-colors:active){._1seauxl6[data-highlighted]{forced-color-adjust:none;color:highlighttext;background-color:highlight}._1seauxl6[aria-disabled=true]{color:graytext}}}
|
|
2
|
+
@layer components.multiselect{._1seauxl0{text-align:start;justify-content:stretch}:where(._1seauxl0) ._1gwwloa0{flex:auto;justify-items:stretch;min-inline-size:0}:where(._1seauxl0) ._1gwwloa1{min-inline-size:0}:where(._1seauxl0) ._1gwwloa2{flex:auto;min-inline-size:0}._1seauxl1{min-inline-size:0;display:block}._1seauxl1[data-placeholder]{color:var(--color-fg-muted)}._1seauxl2{min-inline-size:0;display:grid}._1seauxl3{grid-area:1/1}._1seauxl3[aria-hidden=true]{visibility:hidden}._1seauxl4{grid-area:1/1}._1seauxl5{border:var(--space-1) solid var(--color-border);min-inline-size:var(--anchor-width);max-block-size:var(--available-height);transform-origin:var(--transform-origin);transition:opacity var(--duration-fast) var(--easing-standard), scale var(--duration-fast) var(--easing-enter);overflow-y:auto}._1seauxl5:focus-visible{outline:var(--space-2) solid var(--color-focus);outline-offset:var(--space-2)}._1seauxl5[data-starting-style],._1seauxl5[data-ending-style]{opacity:0;scale:calc(1 - var(--scale-med))}._1seauxl6{cursor:pointer;touch-action:manipulation;-webkit-tap-highlight-color:transparent;-webkit-user-select:none;user-select:none}._1seauxl6:focus-visible{outline:var(--space-2) solid var(--color-focus);outline-offset:calc(-1 * var(--space-2))}._1seauxl6[data-highlighted]{background-color:light-dark(var(--color-bg-muted),color-mix(in srgb, var(--color-fg) 10%, var(--color-bg-raised)))}._1seauxl6[aria-disabled=true]{color:var(--color-fg-muted);cursor:not-allowed}._1seauxl7{visibility:hidden;flex-shrink:0}._1seauxl6[aria-selected=true] ._1seauxl7{visibility:visible}@media (forced-colors:active){._1seauxl6[data-highlighted]{forced-color-adjust:none;color:highlighttext;background-color:highlight}._1seauxl6[data-highlighted]:focus-visible{color:canvastext;background-color:canvas}._1seauxl6[aria-disabled=true]{color:graytext}}}
|
|
@@ -10,13 +10,14 @@ import { jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
|
10
10
|
import { createContext as _, use as v, useId as y, useLayoutEffect as b, useMemo as x, useRef as S, useState as C } from "react";
|
|
11
11
|
import { Select as w } from "@base-ui/react/select";
|
|
12
12
|
//#region src/MultiSelect/client.tsx
|
|
13
|
-
function T({ options: e, placeholder: t, countLabel: n, disabled: r }) {
|
|
14
|
-
let { ref:
|
|
13
|
+
function T({ options: e, placeholder: t, countLabel: n, disabled: r, size: a }) {
|
|
14
|
+
let { ref: s } = o(), c = x(() => new Map(e.map((e) => [e.value, e.label])), [e]);
|
|
15
15
|
return /* @__PURE__ */ h(w.Trigger, {
|
|
16
16
|
disabled: r,
|
|
17
|
-
ref:
|
|
17
|
+
ref: s,
|
|
18
18
|
render: i({
|
|
19
19
|
variant: "secondary",
|
|
20
|
+
size: a,
|
|
20
21
|
iconEnd: l,
|
|
21
22
|
className: p,
|
|
22
23
|
children: /* @__PURE__ */ h(w.Value, {
|
|
@@ -24,7 +25,7 @@ function T({ options: e, placeholder: t, countLabel: n, disabled: r }) {
|
|
|
24
25
|
placeholder: t,
|
|
25
26
|
children: (e) => e.length > 0 ? /* @__PURE__ */ h(E, {
|
|
26
27
|
count: n.replaceAll("{count}", String(e.length)),
|
|
27
|
-
labels: e.map((e) =>
|
|
28
|
+
labels: e.map((e) => c.get(e) ?? e)
|
|
28
29
|
}) : t
|
|
29
30
|
})
|
|
30
31
|
})
|
|
@@ -16,8 +16,9 @@ export type MultiSelectProps = StyleProps & {
|
|
|
16
16
|
options: readonly MultiSelectOption[];
|
|
17
17
|
placeholder?: string;
|
|
18
18
|
required?: boolean;
|
|
19
|
+
size?: "sm" | "med" | "lg";
|
|
19
20
|
style?: CSSProperties;
|
|
20
21
|
value?: readonly string[];
|
|
21
22
|
};
|
|
22
|
-
export declare function MultiSelect({ options, value, defaultValue, onValueChange, label, description, error, placeholder, countLabel, disabled, required, name, className, style, ...atoms }: MultiSelectProps): import("react").JSX.Element;
|
|
23
|
+
export declare function MultiSelect({ options, value, defaultValue, onValueChange, label, description, error, placeholder, countLabel, disabled, required, size, name, className, style, ...atoms }: MultiSelectProps): import("react").JSX.Element;
|
|
23
24
|
//#endregion
|
|
@@ -7,18 +7,18 @@ import { MultiSelectLabel as o, MultiSelectPopup as s, MultiSelectPortal as c, M
|
|
|
7
7
|
import { jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
8
8
|
import { Select as h } from "@base-ui/react/select";
|
|
9
9
|
//#region src/MultiSelect/index.tsx
|
|
10
|
-
function g({ options: g, value: _, defaultValue: v, onValueChange: y, label: b, description: x, error: S, placeholder: C = "Select", countLabel: w = "{count} selected", disabled: T = !1, required: E = !1,
|
|
10
|
+
function g({ options: g, value: _, defaultValue: v, onValueChange: y, label: b, description: x, error: S, placeholder: C = "Select", countLabel: w = "{count} selected", disabled: T = !1, required: E = !1, size: D = "med", name: O, className: k, style: A, ...j }) {
|
|
11
11
|
return /* @__PURE__ */ m(r, {
|
|
12
|
-
...
|
|
13
|
-
className:
|
|
12
|
+
...j,
|
|
13
|
+
className: k,
|
|
14
14
|
disabled: T,
|
|
15
15
|
invalid: S != null && S !== !1 && S !== "",
|
|
16
|
-
style:
|
|
16
|
+
style: A,
|
|
17
17
|
children: [
|
|
18
18
|
/* @__PURE__ */ p(d, { children: /* @__PURE__ */ m(u, {
|
|
19
19
|
defaultValue: v,
|
|
20
20
|
disabled: T,
|
|
21
|
-
name:
|
|
21
|
+
name: O,
|
|
22
22
|
onValueChange: y,
|
|
23
23
|
required: E,
|
|
24
24
|
value: _,
|
|
@@ -28,7 +28,8 @@ function g({ options: g, value: _, defaultValue: v, onValueChange: y, label: b,
|
|
|
28
28
|
countLabel: w,
|
|
29
29
|
disabled: T,
|
|
30
30
|
options: g,
|
|
31
|
-
placeholder: C
|
|
31
|
+
placeholder: C,
|
|
32
|
+
size: D
|
|
32
33
|
}),
|
|
33
34
|
/* @__PURE__ */ p(c, { children: /* @__PURE__ */ p(l, { children: /* @__PURE__ */ p(s, { children: g.map((r) => /* @__PURE__ */ m(h.Item, {
|
|
34
35
|
disabled: r.disabled,
|
|
@@ -39,20 +40,21 @@ function g({ options: g, value: _, defaultValue: v, onValueChange: y, label: b,
|
|
|
39
40
|
className: a,
|
|
40
41
|
display: "flex",
|
|
41
42
|
gap: "8",
|
|
43
|
+
justifyContent: "space-between",
|
|
42
44
|
minBlockSize: "sm",
|
|
43
45
|
paddingInline: "12"
|
|
44
46
|
}),
|
|
45
47
|
value: r.value,
|
|
46
|
-
children: [/* @__PURE__ */ p(
|
|
47
|
-
className: i,
|
|
48
|
-
size: "sm"
|
|
49
|
-
}), /* @__PURE__ */ p(h.ItemText, {
|
|
48
|
+
children: [/* @__PURE__ */ p(h.ItemText, {
|
|
50
49
|
render: /* @__PURE__ */ p(t, {
|
|
51
50
|
as: "span",
|
|
52
51
|
font: "label",
|
|
53
52
|
size: "sm"
|
|
54
53
|
}),
|
|
55
54
|
children: r.label
|
|
55
|
+
}), /* @__PURE__ */ p(n, {
|
|
56
|
+
className: i,
|
|
57
|
+
size: "sm"
|
|
56
58
|
})]
|
|
57
59
|
}, r.value)) }) }) })
|
|
58
60
|
]
|
package/dist/docs/Menu.md
CHANGED
|
@@ -20,12 +20,14 @@ A list of actions that opens from a button: a row's "Edit, Duplicate, Delete", a
|
|
|
20
20
|
## Rules
|
|
21
21
|
|
|
22
22
|
- Compose the parts: `Menu` > `Menu.Trigger` + `Menu.Popup` > `Menu.Item`, `Menu.LinkItem`, `Menu.Separator`, `Menu.Group`. `Menu` holds the open state and renders no element, so it takes no `className` or `style`; every other part does, plus style props.
|
|
23
|
-
- `Menu.Trigger` is a bare `Clickable`: give it its look with style props (or your own class), and an accessible name.
|
|
23
|
+
- `Menu.Trigger` is a bare `Clickable`: give it its look with style props (or your own class), and an accessible name.
|
|
24
|
+
- For an icon-only trigger ("More actions"), pass `icon` and `label`: it renders an `IconButton`, the same square as one at each `size` (`sm`, `med`, `lg`; `med` by default), named by `label`, with IconButton's `variant` (`secondary` by default) and the open look below. It takes no children, `iconStart`, `iconEnd` or `aria-label` (ADR 0123). Never build one from `iconStart` and `aria-label`: Button's padding makes it wider than the IconButtons beside it.
|
|
24
25
|
- For a trigger that reads as a button ("Actions", "New"), pass Button's `variant`, `size`, `iconStart` or `iconEnd` (a `ChevronDownIcon` for "Actions ▾"): it renders a `Button`, with its fill, border and height, and keeps the trigger's behavior and `aria-disabled`. While the menu is open it shows Button's open look, a held tint and an inset ring (ADR 0063); a bare trigger has none, so style it yourself off `aria-expanded`. Style props still override the defaults.
|
|
25
26
|
- `Menu.Item` runs its `onClick` on click, Enter and Space, then the menu closes. Pass `closeOnClick={false}` to keep it open.
|
|
26
27
|
- `Menu.LinkItem` is a real `<a role="menuitem">` for an entry that goes somewhere. `href` is required; `target`, `rel` and `download` pass through. Hover shows the URL, Cmd/Ctrl-click and middle-click open a new tab, and a click, Enter or Space follows it and closes the menu. Never navigate from a `Menu.Item`'s `onClick` (`location.assign`, a router's `navigate`): it loses all of that. Router-aware (client-side) links are not offered. It takes no `variant`.
|
|
27
28
|
- `variant="danger"` marks a destructive item. It still runs on one click, so open a confirm dialog from it (Cancel focused first) before anything irreversible happens.
|
|
28
29
|
- `disabled` on an item renders `aria-disabled`: it stays announced and reachable with the arrow keys, and does nothing. A disabled `Menu.LinkItem` also drops its `href`, so no click or context menu reaches the URL. On the trigger it keeps the button focusable and stops it opening.
|
|
30
|
+
- `description` on `Menu.Item` or `Menu.LinkItem` puts a short line of muted text below the label, such as why a disabled item cannot act ("Already running"). The item grows to fit both lines. Put secondary text there, never as a second line in the children, which overlaps the label and joins its name.
|
|
29
31
|
- `Menu.Group` takes a `label` that is shown and names the group. Separate groups with `Menu.Separator`.
|
|
30
32
|
- `Menu.Separator` draws a line inside its own padding (`paddingBlock="4"`, `paddingInline="8"`) and sets no margin. Change its spacing with `paddingBlock` and `paddingInline` (the `padding` shorthand loses to these defaults, decision 0065); a `margin*` prop adds space outside the padding. `style={{ borderBlockStartColor }}` recolours the line.
|
|
31
33
|
- The popup portals into the trigger's nearest `ThemeProvider`, so it keeps the brand and mode. That provider must not clip or stack its content: wrap the app root, and keep a nested provider off elements with `overflow: hidden`, a `transform` or their own `z-index`, or the popup is clipped or drawn under siblings. It sits on `zIndex` `popover`. A menu opened only through `open`, with no `Menu.Trigger`, has no provider to find and portals to `<body>`.
|
|
@@ -38,9 +40,7 @@ A list of actions that opens from a button: a row's "Edit, Duplicate, Delete", a
|
|
|
38
40
|
|
|
39
41
|
```tsx
|
|
40
42
|
<Menu>
|
|
41
|
-
<Menu.Trigger
|
|
42
|
-
<MoreIcon />
|
|
43
|
-
</Menu.Trigger>
|
|
43
|
+
<Menu.Trigger icon={EllipsisIcon} label="Actions for Invoice 42" />
|
|
44
44
|
<Menu.Popup>
|
|
45
45
|
<Menu.Item onClick={edit}>Edit</Menu.Item>
|
|
46
46
|
<Menu.Item onClick={duplicate}>Duplicate</Menu.Item>
|
|
@@ -61,6 +61,20 @@ A list of actions that opens from a button: a row's "Edit, Duplicate, Delete", a
|
|
|
61
61
|
</Menu.Popup>
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
+
```tsx
|
|
65
|
+
<Menu>
|
|
66
|
+
<Menu.Trigger icon={EllipsisIcon} label="More actions" size="sm" />
|
|
67
|
+
<Menu.Popup>
|
|
68
|
+
<Menu.Item onClick={retry} description="Runs it again from the start">
|
|
69
|
+
Retry
|
|
70
|
+
</Menu.Item>
|
|
71
|
+
<Menu.Item disabled description="Already running">
|
|
72
|
+
Unqueue
|
|
73
|
+
</Menu.Item>
|
|
74
|
+
</Menu.Popup>
|
|
75
|
+
</Menu>
|
|
76
|
+
```
|
|
77
|
+
|
|
64
78
|
```tsx
|
|
65
79
|
<Menu>
|
|
66
80
|
<Menu.Trigger variant="secondary" size="sm">
|
|
@@ -93,6 +107,19 @@ A list of actions that opens from a button: a row's "Edit, Duplicate, Delete", a
|
|
|
93
107
|
</Menu.Item>
|
|
94
108
|
```
|
|
95
109
|
|
|
110
|
+
```tsx
|
|
111
|
+
// Button's padding makes this wider than an IconButton. Use icon={EllipsisIcon} label="More actions".
|
|
112
|
+
<Menu.Trigger iconStart={EllipsisIcon} aria-label="More actions" size="sm" />
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
// The second line overlaps the label and joins the item's name. Use description="Already running".
|
|
117
|
+
<Menu.Item disabled>
|
|
118
|
+
Unqueue
|
|
119
|
+
<Text size="xs">Already running</Text>
|
|
120
|
+
</Menu.Item>
|
|
121
|
+
```
|
|
122
|
+
|
|
96
123
|
```tsx
|
|
97
124
|
// Base UI already moves focus with the arrow keys; this fights it.
|
|
98
125
|
<Menu.Item onKeyDown={(event) => event.key === "ArrowDown" && next()}>Edit</Menu.Item>
|
|
@@ -116,7 +143,10 @@ A list of actions that opens from a button: a row's "Edit, Duplicate, Delete", a
|
|
|
116
143
|
- The trigger has `aria-haspopup="menu"` and `aria-expanded`; the popup is `role="menu"` labelled by the trigger, items and link items are `role="menuitem"` (a link item is an `<a>` with an `href`, so the browser treats it as a link), groups are `role="group"` named by their label.
|
|
117
144
|
- Opening from the keyboard focuses the first item; from the pointer, the popup. Focus stays in the menu until it closes. Closed by Esc, an item or `open={false}`, focus returns at once to the trigger that opened it, so a Tab pressed while it fades goes on to the control after the trigger. A press outside, a Tab out, a hover menu the pointer left, or a popup with `finalFocus` leaves focus to Base UI, which places it when the fade ends.
|
|
118
145
|
- A closed menu stays on the page while it fades out, but is `inert` and `aria-hidden` from the moment it closes, so a menu opened during the fade (the next row's) is the only one a screen reader or a role query finds, and nothing in the fading one takes focus or a click.
|
|
119
|
-
- The
|
|
146
|
+
- The icon trigger's name is its `label`, as `aria-label`.
|
|
147
|
+
- An item's `description` is its accessible description (`aria-describedby`), read after its name; the name stays the label alone. An `aria-describedby` of the item's own is kept, read after the description. With plain-text children, typeahead matches the label alone, not the description; otherwise pass `label`.
|
|
148
|
+
- The popup is never wider than the viewport beside its trigger, so at 320 px and 200% text a long item wraps inside it (WCAG 1.4.10).
|
|
149
|
+
- The highlighted item gets a fill (`bgMuted` in light mode; in dark mode `bgRaised` with 10% `fg` mixed in, since `bgMuted` sits too close to the popup there), the same from the pointer and the keyboard. From the keyboard it also gets the shared focus ring, drawn inside the item so it never meets the popup's edge; the fill alone is under 3:1 on the popup, the ring passes 3:1 on the fill (`Menu.test.tsx` checks it). Under forced colors it is `Highlight` with `HighlightText`; from the keyboard the fill drops to `Canvas` so the `Highlight` ring alone marks the item; disabled items are `GrayText` on the page's fill even when highlighted (`GrayText` pairs with `Canvas` only) and marked by the ring, and the popup keeps its border.
|
|
120
150
|
- The danger item's `danger` color passes 4.5:1 on the popup and on the highlight fill in every preset (`Menu.test.tsx` checks it, with `fg` and `fgMuted`); the word ("Delete") carries the meaning, not the color.
|
|
121
151
|
|
|
122
152
|
## Props
|
|
@@ -152,6 +182,7 @@ Also accepts the style props (see `manifest.json` `styleProps`).
|
|
|
152
182
|
| --- | --- | --- | --- |
|
|
153
183
|
| `className` | `string` | no | |
|
|
154
184
|
| `closeOnClick` | `boolean` | no | Whether to close the menu when the item is clicked. |
|
|
185
|
+
| `description` | `ReactNode` | no | |
|
|
155
186
|
| `disabled` | `boolean` | no | Whether the component should ignore user interaction. |
|
|
156
187
|
| `id` | `string` | no | |
|
|
157
188
|
| `label` | `string` | no | Overrides the text used for keyboard text navigation and filtering. Falls back to the rendered text when not provided. |
|
|
@@ -168,6 +199,7 @@ Also accepts the style props (see `manifest.json` `styleProps`).
|
|
|
168
199
|
| --- | --- | --- | --- |
|
|
169
200
|
| `className` | `string` | no | |
|
|
170
201
|
| `closeOnClick` | `boolean` | no | Whether to close the menu when the item is clicked. |
|
|
202
|
+
| `description` | `ReactNode` | no | |
|
|
171
203
|
| `disabled` | `boolean` | no | |
|
|
172
204
|
| `href` | `string` | yes | |
|
|
173
205
|
| `id` | `string` | no | |
|
|
@@ -204,13 +236,17 @@ Also accepts the style props (see `manifest.json` `styleProps`).
|
|
|
204
236
|
|
|
205
237
|
| Prop | Type | Required | Description |
|
|
206
238
|
| --- | --- | --- | --- |
|
|
239
|
+
| `aria-label` | `string` | no | Defines a string value that labels the current element. |
|
|
240
|
+
| `aria-labelledby` | `string` | no | Identifies the element (or elements) that labels the current element. |
|
|
207
241
|
| `children` | `ReactNode` | no | |
|
|
208
242
|
| `closeDelay` | `number` | no | How long to wait before closing the menu that was opened on hover. Specified in milliseconds. Requires the `openOnHover` prop. |
|
|
209
243
|
| `delay` | `number` | no | How long to wait before the menu may be opened on hover. Specified in milliseconds. Requires the `openOnHover` prop. |
|
|
210
244
|
| `disabled` | `boolean` | no | Whether the component should ignore user interaction. |
|
|
211
245
|
| `handle` | `MenuHandle<unknown>` | no | A handle to associate the trigger with a menu. |
|
|
246
|
+
| `icon` | `ComponentType` | no | |
|
|
212
247
|
| `iconEnd` | `ComponentType` | no | |
|
|
213
248
|
| `iconStart` | `ComponentType` | no | |
|
|
249
|
+
| `label` | `string` | no | |
|
|
214
250
|
| `openOnHover` | `boolean` | no | Whether the menu should also open when the trigger is hovered. |
|
|
215
251
|
| `payload` | `unknown` | no | A payload to pass to the menu when it is opened. |
|
|
216
252
|
| `size` | `"lg" \| "med" \| "sm"` | no | |
|
package/dist/docs/MultiSelect.md
CHANGED
|
@@ -25,6 +25,7 @@ A form field for picking any number of values from a list too long to show at on
|
|
|
25
25
|
- `value` with `onValueChange` controls it; `defaultValue` leaves it uncontrolled. Both are arrays of option values, and `onValueChange` gets the new array.
|
|
26
26
|
- `name` makes each selected value submit as its own `name=value` pair, as a `<select multiple>` does; read them with `formData.getAll(name)`. Nothing selected submits nothing.
|
|
27
27
|
- `placeholder` (`"Select"`) shows while nothing is selected. `countLabel` (`"{count} selected"`) is the summary once the joined labels do not fit; `{count}` is replaced with the number selected. Translate both. One selected label that does not fit is truncated, not replaced by a count.
|
|
28
|
+
- `size` (`sm`, `med`, `lg`; default `med`) is the trigger's, as Button's: it matches a SearchField, TextField or Button of the same size in height. The list's options do not change size.
|
|
28
29
|
- `disabled` takes the trigger out of the tab order and mutes the label. `required` sets `aria-required` on the trigger; report a missing value through `error`.
|
|
29
30
|
- The trigger and the open listbox are both named by `label`.
|
|
30
31
|
- Style props, `className` and `style` go to the `Field` around the label, trigger and messages, not to the trigger or the popup.
|
|
@@ -91,9 +92,9 @@ A form field for picking any number of values from a list too long to show at on
|
|
|
91
92
|
- The trigger is a button with `aria-haspopup="listbox"` and `aria-expanded`, labelled by the `Field` label and described by the description and error. The popup is `role="listbox"` with `aria-multiselectable="true"`, options are `role="option"` with `aria-selected`.
|
|
92
93
|
- Opening from the keyboard focuses an option; focus stays in the list until it closes. Choosing an option toggles it and leaves the list open, so several can be picked in one visit. Closed by Esc or the trigger, focus returns at once to the trigger, so a Tab pressed while the list fades goes on to the next control. A press outside or a Tab out leaves focus to Base UI.
|
|
93
94
|
- A closed list stays on the page while it fades out, but is `inert` and `aria-hidden` from the moment it closes, so a list opened during the fade (the next filter's) is the only one a screen reader or a role query finds, and nothing in the fading one takes focus or a click (ADR 0113).
|
|
94
|
-
- Selection is a check mark on the option as well as its highlight, so it is not color alone. The check
|
|
95
|
+
- Selection is a check mark on the option as well as its highlight, so it is not color alone. The check sits at the end of the row; its space is always kept, so the labels start at the option's padding and never shift.
|
|
95
96
|
- The trigger summary is text: the joined labels, or the count. When the count replaces the labels, the labels are hidden from assistive technology so the count is read once.
|
|
96
|
-
- The shared focus ring shows on the trigger and, from the keyboard, on the highlighted option. Under forced colors the highlighted option is `Highlight` with `HighlightText
|
|
97
|
+
- The shared focus ring shows on the trigger and, from the keyboard, on the highlighted option, drawn inset so the popup's edge does not crowd or clip it (ADR 0122). Under forced colors the pointer's highlighted option is `Highlight` with `HighlightText`; a keyboard-focused one keeps `Canvas` so the `Highlight` ring shows, and the popup keeps its border.
|
|
97
98
|
|
|
98
99
|
## Props
|
|
99
100
|
|
|
@@ -115,6 +116,7 @@ Generated from the TypeScript types.
|
|
|
115
116
|
| `options` | `readonly Option[]` | yes | |
|
|
116
117
|
| `placeholder` | `string` | no | |
|
|
117
118
|
| `required` | `boolean` | no | |
|
|
119
|
+
| `size` | `"lg" \| "med" \| "sm"` | no | |
|
|
118
120
|
| `style` | `CSSProperties` | no | |
|
|
119
121
|
| `value` | `readonly string[]` | no | |
|
|
120
122
|
|
package/dist/docs/manifest.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "./manifest.schema.json",
|
|
3
3
|
"package": "@jonmilner/ui",
|
|
4
|
-
"version": "0.8.
|
|
4
|
+
"version": "0.8.2",
|
|
5
5
|
"components": [
|
|
6
6
|
{
|
|
7
7
|
"name": "AlertDialog",
|
|
@@ -1301,6 +1301,11 @@
|
|
|
1301
1301
|
"required": false,
|
|
1302
1302
|
"description": "Whether to close the menu when the item is clicked."
|
|
1303
1303
|
},
|
|
1304
|
+
{
|
|
1305
|
+
"name": "description",
|
|
1306
|
+
"type": "ReactNode",
|
|
1307
|
+
"required": false
|
|
1308
|
+
},
|
|
1304
1309
|
{
|
|
1305
1310
|
"name": "disabled",
|
|
1306
1311
|
"type": "boolean",
|
|
@@ -1361,6 +1366,11 @@
|
|
|
1361
1366
|
"required": false,
|
|
1362
1367
|
"description": "Whether to close the menu when the item is clicked."
|
|
1363
1368
|
},
|
|
1369
|
+
{
|
|
1370
|
+
"name": "description",
|
|
1371
|
+
"type": "ReactNode",
|
|
1372
|
+
"required": false
|
|
1373
|
+
},
|
|
1364
1374
|
{
|
|
1365
1375
|
"name": "disabled",
|
|
1366
1376
|
"type": "boolean",
|
|
@@ -1476,6 +1486,18 @@
|
|
|
1476
1486
|
"name": "Menu.Trigger",
|
|
1477
1487
|
"styleProps": true,
|
|
1478
1488
|
"props": [
|
|
1489
|
+
{
|
|
1490
|
+
"name": "aria-label",
|
|
1491
|
+
"type": "string",
|
|
1492
|
+
"required": false,
|
|
1493
|
+
"description": "Defines a string value that labels the current element."
|
|
1494
|
+
},
|
|
1495
|
+
{
|
|
1496
|
+
"name": "aria-labelledby",
|
|
1497
|
+
"type": "string",
|
|
1498
|
+
"required": false,
|
|
1499
|
+
"description": "Identifies the element (or elements) that labels the current element."
|
|
1500
|
+
},
|
|
1479
1501
|
{
|
|
1480
1502
|
"name": "children",
|
|
1481
1503
|
"type": "ReactNode",
|
|
@@ -1505,6 +1527,11 @@
|
|
|
1505
1527
|
"required": false,
|
|
1506
1528
|
"description": "A handle to associate the trigger with a menu."
|
|
1507
1529
|
},
|
|
1530
|
+
{
|
|
1531
|
+
"name": "icon",
|
|
1532
|
+
"type": "ComponentType",
|
|
1533
|
+
"required": false
|
|
1534
|
+
},
|
|
1508
1535
|
{
|
|
1509
1536
|
"name": "iconEnd",
|
|
1510
1537
|
"type": "ComponentType",
|
|
@@ -1515,6 +1542,11 @@
|
|
|
1515
1542
|
"type": "ComponentType",
|
|
1516
1543
|
"required": false
|
|
1517
1544
|
},
|
|
1545
|
+
{
|
|
1546
|
+
"name": "label",
|
|
1547
|
+
"type": "string",
|
|
1548
|
+
"required": false
|
|
1549
|
+
},
|
|
1518
1550
|
{
|
|
1519
1551
|
"name": "openOnHover",
|
|
1520
1552
|
"type": "boolean",
|
|
@@ -1615,6 +1647,16 @@
|
|
|
1615
1647
|
"type": "boolean",
|
|
1616
1648
|
"required": false
|
|
1617
1649
|
},
|
|
1650
|
+
{
|
|
1651
|
+
"name": "size",
|
|
1652
|
+
"type": "\"lg\" | \"med\" | \"sm\"",
|
|
1653
|
+
"required": false,
|
|
1654
|
+
"values": [
|
|
1655
|
+
"lg",
|
|
1656
|
+
"med",
|
|
1657
|
+
"sm"
|
|
1658
|
+
]
|
|
1659
|
+
},
|
|
1618
1660
|
{
|
|
1619
1661
|
"name": "style",
|
|
1620
1662
|
"type": "CSSProperties",
|