@diwauhris/ui 1.7.20 → 1.7.21
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/lib/index.cjs +58 -17
- package/lib/index.mjs +58 -17
- package/lib/types/ui-library/gallery/menu/Menu.d.ts +21 -4
- package/package.json +1 -1
package/lib/index.cjs
CHANGED
|
@@ -3924,9 +3924,15 @@ function Dropdown({ trigger, isOpen, onToggle, onClose, children, triggerClassNa
|
|
|
3924
3924
|
* Menu — Design System Component
|
|
3925
3925
|
*
|
|
3926
3926
|
* A dropdown menu anchored to a trigger. Opens on trigger click,
|
|
3927
|
-
* closes on outside-click or
|
|
3928
|
-
* ArrowDown/ArrowUp
|
|
3929
|
-
* Escape
|
|
3927
|
+
* closes on outside-click, Escape, or scroll. Full keyboard navigation:
|
|
3928
|
+
* ArrowDown/ArrowUp move between items (skipping disabled), Home/End jump to
|
|
3929
|
+
* the first/last enabled item, Escape closes. When focus is on a closed
|
|
3930
|
+
* trigger, Enter/Space/ArrowDown open it and focus the first item; ArrowUp
|
|
3931
|
+
* opens it and focuses the last item.
|
|
3932
|
+
*
|
|
3933
|
+
* The panel renders in a body portal with fixed positioning: it flips above
|
|
3934
|
+
* the trigger when there isn't room below, and clamps horizontally so it never
|
|
3935
|
+
* overflows the viewport.
|
|
3930
3936
|
*
|
|
3931
3937
|
* Follows WAI-ARIA Menu Button pattern:
|
|
3932
3938
|
* - trigger: role="button", aria-haspopup="menu", aria-expanded
|
|
@@ -3942,7 +3948,7 @@ function Dropdown({ trigger, isOpen, onToggle, onClose, children, triggerClassNa
|
|
|
3942
3948
|
* ]}
|
|
3943
3949
|
* />
|
|
3944
3950
|
*/
|
|
3945
|
-
function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: controlledOpen, onOpenChange, panelClassName = "" }) {
|
|
3951
|
+
function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: controlledOpen, onOpenChange, closeOnSelect = true, panelClassName = "" }) {
|
|
3946
3952
|
const [internalOpen, setInternalOpen] = (0, react.useState)(false);
|
|
3947
3953
|
const isControlled = controlledOpen !== void 0;
|
|
3948
3954
|
const open = isControlled ? controlledOpen : internalOpen;
|
|
@@ -3955,6 +3961,7 @@ function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: contr
|
|
|
3955
3961
|
const panelRef = (0, react.useRef)(null);
|
|
3956
3962
|
const itemRefs = (0, react.useRef)([]);
|
|
3957
3963
|
const [panelStyle, setPanelStyle] = (0, react.useState)({});
|
|
3964
|
+
const pendingFocusRef = (0, react.useRef)("first");
|
|
3958
3965
|
(0, react.useEffect)(() => {
|
|
3959
3966
|
if (!open || !triggerRef.current) return;
|
|
3960
3967
|
const GAP = 4;
|
|
@@ -3969,21 +3976,23 @@ function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: contr
|
|
|
3969
3976
|
const panelHeight = panelRef.current?.offsetHeight ?? items.length * ROW_HEIGHT + HEADER_HEIGHT;
|
|
3970
3977
|
const spaceBelow = window.innerHeight - rect.bottom;
|
|
3971
3978
|
const flipUp = spaceBelow < panelHeight + GAP + MARGIN && rect.top > spaceBelow;
|
|
3979
|
+
const panelWidth = Math.max(panelRef.current?.offsetWidth ?? 0, rect.width, PANEL_MIN_WIDTH);
|
|
3980
|
+
const desiredLeft = align === "left" ? rect.left : rect.right - panelWidth;
|
|
3981
|
+
const maxLeft = window.innerWidth - panelWidth - MARGIN;
|
|
3982
|
+
const left = Math.min(Math.max(MARGIN, desiredLeft), Math.max(MARGIN, maxLeft));
|
|
3972
3983
|
setPanelStyle({
|
|
3973
3984
|
position: "fixed",
|
|
3974
3985
|
...flipUp ? { bottom: Math.max(MARGIN, window.innerHeight - rect.top + GAP) } : { top: rect.bottom + GAP },
|
|
3975
|
-
left
|
|
3986
|
+
left,
|
|
3976
3987
|
zIndex: 9999,
|
|
3977
3988
|
minWidth: Math.max(rect.width, PANEL_MIN_WIDTH)
|
|
3978
3989
|
});
|
|
3979
3990
|
};
|
|
3980
3991
|
reposition();
|
|
3981
3992
|
const raf = window.requestAnimationFrame(reposition);
|
|
3982
|
-
window.addEventListener("scroll", reposition, true);
|
|
3983
3993
|
window.addEventListener("resize", reposition);
|
|
3984
3994
|
return () => {
|
|
3985
3995
|
window.cancelAnimationFrame(raf);
|
|
3986
|
-
window.removeEventListener("scroll", reposition, true);
|
|
3987
3996
|
window.removeEventListener("resize", reposition);
|
|
3988
3997
|
};
|
|
3989
3998
|
}, [
|
|
@@ -4007,33 +4016,64 @@ function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: contr
|
|
|
4007
4016
|
(triggerRef.current?.querySelector("button,a,[tabindex]"))?.focus();
|
|
4008
4017
|
}
|
|
4009
4018
|
};
|
|
4019
|
+
const handleScroll = (e) => {
|
|
4020
|
+
if (panelRef.current && e.target instanceof Node && panelRef.current.contains(e.target)) return;
|
|
4021
|
+
setOpen(false);
|
|
4022
|
+
};
|
|
4010
4023
|
document.addEventListener("mousedown", handlePointerDown);
|
|
4011
4024
|
document.addEventListener("keydown", handleKeyDown);
|
|
4025
|
+
window.addEventListener("scroll", handleScroll, true);
|
|
4012
4026
|
window.setTimeout(() => {
|
|
4013
|
-
itemRefs.current.
|
|
4027
|
+
const enabled = itemRefs.current.map((node, i) => ({
|
|
4028
|
+
node,
|
|
4029
|
+
i
|
|
4030
|
+
})).filter((x) => x.node && !x.node.disabled);
|
|
4031
|
+
(pendingFocusRef.current === "last" ? enabled[enabled.length - 1] : enabled[0])?.node?.focus();
|
|
4032
|
+
pendingFocusRef.current = "first";
|
|
4014
4033
|
}, 0);
|
|
4015
4034
|
return () => {
|
|
4016
4035
|
document.removeEventListener("mousedown", handlePointerDown);
|
|
4017
4036
|
document.removeEventListener("keydown", handleKeyDown);
|
|
4037
|
+
window.removeEventListener("scroll", handleScroll, true);
|
|
4018
4038
|
};
|
|
4019
4039
|
}, [open]);
|
|
4020
|
-
const
|
|
4021
|
-
const
|
|
4022
|
-
|
|
4040
|
+
const focusFrom = (index, dir) => {
|
|
4041
|
+
const n = items.length;
|
|
4042
|
+
if (n === 0) return;
|
|
4043
|
+
for (let step = 0; step < n; step++) {
|
|
4044
|
+
const next = ((index + dir * step) % n + n) % n;
|
|
4045
|
+
const node = itemRefs.current[next];
|
|
4046
|
+
if (node && !node.disabled) {
|
|
4047
|
+
node.focus();
|
|
4048
|
+
return;
|
|
4049
|
+
}
|
|
4050
|
+
}
|
|
4023
4051
|
};
|
|
4024
4052
|
const handleItemKeyDown = (e, index) => {
|
|
4025
4053
|
if (e.key === "ArrowDown") {
|
|
4026
4054
|
e.preventDefault();
|
|
4027
|
-
|
|
4055
|
+
focusFrom(index + 1, 1);
|
|
4028
4056
|
} else if (e.key === "ArrowUp") {
|
|
4029
4057
|
e.preventDefault();
|
|
4030
|
-
|
|
4058
|
+
focusFrom(index - 1, -1);
|
|
4031
4059
|
} else if (e.key === "Home") {
|
|
4032
4060
|
e.preventDefault();
|
|
4033
|
-
|
|
4061
|
+
focusFrom(0, 1);
|
|
4034
4062
|
} else if (e.key === "End") {
|
|
4035
4063
|
e.preventDefault();
|
|
4036
|
-
|
|
4064
|
+
focusFrom(items.length - 1, -1);
|
|
4065
|
+
}
|
|
4066
|
+
};
|
|
4067
|
+
const handleTriggerKeyDown = (e) => {
|
|
4068
|
+
if (open) return;
|
|
4069
|
+
if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " " || e.key === "Spacebar") {
|
|
4070
|
+
e.preventDefault();
|
|
4071
|
+
pendingFocusRef.current = "first";
|
|
4072
|
+
setOpen(true);
|
|
4073
|
+
} else if (e.key === "ArrowUp") {
|
|
4074
|
+
e.preventDefault();
|
|
4075
|
+
pendingFocusRef.current = "last";
|
|
4076
|
+
setOpen(true);
|
|
4037
4077
|
}
|
|
4038
4078
|
};
|
|
4039
4079
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
@@ -4042,6 +4082,7 @@ function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: contr
|
|
|
4042
4082
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4043
4083
|
ref: triggerRef,
|
|
4044
4084
|
onClick: () => setOpen(!open),
|
|
4085
|
+
onKeyDown: handleTriggerKeyDown,
|
|
4045
4086
|
className: "cursor-pointer",
|
|
4046
4087
|
children: (0, react.isValidElement)(trigger) ? (0, react.cloneElement)(trigger, {
|
|
4047
4088
|
"aria-expanded": open,
|
|
@@ -4061,7 +4102,7 @@ function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: contr
|
|
|
4061
4102
|
role: "menuitem",
|
|
4062
4103
|
disabled: item.disabled,
|
|
4063
4104
|
onClick: () => {
|
|
4064
|
-
setOpen(false);
|
|
4105
|
+
if (closeOnSelect) setOpen(false);
|
|
4065
4106
|
item.onClick();
|
|
4066
4107
|
},
|
|
4067
4108
|
onKeyDown: (e) => handleItemKeyDown(e, index),
|
|
@@ -4077,7 +4118,7 @@ function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: contr
|
|
|
4077
4118
|
"aria-hidden": "true",
|
|
4078
4119
|
children: item.icon
|
|
4079
4120
|
}), item.label]
|
|
4080
|
-
}, item.label))
|
|
4121
|
+
}, item.id ?? item.label ?? index))
|
|
4081
4122
|
}), document.body)]
|
|
4082
4123
|
});
|
|
4083
4124
|
}
|
package/lib/index.mjs
CHANGED
|
@@ -3900,9 +3900,15 @@ function Dropdown({ trigger, isOpen, onToggle, onClose, children, triggerClassNa
|
|
|
3900
3900
|
* Menu — Design System Component
|
|
3901
3901
|
*
|
|
3902
3902
|
* A dropdown menu anchored to a trigger. Opens on trigger click,
|
|
3903
|
-
* closes on outside-click or
|
|
3904
|
-
* ArrowDown/ArrowUp
|
|
3905
|
-
* Escape
|
|
3903
|
+
* closes on outside-click, Escape, or scroll. Full keyboard navigation:
|
|
3904
|
+
* ArrowDown/ArrowUp move between items (skipping disabled), Home/End jump to
|
|
3905
|
+
* the first/last enabled item, Escape closes. When focus is on a closed
|
|
3906
|
+
* trigger, Enter/Space/ArrowDown open it and focus the first item; ArrowUp
|
|
3907
|
+
* opens it and focuses the last item.
|
|
3908
|
+
*
|
|
3909
|
+
* The panel renders in a body portal with fixed positioning: it flips above
|
|
3910
|
+
* the trigger when there isn't room below, and clamps horizontally so it never
|
|
3911
|
+
* overflows the viewport.
|
|
3906
3912
|
*
|
|
3907
3913
|
* Follows WAI-ARIA Menu Button pattern:
|
|
3908
3914
|
* - trigger: role="button", aria-haspopup="menu", aria-expanded
|
|
@@ -3918,7 +3924,7 @@ function Dropdown({ trigger, isOpen, onToggle, onClose, children, triggerClassNa
|
|
|
3918
3924
|
* ]}
|
|
3919
3925
|
* />
|
|
3920
3926
|
*/
|
|
3921
|
-
function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: controlledOpen, onOpenChange, panelClassName = "" }) {
|
|
3927
|
+
function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: controlledOpen, onOpenChange, closeOnSelect = true, panelClassName = "" }) {
|
|
3922
3928
|
const [internalOpen, setInternalOpen] = useState(false);
|
|
3923
3929
|
const isControlled = controlledOpen !== void 0;
|
|
3924
3930
|
const open = isControlled ? controlledOpen : internalOpen;
|
|
@@ -3931,6 +3937,7 @@ function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: contr
|
|
|
3931
3937
|
const panelRef = useRef(null);
|
|
3932
3938
|
const itemRefs = useRef([]);
|
|
3933
3939
|
const [panelStyle, setPanelStyle] = useState({});
|
|
3940
|
+
const pendingFocusRef = useRef("first");
|
|
3934
3941
|
useEffect(() => {
|
|
3935
3942
|
if (!open || !triggerRef.current) return;
|
|
3936
3943
|
const GAP = 4;
|
|
@@ -3945,21 +3952,23 @@ function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: contr
|
|
|
3945
3952
|
const panelHeight = panelRef.current?.offsetHeight ?? items.length * ROW_HEIGHT + HEADER_HEIGHT;
|
|
3946
3953
|
const spaceBelow = window.innerHeight - rect.bottom;
|
|
3947
3954
|
const flipUp = spaceBelow < panelHeight + GAP + MARGIN && rect.top > spaceBelow;
|
|
3955
|
+
const panelWidth = Math.max(panelRef.current?.offsetWidth ?? 0, rect.width, PANEL_MIN_WIDTH);
|
|
3956
|
+
const desiredLeft = align === "left" ? rect.left : rect.right - panelWidth;
|
|
3957
|
+
const maxLeft = window.innerWidth - panelWidth - MARGIN;
|
|
3958
|
+
const left = Math.min(Math.max(MARGIN, desiredLeft), Math.max(MARGIN, maxLeft));
|
|
3948
3959
|
setPanelStyle({
|
|
3949
3960
|
position: "fixed",
|
|
3950
3961
|
...flipUp ? { bottom: Math.max(MARGIN, window.innerHeight - rect.top + GAP) } : { top: rect.bottom + GAP },
|
|
3951
|
-
left
|
|
3962
|
+
left,
|
|
3952
3963
|
zIndex: 9999,
|
|
3953
3964
|
minWidth: Math.max(rect.width, PANEL_MIN_WIDTH)
|
|
3954
3965
|
});
|
|
3955
3966
|
};
|
|
3956
3967
|
reposition();
|
|
3957
3968
|
const raf = window.requestAnimationFrame(reposition);
|
|
3958
|
-
window.addEventListener("scroll", reposition, true);
|
|
3959
3969
|
window.addEventListener("resize", reposition);
|
|
3960
3970
|
return () => {
|
|
3961
3971
|
window.cancelAnimationFrame(raf);
|
|
3962
|
-
window.removeEventListener("scroll", reposition, true);
|
|
3963
3972
|
window.removeEventListener("resize", reposition);
|
|
3964
3973
|
};
|
|
3965
3974
|
}, [
|
|
@@ -3983,33 +3992,64 @@ function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: contr
|
|
|
3983
3992
|
(triggerRef.current?.querySelector("button,a,[tabindex]"))?.focus();
|
|
3984
3993
|
}
|
|
3985
3994
|
};
|
|
3995
|
+
const handleScroll = (e) => {
|
|
3996
|
+
if (panelRef.current && e.target instanceof Node && panelRef.current.contains(e.target)) return;
|
|
3997
|
+
setOpen(false);
|
|
3998
|
+
};
|
|
3986
3999
|
document.addEventListener("mousedown", handlePointerDown);
|
|
3987
4000
|
document.addEventListener("keydown", handleKeyDown);
|
|
4001
|
+
window.addEventListener("scroll", handleScroll, true);
|
|
3988
4002
|
window.setTimeout(() => {
|
|
3989
|
-
itemRefs.current.
|
|
4003
|
+
const enabled = itemRefs.current.map((node, i) => ({
|
|
4004
|
+
node,
|
|
4005
|
+
i
|
|
4006
|
+
})).filter((x) => x.node && !x.node.disabled);
|
|
4007
|
+
(pendingFocusRef.current === "last" ? enabled[enabled.length - 1] : enabled[0])?.node?.focus();
|
|
4008
|
+
pendingFocusRef.current = "first";
|
|
3990
4009
|
}, 0);
|
|
3991
4010
|
return () => {
|
|
3992
4011
|
document.removeEventListener("mousedown", handlePointerDown);
|
|
3993
4012
|
document.removeEventListener("keydown", handleKeyDown);
|
|
4013
|
+
window.removeEventListener("scroll", handleScroll, true);
|
|
3994
4014
|
};
|
|
3995
4015
|
}, [open]);
|
|
3996
|
-
const
|
|
3997
|
-
const
|
|
3998
|
-
|
|
4016
|
+
const focusFrom = (index, dir) => {
|
|
4017
|
+
const n = items.length;
|
|
4018
|
+
if (n === 0) return;
|
|
4019
|
+
for (let step = 0; step < n; step++) {
|
|
4020
|
+
const next = ((index + dir * step) % n + n) % n;
|
|
4021
|
+
const node = itemRefs.current[next];
|
|
4022
|
+
if (node && !node.disabled) {
|
|
4023
|
+
node.focus();
|
|
4024
|
+
return;
|
|
4025
|
+
}
|
|
4026
|
+
}
|
|
3999
4027
|
};
|
|
4000
4028
|
const handleItemKeyDown = (e, index) => {
|
|
4001
4029
|
if (e.key === "ArrowDown") {
|
|
4002
4030
|
e.preventDefault();
|
|
4003
|
-
|
|
4031
|
+
focusFrom(index + 1, 1);
|
|
4004
4032
|
} else if (e.key === "ArrowUp") {
|
|
4005
4033
|
e.preventDefault();
|
|
4006
|
-
|
|
4034
|
+
focusFrom(index - 1, -1);
|
|
4007
4035
|
} else if (e.key === "Home") {
|
|
4008
4036
|
e.preventDefault();
|
|
4009
|
-
|
|
4037
|
+
focusFrom(0, 1);
|
|
4010
4038
|
} else if (e.key === "End") {
|
|
4011
4039
|
e.preventDefault();
|
|
4012
|
-
|
|
4040
|
+
focusFrom(items.length - 1, -1);
|
|
4041
|
+
}
|
|
4042
|
+
};
|
|
4043
|
+
const handleTriggerKeyDown = (e) => {
|
|
4044
|
+
if (open) return;
|
|
4045
|
+
if (e.key === "ArrowDown" || e.key === "Enter" || e.key === " " || e.key === "Spacebar") {
|
|
4046
|
+
e.preventDefault();
|
|
4047
|
+
pendingFocusRef.current = "first";
|
|
4048
|
+
setOpen(true);
|
|
4049
|
+
} else if (e.key === "ArrowUp") {
|
|
4050
|
+
e.preventDefault();
|
|
4051
|
+
pendingFocusRef.current = "last";
|
|
4052
|
+
setOpen(true);
|
|
4013
4053
|
}
|
|
4014
4054
|
};
|
|
4015
4055
|
return /* @__PURE__ */ jsxs("div", {
|
|
@@ -4018,6 +4058,7 @@ function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: contr
|
|
|
4018
4058
|
children: [/* @__PURE__ */ jsx("div", {
|
|
4019
4059
|
ref: triggerRef,
|
|
4020
4060
|
onClick: () => setOpen(!open),
|
|
4061
|
+
onKeyDown: handleTriggerKeyDown,
|
|
4021
4062
|
className: "cursor-pointer",
|
|
4022
4063
|
children: isValidElement(trigger) ? cloneElement(trigger, {
|
|
4023
4064
|
"aria-expanded": open,
|
|
@@ -4037,7 +4078,7 @@ function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: contr
|
|
|
4037
4078
|
role: "menuitem",
|
|
4038
4079
|
disabled: item.disabled,
|
|
4039
4080
|
onClick: () => {
|
|
4040
|
-
setOpen(false);
|
|
4081
|
+
if (closeOnSelect) setOpen(false);
|
|
4041
4082
|
item.onClick();
|
|
4042
4083
|
},
|
|
4043
4084
|
onKeyDown: (e) => handleItemKeyDown(e, index),
|
|
@@ -4053,7 +4094,7 @@ function Menu({ trigger, items, ariaLabel = "Menu", align = "right", open: contr
|
|
|
4053
4094
|
"aria-hidden": "true",
|
|
4054
4095
|
children: item.icon
|
|
4055
4096
|
}), item.label]
|
|
4056
|
-
}, item.label))
|
|
4097
|
+
}, item.id ?? item.label ?? index))
|
|
4057
4098
|
}), document.body)]
|
|
4058
4099
|
});
|
|
4059
4100
|
}
|
|
@@ -2,9 +2,15 @@
|
|
|
2
2
|
* Menu — Design System Component
|
|
3
3
|
*
|
|
4
4
|
* A dropdown menu anchored to a trigger. Opens on trigger click,
|
|
5
|
-
* closes on outside-click or
|
|
6
|
-
* ArrowDown/ArrowUp
|
|
7
|
-
* Escape
|
|
5
|
+
* closes on outside-click, Escape, or scroll. Full keyboard navigation:
|
|
6
|
+
* ArrowDown/ArrowUp move between items (skipping disabled), Home/End jump to
|
|
7
|
+
* the first/last enabled item, Escape closes. When focus is on a closed
|
|
8
|
+
* trigger, Enter/Space/ArrowDown open it and focus the first item; ArrowUp
|
|
9
|
+
* opens it and focuses the last item.
|
|
10
|
+
*
|
|
11
|
+
* The panel renders in a body portal with fixed positioning: it flips above
|
|
12
|
+
* the trigger when there isn't room below, and clamps horizontally so it never
|
|
13
|
+
* overflows the viewport.
|
|
8
14
|
*
|
|
9
15
|
* Follows WAI-ARIA Menu Button pattern:
|
|
10
16
|
* - trigger: role="button", aria-haspopup="menu", aria-expanded
|
|
@@ -23,6 +29,12 @@
|
|
|
23
29
|
import { type ReactNode } from 'react';
|
|
24
30
|
export type MenuItemTone = 'default' | 'danger';
|
|
25
31
|
export interface MenuItem {
|
|
32
|
+
/**
|
|
33
|
+
* Stable identity for the item. Used for the React key and focus tracking.
|
|
34
|
+
* Recommended when labels can repeat or the item list is dynamic; falls back
|
|
35
|
+
* to `label` then index when omitted.
|
|
36
|
+
*/
|
|
37
|
+
id?: string;
|
|
26
38
|
label: string;
|
|
27
39
|
icon?: ReactNode;
|
|
28
40
|
onClick: () => void;
|
|
@@ -46,7 +58,12 @@ export interface MenuProps {
|
|
|
46
58
|
open?: boolean;
|
|
47
59
|
/** Called when the menu should open or close. */
|
|
48
60
|
onOpenChange?: (open: boolean) => void;
|
|
61
|
+
/**
|
|
62
|
+
* Close the menu after an item is selected. Default `true`.
|
|
63
|
+
* Set `false` for menus that stay open across clicks (e.g. multi-toggle filters).
|
|
64
|
+
*/
|
|
65
|
+
closeOnSelect?: boolean;
|
|
49
66
|
/** Additional class on the floating panel. */
|
|
50
67
|
panelClassName?: string;
|
|
51
68
|
}
|
|
52
|
-
export declare function Menu({ trigger, items, ariaLabel, align, open: controlledOpen, onOpenChange, panelClassName, }: MenuProps): import("react").JSX.Element;
|
|
69
|
+
export declare function Menu({ trigger, items, ariaLabel, align, open: controlledOpen, onOpenChange, closeOnSelect, panelClassName, }: MenuProps): import("react").JSX.Element;
|