@shadow-js/ui 0.0.0-stage → 1.0.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/CHANGELOG.md +24 -0
- package/LICENSE +21 -0
- package/README.md +598 -2
- package/dist/cli.mjs +2293 -0
- package/dist/dev/cli/schema.d.ts +73 -0
- package/dist/dev/index.d.ts +6 -0
- package/dist/dev/index.js +5 -0
- package/dist/dev/locales/ar.d.ts +141 -0
- package/dist/dev/locales/ar.js +128 -0
- package/dist/dev/locales/ar.js.map +1 -0
- package/dist/dev/locales/en.d.ts +141 -0
- package/dist/dev/locales/en.js +128 -0
- package/dist/dev/locales/en.js.map +1 -0
- package/dist/dev/registry/utils/utils.d.ts +29 -0
- package/dist/dev/registry/utils/utils.js +27 -0
- package/dist/dev/registry/utils/utils.js.map +1 -0
- package/dist/dev/theme/theme-logic.d.ts +187 -0
- package/dist/dev/theme/theme-logic.js +184 -0
- package/dist/dev/theme/theme-logic.js.map +1 -0
- package/dist/dev/theme/theme-provider.d.ts +90 -0
- package/dist/dev/theme/theme-provider.js +150 -0
- package/dist/dev/theme/theme-provider.js.map +1 -0
- package/dist/prod/index.js +1 -0
- package/dist/prod/locales/ar.js +2 -0
- package/dist/prod/locales/ar.js.map +1 -0
- package/dist/prod/locales/en.js +2 -0
- package/dist/prod/locales/en.js.map +1 -0
- package/dist/prod/registry/utils/utils.js +2 -0
- package/dist/prod/registry/utils/utils.js.map +1 -0
- package/dist/prod/theme/theme-logic.js +2 -0
- package/dist/prod/theme/theme-logic.js.map +1 -0
- package/dist/prod/theme/theme-provider.js +2 -0
- package/dist/prod/theme/theme-provider.js.map +1 -0
- package/package.json +102 -4
- package/registry/accordion/accordion.tsx +210 -0
- package/registry/accordion/item.json +4 -0
- package/registry/alert/alert.tsx +200 -0
- package/registry/alert/item.json +4 -0
- package/registry/alert-dialog/alert-dialog.tsx +530 -0
- package/registry/alert-dialog/item.json +4 -0
- package/registry/aspect-ratio/aspect-ratio.tsx +71 -0
- package/registry/aspect-ratio/item.json +4 -0
- package/registry/attachment/attachment.tsx +459 -0
- package/registry/attachment/item.json +4 -0
- package/registry/avatar/avatar.tsx +385 -0
- package/registry/avatar/item.json +4 -0
- package/registry/badge/badge.tsx +108 -0
- package/registry/badge/item.json +4 -0
- package/registry/breadcrumb/breadcrumb.tsx +354 -0
- package/registry/breadcrumb/item.json +4 -0
- package/registry/bubble/bubble.tsx +260 -0
- package/registry/bubble/item.json +4 -0
- package/registry/button/button.tsx +125 -0
- package/registry/button/item.json +4 -0
- package/registry/button-group/button-group.tsx +189 -0
- package/registry/button-group/item.json +4 -0
- package/registry/calendar/calendar.tsx +348 -0
- package/registry/calendar/item.json +4 -0
- package/registry/card/card.tsx +311 -0
- package/registry/card/item.json +4 -0
- package/registry/carousel/carousel.tsx +851 -0
- package/registry/carousel/item.json +4 -0
- package/registry/chart/chart.tsx +1956 -0
- package/registry/chart/item.json +4 -0
- package/registry/chart-scale/chart-scale.ts +670 -0
- package/registry/chart-scale/item.json +5 -0
- package/registry/checkbox/checkbox.tsx +79 -0
- package/registry/checkbox/item.json +4 -0
- package/registry/code-block/code-block.tsx +470 -0
- package/registry/code-block/item.json +4 -0
- package/registry/collapsible/collapsible.tsx +117 -0
- package/registry/collapsible/item.json +4 -0
- package/registry/combobox/combobox.tsx +977 -0
- package/registry/combobox/item.json +4 -0
- package/registry/command/command.tsx +757 -0
- package/registry/command/item.json +4 -0
- package/registry/context-menu/context-menu.tsx +697 -0
- package/registry/context-menu/item.json +4 -0
- package/registry/data-table/data-table.tsx +437 -0
- package/registry/data-table/item.json +4 -0
- package/registry/date-picker/date-picker.tsx +349 -0
- package/registry/date-picker/item.json +4 -0
- package/registry/dialog/dialog.tsx +412 -0
- package/registry/dialog/item.json +4 -0
- package/registry/direction/direction.tsx +88 -0
- package/registry/direction/item.json +4 -0
- package/registry/drawer/drawer.tsx +787 -0
- package/registry/drawer/item.json +4 -0
- package/registry/dropdown-menu/dropdown-menu.tsx +692 -0
- package/registry/dropdown-menu/item.json +4 -0
- package/registry/empty/empty.tsx +240 -0
- package/registry/empty/item.json +4 -0
- package/registry/field/field.tsx +624 -0
- package/registry/field/item.json +4 -0
- package/registry/form/form.tsx +1112 -0
- package/registry/form/item.json +4 -0
- package/registry/hover-card/hover-card.tsx +144 -0
- package/registry/hover-card/item.json +4 -0
- package/registry/icons/icons.tsx +1691 -0
- package/registry/icons/item.json +4 -0
- package/registry/input/input.tsx +43 -0
- package/registry/input/item.json +4 -0
- package/registry/input-group/input-group.tsx +315 -0
- package/registry/input-group/item.json +4 -0
- package/registry/input-otp/input-otp.tsx +329 -0
- package/registry/input-otp/item.json +4 -0
- package/registry/item/item.json +4 -0
- package/registry/item/item.tsx +439 -0
- package/registry/kbd/item.json +4 -0
- package/registry/kbd/kbd.tsx +65 -0
- package/registry/label/item.json +4 -0
- package/registry/label/label.tsx +60 -0
- package/registry/marker/item.json +4 -0
- package/registry/marker/marker.tsx +175 -0
- package/registry/menubar/item.json +4 -0
- package/registry/menubar/menubar.tsx +694 -0
- package/registry/message/item.json +4 -0
- package/registry/message/message.tsx +280 -0
- package/registry/message-scroller/item.json +4 -0
- package/registry/message-scroller/message-scroller.tsx +262 -0
- package/registry/native-select/item.json +4 -0
- package/registry/native-select/native-select.tsx +113 -0
- package/registry/navigation-menu/item.json +4 -0
- package/registry/navigation-menu/navigation-menu.tsx +362 -0
- package/registry/pagination/item.json +4 -0
- package/registry/pagination/pagination.tsx +460 -0
- package/registry/password-input/item.json +5 -0
- package/registry/password-input/password-input.tsx +494 -0
- package/registry/popover/item.json +4 -0
- package/registry/popover/popover.tsx +284 -0
- package/registry/progress/item.json +4 -0
- package/registry/progress/progress.tsx +190 -0
- package/registry/questionnaire/item.json +4 -0
- package/registry/questionnaire/questionnaire.tsx +569 -0
- package/registry/radio-group/item.json +4 -0
- package/registry/radio-group/radio-group.tsx +101 -0
- package/registry/resizable/item.json +4 -0
- package/registry/resizable/resizable.tsx +455 -0
- package/registry/scroll-area/item.json +4 -0
- package/registry/scroll-area/scroll-area.tsx +149 -0
- package/registry/select/item.json +4 -0
- package/registry/select/select.tsx +571 -0
- package/registry/separator/item.json +4 -0
- package/registry/separator/separator.tsx +52 -0
- package/registry/sheet/item.json +4 -0
- package/registry/sheet/sheet.tsx +476 -0
- package/registry/sidebar/item.json +4 -0
- package/registry/sidebar/sidebar.tsx +1870 -0
- package/registry/skeleton/item.json +4 -0
- package/registry/skeleton/skeleton.tsx +47 -0
- package/registry/slider/item.json +4 -0
- package/registry/slider/slider.tsx +149 -0
- package/registry/spinner/item.json +4 -0
- package/registry/spinner/spinner.tsx +51 -0
- package/registry/switch/item.json +4 -0
- package/registry/switch/switch.tsx +93 -0
- package/registry/table/item.json +4 -0
- package/registry/table/table.tsx +373 -0
- package/registry/tabs/item.json +4 -0
- package/registry/tabs/tabs.tsx +209 -0
- package/registry/textarea/item.json +4 -0
- package/registry/textarea/textarea.tsx +51 -0
- package/registry/toast/item.json +4 -0
- package/registry/toast/toast.tsx +949 -0
- package/registry/toggle/item.json +4 -0
- package/registry/toggle/toggle.tsx +110 -0
- package/registry/toggle-group/item.json +4 -0
- package/registry/toggle-group/toggle-group.tsx +189 -0
- package/registry/tooltip/item.json +4 -0
- package/registry/tooltip/tooltip.tsx +169 -0
- package/registry/trace/item.json +4 -0
- package/registry/trace/trace.tsx +356 -0
- package/registry/ui-strings/item.json +5 -0
- package/registry/ui-strings/ui-strings.tsx +454 -0
- package/registry/use-highlighted-code/item.json +5 -0
- package/registry/use-highlighted-code/use-highlighted-code.tsx +145 -0
- package/registry/use-mobile/item.json +5 -0
- package/registry/use-mobile/use-mobile.ts +46 -0
- package/registry/utils/item.json +5 -0
- package/registry/utils/utils.ts +38 -0
- package/registry.json +3274 -0
- package/styles/animations.css +321 -0
- package/styles/theme-core.css +55 -0
- package/styles/theme.css +12 -0
- package/styles/themes/gray.css +69 -0
- package/styles/themes/neutral.css +69 -0
- package/styles/themes/slate.css +69 -0
- package/styles/themes/stone.css +69 -0
- package/styles/themes/zinc.css +69 -0
- package/styles/typeset.css +251 -0
|
@@ -0,0 +1,694 @@
|
|
|
1
|
+
import { splitProps } from "@shadow-js/core";
|
|
2
|
+
import {
|
|
3
|
+
type MenubarContentProps,
|
|
4
|
+
type MenubarMenuProps,
|
|
5
|
+
Menubar as MenubarPrimitive,
|
|
6
|
+
type MenubarProps,
|
|
7
|
+
type MenubarTriggerProps,
|
|
8
|
+
type MenuCheckboxItemProps,
|
|
9
|
+
type MenuGroupProps,
|
|
10
|
+
type MenuItemOwnProps,
|
|
11
|
+
type MenuLabelProps,
|
|
12
|
+
type MenuPortalProps,
|
|
13
|
+
type MenuRadioGroupProps,
|
|
14
|
+
type MenuRadioItemProps,
|
|
15
|
+
type MenuSeparatorProps,
|
|
16
|
+
type MenuSubContentProps,
|
|
17
|
+
type MenuSubProps,
|
|
18
|
+
type MenuSubTriggerProps,
|
|
19
|
+
type PolymorphicProps,
|
|
20
|
+
type PolymorphicTarget,
|
|
21
|
+
} from "@shadow-js/primitives";
|
|
22
|
+
import type { ComponentProps, JSX } from "@shadow-js/web";
|
|
23
|
+
import { CheckIcon, ChevronRightIcon, CircleIcon } from "@/components/ui/icons";
|
|
24
|
+
import { type ClassValue, cn } from "@/lib/utils";
|
|
25
|
+
|
|
26
|
+
/** The props as the implementation sees them: the typed own props plus whatever the target takes. */
|
|
27
|
+
type Loose = {
|
|
28
|
+
readonly as?: PolymorphicTarget;
|
|
29
|
+
readonly class?: ClassValue;
|
|
30
|
+
readonly inset?: boolean | undefined;
|
|
31
|
+
readonly variant?: "default" | "destructive" | undefined;
|
|
32
|
+
readonly children?: JSX.Element | undefined;
|
|
33
|
+
readonly [prop: string]: unknown;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/** The placement and entrance animation shared by the menu panels. */
|
|
37
|
+
const PANEL =
|
|
38
|
+
"z-50 min-w-[8rem] origin-(--primitives-transform-origin) rounded-md border bg-popover p-1 text-popover-foreground outline-hidden data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95";
|
|
39
|
+
|
|
40
|
+
/** What every selectable row shares. */
|
|
41
|
+
const ROW =
|
|
42
|
+
"relative flex cursor-default items-center gap-2 rounded-sm text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 forced-colors:focus:bg-[Highlight] forced-colors:focus:text-[HighlightText] forced-colors:data-[disabled]:text-[GrayText] [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4";
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* A horizontal bar of menus (`role="menubar"`). The triggers share one tab stop and move with
|
|
46
|
+
* ArrowLeft and ArrowRight (swapped in right-to-left layouts). While a menu is open, hovering another
|
|
47
|
+
* trigger, or pressing an arrow key, switches to that menu.
|
|
48
|
+
*
|
|
49
|
+
* Keyboard and ARIA: the bar is a `menubar`, and its triggers are `menuitem` buttons. Home and End go
|
|
50
|
+
* to the first and last trigger, and disabled triggers are skipped. Name the bar with `aria-label`,
|
|
51
|
+
* because it has no name of its own. Control the open menu with `value` and `onValueChange` (the
|
|
52
|
+
* value of the open menu), or start uncontrolled with `defaultValue`.
|
|
53
|
+
*
|
|
54
|
+
* shadcn/ui differences: `as` replaces `asChild` on the triggers, items and sub-triggers.
|
|
55
|
+
*
|
|
56
|
+
* @param props The bar's `div` attributes plus `value`, `defaultValue`, `onValueChange`, `dir` and
|
|
57
|
+
* `loop`. `class` adds to the bar's classes.
|
|
58
|
+
* @returns The bar `div` with its menus inside.
|
|
59
|
+
* @example
|
|
60
|
+
* import {
|
|
61
|
+
* Menubar,
|
|
62
|
+
* MenubarContent,
|
|
63
|
+
* MenubarItem,
|
|
64
|
+
* MenubarMenu,
|
|
65
|
+
* MenubarShortcut,
|
|
66
|
+
* MenubarTrigger,
|
|
67
|
+
* } from "@/components/ui/menubar";
|
|
68
|
+
*
|
|
69
|
+
* <Menubar aria-label="Application">
|
|
70
|
+
* <MenubarMenu value="file">
|
|
71
|
+
* <MenubarTrigger>File</MenubarTrigger>
|
|
72
|
+
* <MenubarContent>
|
|
73
|
+
* <MenubarItem>
|
|
74
|
+
* New Tab <MenubarShortcut>Ctrl+T</MenubarShortcut>
|
|
75
|
+
* </MenubarItem>
|
|
76
|
+
* </MenubarContent>
|
|
77
|
+
* </MenubarMenu>
|
|
78
|
+
* </Menubar>
|
|
79
|
+
* @since 1.0.0
|
|
80
|
+
* @see {@link MenubarMenu}
|
|
81
|
+
*/
|
|
82
|
+
function Menubar<T extends PolymorphicTarget = "div">(props: MenubarProps<T>): JSX.Element {
|
|
83
|
+
const [local, rest] = splitProps(props as unknown as Loose, ["class"]);
|
|
84
|
+
return (
|
|
85
|
+
<MenubarPrimitive
|
|
86
|
+
data-slot="menubar"
|
|
87
|
+
class={cn(
|
|
88
|
+
"flex h-9 items-center gap-1 rounded-md border bg-background p-1 shadow-xs",
|
|
89
|
+
local.class,
|
|
90
|
+
)}
|
|
91
|
+
{...rest}
|
|
92
|
+
/>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* One menu of the bar. It pairs a {@link MenubarTrigger} with its {@link MenubarContent}, and it is
|
|
98
|
+
* open while the bar's `value` equals its `value`. It renders no element and handles no keys; the
|
|
99
|
+
* trigger and the content carry the behavior.
|
|
100
|
+
*
|
|
101
|
+
* @param props `value` names the menu (generated when omitted), and `children` are the trigger, the
|
|
102
|
+
* content and anything else in the menu.
|
|
103
|
+
* @returns The menu's children, with no element of its own.
|
|
104
|
+
* @throws Error when rendered outside a {@link Menubar}.
|
|
105
|
+
* @example
|
|
106
|
+
* import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarTrigger } from "@/components/ui/menubar";
|
|
107
|
+
*
|
|
108
|
+
* <Menubar>
|
|
109
|
+
* <MenubarMenu value="edit">
|
|
110
|
+
* <MenubarTrigger>Edit</MenubarTrigger>
|
|
111
|
+
* <MenubarContent>
|
|
112
|
+
* <MenubarItem>Undo</MenubarItem>
|
|
113
|
+
* </MenubarContent>
|
|
114
|
+
* </MenubarMenu>
|
|
115
|
+
* </Menubar>
|
|
116
|
+
* @since 1.0.0
|
|
117
|
+
* @see {@link MenubarTrigger}
|
|
118
|
+
*/
|
|
119
|
+
function MenubarMenu(props: MenubarMenuProps): JSX.Element {
|
|
120
|
+
return <MenubarPrimitive.Menu {...props} />;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Renders its children into `document.body` (or into `container`) while the menu is open. It is
|
|
125
|
+
* client only: nothing renders on the server. {@link MenubarContent} already renders its panel this
|
|
126
|
+
* way, so use this portal for other content that belongs in the menu's layer.
|
|
127
|
+
*
|
|
128
|
+
* @param props `container` (an element, `null`, or a function that returns one; the default is
|
|
129
|
+
* `document.body`) and `forceMount` (keep the children mounted while the menu is closed).
|
|
130
|
+
* @returns The portal, or nothing while the menu is closed.
|
|
131
|
+
* @throws Error when rendered outside a {@link MenubarMenu}.
|
|
132
|
+
* @example
|
|
133
|
+
* import { Menubar, MenubarMenu, MenubarPortal, MenubarTrigger } from "@/components/ui/menubar";
|
|
134
|
+
*
|
|
135
|
+
* <Menubar>
|
|
136
|
+
* <MenubarMenu value="help">
|
|
137
|
+
* <MenubarTrigger>Help</MenubarTrigger>
|
|
138
|
+
* <MenubarPortal container={() => document.body}>
|
|
139
|
+
* <p>Shown in the body while the menu is open.</p>
|
|
140
|
+
* </MenubarPortal>
|
|
141
|
+
* </MenubarMenu>
|
|
142
|
+
* </Menubar>
|
|
143
|
+
* @since 1.0.0
|
|
144
|
+
* @see {@link MenubarContent}
|
|
145
|
+
*/
|
|
146
|
+
function MenubarPortal(props: MenuPortalProps): JSX.Element {
|
|
147
|
+
return <MenubarPrimitive.Portal {...props} />;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* The button of the bar that opens its menu. Its `data-state` is `open` or `closed`.
|
|
152
|
+
*
|
|
153
|
+
* Keyboard and ARIA: a `menuitem` button with `aria-haspopup="menu"`, `aria-expanded`, and
|
|
154
|
+
* `aria-controls` while its menu is open. ArrowLeft and ArrowRight move to the neighboring trigger.
|
|
155
|
+
* ArrowDown, Enter and Space open the menu and focus its first item; ArrowUp opens it and focuses the
|
|
156
|
+
* last item. A pointer press toggles the menu. Its name is its text.
|
|
157
|
+
*
|
|
158
|
+
* @param props The button's attributes, plus `as` (the element to render in its place).
|
|
159
|
+
* @returns The trigger element.
|
|
160
|
+
* @throws Error when rendered outside a {@link Menubar}.
|
|
161
|
+
* @example
|
|
162
|
+
* import { Menubar, MenubarMenu, MenubarTrigger } from "@/components/ui/menubar";
|
|
163
|
+
*
|
|
164
|
+
* <Menubar>
|
|
165
|
+
* <MenubarMenu value="edit">
|
|
166
|
+
* <MenubarTrigger>Edit</MenubarTrigger>
|
|
167
|
+
* </MenubarMenu>
|
|
168
|
+
* </Menubar>
|
|
169
|
+
* @since 1.0.0
|
|
170
|
+
* @see {@link MenubarContent}
|
|
171
|
+
*/
|
|
172
|
+
function MenubarTrigger<T extends PolymorphicTarget = "button">(
|
|
173
|
+
props: MenubarTriggerProps<T>,
|
|
174
|
+
): JSX.Element {
|
|
175
|
+
const [local, rest] = splitProps(props as unknown as Loose, ["class"]);
|
|
176
|
+
return (
|
|
177
|
+
<MenubarPrimitive.Trigger
|
|
178
|
+
data-slot="menubar-trigger"
|
|
179
|
+
class={cn(
|
|
180
|
+
"flex items-center rounded-sm px-2 py-1 text-sm font-medium outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground forced-colors:focus:bg-[Highlight] forced-colors:focus:text-[HighlightText] forced-colors:data-[state=open]:bg-[Highlight] forced-colors:data-[state=open]:text-[HighlightText]",
|
|
181
|
+
local.class,
|
|
182
|
+
)}
|
|
183
|
+
{...rest}
|
|
184
|
+
/>
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* The menu panel, rendered into `document.body` and placed under its trigger. It is open while its
|
|
190
|
+
* menu is open.
|
|
191
|
+
*
|
|
192
|
+
* Keyboard and ARIA: `role="menu"` with `aria-orientation="vertical"`, named by its trigger
|
|
193
|
+
* (`aria-labelledby`). ArrowDown and ArrowUp move between the items; ArrowLeft and ArrowRight move to
|
|
194
|
+
* the neighboring menu (swapped in right-to-left layouts); Escape and Tab close it, and focus returns
|
|
195
|
+
* to the trigger. Pressing another trigger of the bar does not close it.
|
|
196
|
+
*
|
|
197
|
+
* @param props The panel's attributes. The placement defaults are `align="start"`, `alignOffset={-4}`
|
|
198
|
+
* and `sideOffset={8}`; `class` adds to the panel's classes.
|
|
199
|
+
* @returns The panel element, or nothing while the menu is closed.
|
|
200
|
+
* @throws Error when rendered outside a {@link Menubar}.
|
|
201
|
+
* @example
|
|
202
|
+
* import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarTrigger } from "@/components/ui/menubar";
|
|
203
|
+
*
|
|
204
|
+
* <Menubar>
|
|
205
|
+
* <MenubarMenu value="file">
|
|
206
|
+
* <MenubarTrigger>File</MenubarTrigger>
|
|
207
|
+
* <MenubarContent class="w-64">
|
|
208
|
+
* <MenubarItem>New window</MenubarItem>
|
|
209
|
+
* </MenubarContent>
|
|
210
|
+
* </MenubarMenu>
|
|
211
|
+
* </Menubar>
|
|
212
|
+
* @since 1.0.0
|
|
213
|
+
* @see {@link MenubarTrigger}
|
|
214
|
+
*/
|
|
215
|
+
function MenubarContent(props: MenubarContentProps): JSX.Element {
|
|
216
|
+
const [local, rest] = splitProps(props, ["class", "align", "alignOffset", "sideOffset"]);
|
|
217
|
+
return (
|
|
218
|
+
<MenubarPortal>
|
|
219
|
+
<MenubarPrimitive.Content
|
|
220
|
+
data-slot="menubar-content"
|
|
221
|
+
align={local.align ?? "start"}
|
|
222
|
+
alignOffset={local.alignOffset ?? -4}
|
|
223
|
+
sideOffset={local.sideOffset ?? 8}
|
|
224
|
+
class={cn(
|
|
225
|
+
PANEL,
|
|
226
|
+
"min-w-[12rem] max-h-(--primitives-available-height) overflow-x-hidden overflow-y-auto shadow-md",
|
|
227
|
+
local.class,
|
|
228
|
+
)}
|
|
229
|
+
{...rest}
|
|
230
|
+
/>
|
|
231
|
+
</MenubarPortal>
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Groups related items. It has no keys and no ARIA attributes of its own; the items keep theirs.
|
|
237
|
+
*
|
|
238
|
+
* @param props The group's attributes.
|
|
239
|
+
* @returns The group element.
|
|
240
|
+
* @throws Error when rendered outside a menu of a {@link Menubar}.
|
|
241
|
+
* @example
|
|
242
|
+
* import { Menubar, MenubarContent, MenubarGroup, MenubarItem, MenubarMenu, MenubarTrigger } from "@/components/ui/menubar";
|
|
243
|
+
*
|
|
244
|
+
* <Menubar>
|
|
245
|
+
* <MenubarMenu value="account">
|
|
246
|
+
* <MenubarTrigger>Account</MenubarTrigger>
|
|
247
|
+
* <MenubarContent>
|
|
248
|
+
* <MenubarGroup>
|
|
249
|
+
* <MenubarItem>Profile</MenubarItem>
|
|
250
|
+
* </MenubarGroup>
|
|
251
|
+
* </MenubarContent>
|
|
252
|
+
* </MenubarMenu>
|
|
253
|
+
* </Menubar>
|
|
254
|
+
* @since 1.0.0
|
|
255
|
+
* @see {@link MenubarContent}
|
|
256
|
+
*/
|
|
257
|
+
function MenubarGroup(props: MenuGroupProps): JSX.Element {
|
|
258
|
+
return <MenubarPrimitive.Group data-slot="menubar-group" {...props} />;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* The extra props of {@link MenubarItem}: `inset` and `variant`.
|
|
263
|
+
* @since 1.0.0
|
|
264
|
+
* @see {@link MenubarItem}
|
|
265
|
+
*/
|
|
266
|
+
export interface MenubarItemExtraProps {
|
|
267
|
+
/**
|
|
268
|
+
* Indents the item so it lines up with items that have an indicator.
|
|
269
|
+
* @default false
|
|
270
|
+
*/
|
|
271
|
+
readonly inset?: boolean | undefined;
|
|
272
|
+
/**
|
|
273
|
+
* `destructive` colors the item for dangerous actions.
|
|
274
|
+
* @default "default"
|
|
275
|
+
*/
|
|
276
|
+
readonly variant?: "default" | "destructive" | undefined;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Props of {@link MenubarItem}: the attributes of the chosen element (`div` by default), plus `inset`
|
|
281
|
+
* and `variant`.
|
|
282
|
+
* @since 1.0.0
|
|
283
|
+
* @see {@link MenubarItem}
|
|
284
|
+
*/
|
|
285
|
+
export type MenubarItemProps<T extends PolymorphicTarget = "div"> = PolymorphicProps<
|
|
286
|
+
"div",
|
|
287
|
+
MenuItemOwnProps & MenubarItemExtraProps,
|
|
288
|
+
T
|
|
289
|
+
>;
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* An action in a menu of the bar. Selecting it (by click, Enter or Space) closes the menu, unless
|
|
293
|
+
* `onSelect` calls `event.preventDefault()`.
|
|
294
|
+
*
|
|
295
|
+
* Keyboard and ARIA: `role="menuitem"` with `tabindex="-1"`; the arrow keys move between the items.
|
|
296
|
+
* A disabled item gets `aria-disabled="true"` and is skipped. Its name is its text.
|
|
297
|
+
*
|
|
298
|
+
* shadcn/ui differences: `as` replaces `asChild`, as in `<MenubarItem as="a" href="/settings">`.
|
|
299
|
+
*
|
|
300
|
+
* @param props The item's attributes, plus `inset`, `variant` and `as`. `class` adds to the classes.
|
|
301
|
+
* @returns The item element.
|
|
302
|
+
* @throws Error when rendered outside a menu of a {@link Menubar}.
|
|
303
|
+
* @example
|
|
304
|
+
* import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarTrigger } from "@/components/ui/menubar";
|
|
305
|
+
*
|
|
306
|
+
* const remove = (): void => console.info("remove");
|
|
307
|
+
*
|
|
308
|
+
* <Menubar>
|
|
309
|
+
* <MenubarMenu value="edit">
|
|
310
|
+
* <MenubarTrigger>Edit</MenubarTrigger>
|
|
311
|
+
* <MenubarContent>
|
|
312
|
+
* <MenubarItem variant="destructive" onSelect={remove}>Delete</MenubarItem>
|
|
313
|
+
* </MenubarContent>
|
|
314
|
+
* </MenubarMenu>
|
|
315
|
+
* </Menubar>
|
|
316
|
+
* @since 1.0.0
|
|
317
|
+
* @see {@link MenubarContent}
|
|
318
|
+
*/
|
|
319
|
+
function MenubarItem<T extends PolymorphicTarget = "div">(props: MenubarItemProps<T>): JSX.Element {
|
|
320
|
+
const [local, rest] = splitProps(props as unknown as Loose, ["class", "inset", "variant"]);
|
|
321
|
+
return (
|
|
322
|
+
<MenubarPrimitive.Item
|
|
323
|
+
data-slot="menubar-item"
|
|
324
|
+
data-inset={local.inset === true ? "" : undefined}
|
|
325
|
+
data-variant={local.variant ?? "default"}
|
|
326
|
+
class={cn(
|
|
327
|
+
ROW,
|
|
328
|
+
"px-2 py-1.5 data-[inset]:ps-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:*:[svg]:text-destructive! [&_svg:not([class*='text-'])]:text-muted-foreground",
|
|
329
|
+
local.class,
|
|
330
|
+
)}
|
|
331
|
+
{...rest}
|
|
332
|
+
/>
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* An item that toggles a boolean, with a check mark while it is checked.
|
|
338
|
+
*
|
|
339
|
+
* Keyboard and ARIA: `role="menuitemcheckbox"` with `aria-checked` (`"mixed"` while indeterminate).
|
|
340
|
+
* Enter, Space and a click toggle it, and the state changes even when `onSelect` keeps the menu open.
|
|
341
|
+
* Its name is its text.
|
|
342
|
+
*
|
|
343
|
+
* @param props The item's props: `checked`, `defaultChecked`, `onCheckedChange`, and the label as
|
|
344
|
+
* `children`. `class` adds to the classes.
|
|
345
|
+
* @returns The checkbox item element.
|
|
346
|
+
* @throws Error when rendered outside a menu of a {@link Menubar}.
|
|
347
|
+
* @example
|
|
348
|
+
* import { useSignal } from "@shadow-js/core";
|
|
349
|
+
* import { Menubar, MenubarCheckboxItem, MenubarContent, MenubarMenu, MenubarTrigger } from "@/components/ui/menubar";
|
|
350
|
+
*
|
|
351
|
+
* export function ViewMenu() {
|
|
352
|
+
* const [bookmarks, setBookmarks] = useSignal(true);
|
|
353
|
+
* return (
|
|
354
|
+
* <Menubar>
|
|
355
|
+
* <MenubarMenu value="view">
|
|
356
|
+
* <MenubarTrigger>View</MenubarTrigger>
|
|
357
|
+
* <MenubarContent>
|
|
358
|
+
* <MenubarCheckboxItem checked={bookmarks()} onCheckedChange={setBookmarks}>
|
|
359
|
+
* Show bookmarks
|
|
360
|
+
* </MenubarCheckboxItem>
|
|
361
|
+
* </MenubarContent>
|
|
362
|
+
* </MenubarMenu>
|
|
363
|
+
* </Menubar>
|
|
364
|
+
* );
|
|
365
|
+
* }
|
|
366
|
+
* @since 1.0.0
|
|
367
|
+
* @see {@link MenubarItem}
|
|
368
|
+
*/
|
|
369
|
+
function MenubarCheckboxItem(props: MenuCheckboxItemProps): JSX.Element {
|
|
370
|
+
const [local, rest] = splitProps(props, ["class", "children"]);
|
|
371
|
+
return (
|
|
372
|
+
<MenubarPrimitive.CheckboxItem
|
|
373
|
+
data-slot="menubar-checkbox-item"
|
|
374
|
+
class={cn(ROW, "py-1.5 ps-8 pe-2", local.class)}
|
|
375
|
+
{...rest}
|
|
376
|
+
>
|
|
377
|
+
<span class="pointer-events-none absolute start-2 flex size-3.5 items-center justify-center">
|
|
378
|
+
<MenubarPrimitive.ItemIndicator>
|
|
379
|
+
<CheckIcon class="size-4" />
|
|
380
|
+
</MenubarPrimitive.ItemIndicator>
|
|
381
|
+
</span>
|
|
382
|
+
{local.children}
|
|
383
|
+
</MenubarPrimitive.CheckboxItem>
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* A group of mutually exclusive {@link MenubarRadioItem}s. It handles no keys of its own; the items
|
|
389
|
+
* do.
|
|
390
|
+
*
|
|
391
|
+
* Keyboard and ARIA: a `role="group"`, with no name of its own; pass `aria-label` when the group needs one.
|
|
392
|
+
*
|
|
393
|
+
* @param props The group's props: `value`, `defaultValue`, `onValueChange`, and the `div` attributes.
|
|
394
|
+
* @returns The group element.
|
|
395
|
+
* @example
|
|
396
|
+
* import { Menubar, MenubarContent, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarTrigger } from "@/components/ui/menubar";
|
|
397
|
+
*
|
|
398
|
+
* <Menubar>
|
|
399
|
+
* <MenubarMenu value="view">
|
|
400
|
+
* <MenubarTrigger>View</MenubarTrigger>
|
|
401
|
+
* <MenubarContent>
|
|
402
|
+
* <MenubarRadioGroup defaultValue="list">
|
|
403
|
+
* <MenubarRadioItem value="list">List</MenubarRadioItem>
|
|
404
|
+
* <MenubarRadioItem value="grid">Grid</MenubarRadioItem>
|
|
405
|
+
* </MenubarRadioGroup>
|
|
406
|
+
* </MenubarContent>
|
|
407
|
+
* </MenubarMenu>
|
|
408
|
+
* </Menubar>
|
|
409
|
+
* @since 1.0.0
|
|
410
|
+
* @see {@link MenubarRadioItem}
|
|
411
|
+
*/
|
|
412
|
+
function MenubarRadioGroup(props: MenuRadioGroupProps): JSX.Element {
|
|
413
|
+
return <MenubarPrimitive.RadioGroup data-slot="menubar-radio-group" {...props} />;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* An item of a {@link MenubarRadioGroup}, with a dot while it is the selected one.
|
|
418
|
+
*
|
|
419
|
+
* Keyboard and ARIA: `role="menuitemradio"` with `aria-checked`. Enter, Space and a click select it.
|
|
420
|
+
* Its name is its text.
|
|
421
|
+
*
|
|
422
|
+
* @param props The item's props: `value` (required), and the label as `children`. `class` adds to the
|
|
423
|
+
* classes.
|
|
424
|
+
* @returns The radio item element.
|
|
425
|
+
* @throws Error when rendered outside a menu of a {@link Menubar}.
|
|
426
|
+
* @example
|
|
427
|
+
* import { Menubar, MenubarContent, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarTrigger } from "@/components/ui/menubar";
|
|
428
|
+
*
|
|
429
|
+
* <Menubar>
|
|
430
|
+
* <MenubarMenu value="view">
|
|
431
|
+
* <MenubarTrigger>View</MenubarTrigger>
|
|
432
|
+
* <MenubarContent>
|
|
433
|
+
* <MenubarRadioGroup defaultValue="list">
|
|
434
|
+
* <MenubarRadioItem value="list">List</MenubarRadioItem>
|
|
435
|
+
* </MenubarRadioGroup>
|
|
436
|
+
* </MenubarContent>
|
|
437
|
+
* </MenubarMenu>
|
|
438
|
+
* </Menubar>
|
|
439
|
+
* @since 1.0.0
|
|
440
|
+
* @see {@link MenubarRadioGroup}
|
|
441
|
+
*/
|
|
442
|
+
function MenubarRadioItem(props: MenuRadioItemProps): JSX.Element {
|
|
443
|
+
const [local, rest] = splitProps(props, ["class", "children"]);
|
|
444
|
+
return (
|
|
445
|
+
<MenubarPrimitive.RadioItem
|
|
446
|
+
data-slot="menubar-radio-item"
|
|
447
|
+
class={cn(ROW, "py-1.5 ps-8 pe-2", local.class)}
|
|
448
|
+
{...rest}
|
|
449
|
+
>
|
|
450
|
+
<span class="pointer-events-none absolute start-2 flex size-3.5 items-center justify-center">
|
|
451
|
+
<MenubarPrimitive.ItemIndicator>
|
|
452
|
+
<CircleIcon class="size-2 fill-current" />
|
|
453
|
+
</MenubarPrimitive.ItemIndicator>
|
|
454
|
+
</span>
|
|
455
|
+
{local.children}
|
|
456
|
+
</MenubarPrimitive.RadioItem>
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Props of {@link MenubarLabel}: the primitive's label props plus `inset`.
|
|
462
|
+
* @since 1.0.0
|
|
463
|
+
* @see {@link MenubarLabel}
|
|
464
|
+
*/
|
|
465
|
+
export type MenubarLabelProps = MenuLabelProps & {
|
|
466
|
+
/**
|
|
467
|
+
* Indents the label so it lines up with items that have an indicator.
|
|
468
|
+
* @default false
|
|
469
|
+
*/
|
|
470
|
+
readonly inset?: boolean | undefined;
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* A heading for a group of items. It has no role, it is not focusable, and the arrow keys skip it.
|
|
475
|
+
*
|
|
476
|
+
* @param props The label's attributes, plus `inset`. `class` adds to the classes.
|
|
477
|
+
* @returns The label element.
|
|
478
|
+
* @throws Error when rendered outside a menu of a {@link Menubar}.
|
|
479
|
+
* @example
|
|
480
|
+
* import { Menubar, MenubarContent, MenubarLabel, MenubarMenu, MenubarTrigger } from "@/components/ui/menubar";
|
|
481
|
+
*
|
|
482
|
+
* <Menubar>
|
|
483
|
+
* <MenubarMenu value="account">
|
|
484
|
+
* <MenubarTrigger>Account</MenubarTrigger>
|
|
485
|
+
* <MenubarContent>
|
|
486
|
+
* <MenubarLabel>My Account</MenubarLabel>
|
|
487
|
+
* </MenubarContent>
|
|
488
|
+
* </MenubarMenu>
|
|
489
|
+
* </Menubar>
|
|
490
|
+
* @since 1.0.0
|
|
491
|
+
* @see {@link MenubarGroup}
|
|
492
|
+
*/
|
|
493
|
+
function MenubarLabel(props: MenubarLabelProps): JSX.Element {
|
|
494
|
+
const [local, rest] = splitProps(props, ["class", "inset"]);
|
|
495
|
+
return (
|
|
496
|
+
<MenubarPrimitive.Label
|
|
497
|
+
data-slot="menubar-label"
|
|
498
|
+
data-inset={local.inset === true ? "" : undefined}
|
|
499
|
+
class={cn("px-2 py-1.5 text-sm font-medium data-[inset]:ps-8", local.class)}
|
|
500
|
+
{...rest}
|
|
501
|
+
/>
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* A divider between groups of items.
|
|
507
|
+
*
|
|
508
|
+
* Keyboard and ARIA: a horizontal `role="separator"` with `aria-orientation="horizontal"`. The arrow
|
|
509
|
+
* keys skip it.
|
|
510
|
+
*
|
|
511
|
+
* @param props The separator's attributes. `class` adds to the classes.
|
|
512
|
+
* @returns The separator element.
|
|
513
|
+
* @throws Error when rendered outside a menu of a {@link Menubar}.
|
|
514
|
+
* @example
|
|
515
|
+
* import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarSeparator, MenubarTrigger } from "@/components/ui/menubar";
|
|
516
|
+
*
|
|
517
|
+
* <Menubar>
|
|
518
|
+
* <MenubarMenu value="file">
|
|
519
|
+
* <MenubarTrigger>File</MenubarTrigger>
|
|
520
|
+
* <MenubarContent>
|
|
521
|
+
* <MenubarItem>New window</MenubarItem>
|
|
522
|
+
* <MenubarSeparator />
|
|
523
|
+
* <MenubarItem>Close</MenubarItem>
|
|
524
|
+
* </MenubarContent>
|
|
525
|
+
* </MenubarMenu>
|
|
526
|
+
* </Menubar>
|
|
527
|
+
* @since 1.0.0
|
|
528
|
+
* @see {@link MenubarContent}
|
|
529
|
+
*/
|
|
530
|
+
function MenubarSeparator(props: MenuSeparatorProps): JSX.Element {
|
|
531
|
+
const [local, rest] = splitProps(props, ["class"]);
|
|
532
|
+
return (
|
|
533
|
+
<MenubarPrimitive.Separator
|
|
534
|
+
data-slot="menubar-separator"
|
|
535
|
+
class={cn("-mx-1 my-1 h-px bg-border", local.class)}
|
|
536
|
+
{...rest}
|
|
537
|
+
/>
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* A keyboard shortcut hint at the end of an item. It is text only: it shows the shortcut and does not
|
|
543
|
+
* bind the key, so wire the key yourself.
|
|
544
|
+
*
|
|
545
|
+
* Keyboard and ARIA: a `span` with no role and no keys.
|
|
546
|
+
*
|
|
547
|
+
* @param props The `span` attributes. `class` adds to the classes.
|
|
548
|
+
* @returns The shortcut `span`.
|
|
549
|
+
* @example
|
|
550
|
+
* import { MenubarItem, MenubarShortcut } from "@/components/ui/menubar";
|
|
551
|
+
*
|
|
552
|
+
* <MenubarItem>
|
|
553
|
+
* Save <MenubarShortcut>Ctrl+S</MenubarShortcut>
|
|
554
|
+
* </MenubarItem>
|
|
555
|
+
* @since 1.0.0
|
|
556
|
+
* @see {@link MenubarItem}
|
|
557
|
+
*/
|
|
558
|
+
function MenubarShortcut(props: ComponentProps<"span">): JSX.Element {
|
|
559
|
+
const [local, rest] = splitProps(props, ["class"]);
|
|
560
|
+
return (
|
|
561
|
+
<span
|
|
562
|
+
data-slot="menubar-shortcut"
|
|
563
|
+
class={cn("ms-auto text-xs tracking-widest text-muted-foreground", local.class)}
|
|
564
|
+
{...rest}
|
|
565
|
+
/>
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
/**
|
|
570
|
+
* The root of a submenu. Place a {@link MenubarSubTrigger} and a {@link MenubarSubContent} in it. It
|
|
571
|
+
* renders no element and handles no keys.
|
|
572
|
+
*
|
|
573
|
+
* @param props The submenu's options: `open`, `defaultOpen` and `onOpenChange`.
|
|
574
|
+
* @returns The submenu's context around its children.
|
|
575
|
+
* @throws Error when rendered outside a menu of a {@link Menubar}.
|
|
576
|
+
* @example
|
|
577
|
+
* import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger } from "@/components/ui/menubar";
|
|
578
|
+
*
|
|
579
|
+
* <Menubar>
|
|
580
|
+
* <MenubarMenu value="file">
|
|
581
|
+
* <MenubarTrigger>File</MenubarTrigger>
|
|
582
|
+
* <MenubarContent>
|
|
583
|
+
* <MenubarSub>
|
|
584
|
+
* <MenubarSubTrigger>Share</MenubarSubTrigger>
|
|
585
|
+
* <MenubarSubContent>
|
|
586
|
+
* <MenubarItem>Email</MenubarItem>
|
|
587
|
+
* </MenubarSubContent>
|
|
588
|
+
* </MenubarSub>
|
|
589
|
+
* </MenubarContent>
|
|
590
|
+
* </MenubarMenu>
|
|
591
|
+
* </Menubar>
|
|
592
|
+
* @since 1.0.0
|
|
593
|
+
* @see {@link MenubarSubTrigger}
|
|
594
|
+
*/
|
|
595
|
+
function MenubarSub(props: MenuSubProps): JSX.Element {
|
|
596
|
+
return <MenubarPrimitive.Sub {...props} />;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* The item that opens a submenu, with a chevron that flips in right-to-left layouts.
|
|
601
|
+
*
|
|
602
|
+
* Keyboard and ARIA: `role="menuitem"` with `aria-haspopup="menu"`, `aria-expanded`, and
|
|
603
|
+
* `aria-controls` while the submenu is open. ArrowRight (ArrowLeft in right-to-left layouts), Enter
|
|
604
|
+
* and Space open the submenu and focus its first item. Resting the pointer on it for a moment opens it
|
|
605
|
+
* too.
|
|
606
|
+
*
|
|
607
|
+
* @param props The trigger's attributes, plus `inset` and `as`. `class` adds to the classes.
|
|
608
|
+
* @returns The trigger element.
|
|
609
|
+
* @throws Error when rendered outside a menu of a {@link Menubar}.
|
|
610
|
+
* @example
|
|
611
|
+
* import { MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarItem } from "@/components/ui/menubar";
|
|
612
|
+
*
|
|
613
|
+
* <MenubarSub>
|
|
614
|
+
* <MenubarSubTrigger>Invite users</MenubarSubTrigger>
|
|
615
|
+
* <MenubarSubContent>
|
|
616
|
+
* <MenubarItem>Email</MenubarItem>
|
|
617
|
+
* </MenubarSubContent>
|
|
618
|
+
* </MenubarSub>
|
|
619
|
+
* @since 1.0.0
|
|
620
|
+
* @see {@link MenubarSubContent}
|
|
621
|
+
*/
|
|
622
|
+
function MenubarSubTrigger<T extends PolymorphicTarget = "div">(
|
|
623
|
+
props: MenuSubTriggerProps<T> & { readonly inset?: boolean | undefined },
|
|
624
|
+
): JSX.Element {
|
|
625
|
+
const [local, rest] = splitProps(props as unknown as Loose, ["class", "inset", "children"]);
|
|
626
|
+
return (
|
|
627
|
+
<MenubarPrimitive.SubTrigger
|
|
628
|
+
data-slot="menubar-sub-trigger"
|
|
629
|
+
data-inset={local.inset === true ? "" : undefined}
|
|
630
|
+
class={cn(
|
|
631
|
+
ROW,
|
|
632
|
+
"px-2 py-1.5 data-[inset]:ps-8 data-[state=open]:bg-accent data-[state=open]:text-accent-foreground forced-colors:data-[state=open]:bg-[Highlight] forced-colors:data-[state=open]:text-[HighlightText] [&_svg:not([class*='text-'])]:text-muted-foreground",
|
|
633
|
+
local.class,
|
|
634
|
+
)}
|
|
635
|
+
{...rest}
|
|
636
|
+
>
|
|
637
|
+
{local.children}
|
|
638
|
+
<ChevronRightIcon class="ms-auto size-4 rtl:rotate-180" />
|
|
639
|
+
</MenubarPrimitive.SubTrigger>
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* The submenu panel, placed beside its trigger.
|
|
645
|
+
*
|
|
646
|
+
* Keyboard and ARIA: `role="menu"` with `aria-orientation="vertical"`, named by its trigger. ArrowLeft
|
|
647
|
+
* (ArrowRight in right-to-left layouts) and Escape close it and return focus to the trigger. The arrow
|
|
648
|
+
* keys, Home and End move between the items.
|
|
649
|
+
*
|
|
650
|
+
* @param props The panel's attributes. `class` adds to the classes.
|
|
651
|
+
* @returns The submenu element, or nothing while it is closed.
|
|
652
|
+
* @throws Error when rendered outside a menu of a {@link Menubar}.
|
|
653
|
+
* @example
|
|
654
|
+
* import { MenubarItem, MenubarSubContent } from "@/components/ui/menubar";
|
|
655
|
+
*
|
|
656
|
+
* <MenubarSubContent>
|
|
657
|
+
* <MenubarItem>Email</MenubarItem>
|
|
658
|
+
* </MenubarSubContent>
|
|
659
|
+
* @since 1.0.0
|
|
660
|
+
* @see {@link MenubarSubTrigger}
|
|
661
|
+
*/
|
|
662
|
+
function MenubarSubContent(props: MenuSubContentProps): JSX.Element {
|
|
663
|
+
const [local, rest] = splitProps(props, ["class"]);
|
|
664
|
+
return (
|
|
665
|
+
<MenubarPrimitive.SubContent
|
|
666
|
+
data-slot="menubar-sub-content"
|
|
667
|
+
class={cn(
|
|
668
|
+
PANEL,
|
|
669
|
+
"max-h-(--primitives-available-height) overflow-x-hidden overflow-y-auto shadow-lg",
|
|
670
|
+
local.class,
|
|
671
|
+
)}
|
|
672
|
+
{...rest}
|
|
673
|
+
/>
|
|
674
|
+
);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
export {
|
|
678
|
+
Menubar,
|
|
679
|
+
MenubarCheckboxItem,
|
|
680
|
+
MenubarContent,
|
|
681
|
+
MenubarGroup,
|
|
682
|
+
MenubarItem,
|
|
683
|
+
MenubarLabel,
|
|
684
|
+
MenubarMenu,
|
|
685
|
+
MenubarPortal,
|
|
686
|
+
MenubarRadioGroup,
|
|
687
|
+
MenubarRadioItem,
|
|
688
|
+
MenubarSeparator,
|
|
689
|
+
MenubarShortcut,
|
|
690
|
+
MenubarSub,
|
|
691
|
+
MenubarSubContent,
|
|
692
|
+
MenubarSubTrigger,
|
|
693
|
+
MenubarTrigger,
|
|
694
|
+
};
|