Migrate Menu component from useStyles to useDefinition

Split monolithic MenuDefinition (17 classNames) into 9 per-sub-component
definitions (Menu, MenuListBox, MenuAutocomplete, MenuAutocompleteListbox,
MenuItem, MenuListBoxItem, MenuSection, MenuSeparator, MenuEmptyState).
MenuItem color prop uses dataAttribute with default in propDefs. Defaults
for placement, virtualized, selectionMode moved to propDefs.

Signed-off-by: Johan Persson <johanopersson@gmail.com>
This commit is contained in:
Johan Persson
2026-02-27 11:14:10 +01:00
parent 36b1ac8802
commit 403496c5cb
5 changed files with 440 additions and 353 deletions
+100 -81
View File
@@ -1481,57 +1481,59 @@ export const MenuAutocompleteListbox: (
) => JSX_2.Element;
// @public (undocumented)
export interface MenuAutocompleteListBoxProps<T>
extends ListBoxProps<T>,
Omit<ListBoxProps<T>, 'children'> {
// (undocumented)
maxHeight?: string;
// (undocumented)
maxWidth?: string;
// (undocumented)
export type MenuAutocompleteListBoxOwnProps = {
placeholder?: string;
// (undocumented)
placement?: PopoverProps_2['placement'];
// (undocumented)
selectionMode?: ListBoxProps<object>['selectionMode'];
virtualized?: boolean;
}
maxWidth?: string;
maxHeight?: string;
style?: React.CSSProperties;
className?: string;
};
// @public (undocumented)
export interface MenuAutocompleteListBoxProps<T>
extends MenuAutocompleteListBoxOwnProps,
Omit<ListBoxProps<T>, keyof MenuAutocompleteListBoxOwnProps> {}
// @public (undocumented)
export type MenuAutocompleteOwnProps = {
placeholder?: string;
placement?: PopoverProps_2['placement'];
virtualized?: boolean;
maxWidth?: string;
maxHeight?: string;
style?: React.CSSProperties;
className?: string;
};
// @public (undocumented)
export interface MenuAutocompleteProps<T>
extends MenuProps_2<T>,
Omit<MenuProps_2<T>, 'children'> {
// (undocumented)
maxHeight?: string;
// (undocumented)
maxWidth?: string;
// (undocumented)
placeholder?: string;
// (undocumented)
placement?: PopoverProps_2['placement'];
// (undocumented)
virtualized?: boolean;
}
extends MenuAutocompleteOwnProps,
Omit<MenuProps_2<T>, keyof MenuAutocompleteOwnProps> {}
// @public
export const MenuDefinition: {
readonly styles: {
readonly [key: string]: string;
};
readonly classNames: {
readonly root: 'bui-Menu';
readonly popover: 'bui-MenuPopover';
readonly root: 'bui-MenuPopover';
readonly inner: 'bui-MenuInner';
readonly content: 'bui-MenuContent';
readonly section: 'bui-MenuSection';
readonly sectionHeader: 'bui-MenuSectionHeader';
readonly item: 'bui-MenuItem';
readonly itemListBox: 'bui-MenuItemListBox';
readonly itemListBoxCheck: 'bui-MenuItemListBoxCheck';
readonly itemWrapper: 'bui-MenuItemWrapper';
readonly itemContent: 'bui-MenuItemContent';
readonly itemArrow: 'bui-MenuItemArrow';
readonly separator: 'bui-MenuSeparator';
readonly searchField: 'bui-MenuSearchField';
readonly searchFieldInput: 'bui-MenuSearchFieldInput';
readonly searchFieldClear: 'bui-MenuSearchFieldClear';
readonly emptyState: 'bui-MenuEmptyState';
};
readonly propDefs: {
readonly placement: {
readonly default: 'bottom start';
};
readonly virtualized: {
readonly default: false;
};
readonly maxWidth: {};
readonly maxHeight: {};
readonly style: {};
readonly className: {};
};
};
@@ -1539,16 +1541,18 @@ export const MenuDefinition: {
export const MenuItem: (props: MenuItemProps) => JSX_2.Element;
// @public (undocumented)
export interface MenuItemProps
extends MenuItemProps_2,
Omit<MenuItemProps_2, 'children'> {
// (undocumented)
children: React.ReactNode;
// (undocumented)
color?: 'primary' | 'danger';
// (undocumented)
export type MenuItemOwnProps = {
iconStart?: React.ReactNode;
}
children: React.ReactNode;
color?: 'primary' | 'danger';
href?: MenuItemProps_2['href'];
className?: string;
};
// @public (undocumented)
export interface MenuItemProps
extends MenuItemOwnProps,
Omit<MenuItemProps_2, keyof MenuItemOwnProps> {}
// @public (undocumented)
export const MenuListBox: (props: MenuListBoxProps<object>) => JSX_2.Element;
@@ -1557,59 +1561,74 @@ export const MenuListBox: (props: MenuListBoxProps<object>) => JSX_2.Element;
export const MenuListBoxItem: (props: MenuListBoxItemProps) => JSX_2.Element;
// @public (undocumented)
export interface MenuListBoxItemProps
extends ListBoxItemProps,
Omit<ListBoxItemProps, 'children'> {
// (undocumented)
export type MenuListBoxItemOwnProps = {
children: React.ReactNode;
}
className?: string;
};
// @public (undocumented)
export interface MenuListBoxItemProps
extends MenuListBoxItemOwnProps,
Omit<ListBoxItemProps, keyof MenuListBoxItemOwnProps> {}
// @public (undocumented)
export type MenuListBoxOwnProps = {
placement?: PopoverProps_2['placement'];
selectionMode?: ListBoxProps<object>['selectionMode'];
virtualized?: boolean;
maxWidth?: string;
maxHeight?: string;
style?: React.CSSProperties;
className?: string;
};
// @public (undocumented)
export interface MenuListBoxProps<T>
extends ListBoxProps<T>,
Omit<ListBoxProps<T>, 'children'> {
// (undocumented)
maxHeight?: string;
// (undocumented)
maxWidth?: string;
// (undocumented)
extends MenuListBoxOwnProps,
Omit<ListBoxProps<T>, keyof MenuListBoxOwnProps> {}
// @public (undocumented)
export type MenuOwnProps = {
placement?: PopoverProps_2['placement'];
// (undocumented)
virtualized?: boolean;
}
maxWidth?: string;
maxHeight?: string;
style?: React.CSSProperties;
className?: string;
};
// @public (undocumented)
export interface MenuProps<T>
extends MenuProps_2<T>,
Omit<MenuProps_2<T>, 'children'> {
// (undocumented)
maxHeight?: string;
// (undocumented)
maxWidth?: string;
// (undocumented)
placement?: PopoverProps_2['placement'];
// (undocumented)
virtualized?: boolean;
}
extends MenuOwnProps,
Omit<MenuProps_2<T>, keyof MenuOwnProps> {}
// @public (undocumented)
export const MenuSection: (props: MenuSectionProps<object>) => JSX_2.Element;
// @public (undocumented)
export interface MenuSectionProps<T>
extends MenuSectionProps_2<T>,
Omit<MenuSectionProps_2<T>, 'children'> {
// (undocumented)
children: React.ReactNode;
// (undocumented)
export type MenuSectionOwnProps = {
title: string;
}
children: React.ReactNode;
className?: string;
};
// @public (undocumented)
export interface MenuSectionProps<T>
extends MenuSectionOwnProps,
Omit<MenuSectionProps_2<T>, keyof MenuSectionOwnProps> {}
// @public (undocumented)
export const MenuSeparator: (props: MenuSeparatorProps) => JSX_2.Element;
// @public (undocumented)
export interface MenuSeparatorProps extends SeparatorProps {}
export type MenuSeparatorOwnProps = {
className?: string;
};
// @public (undocumented)
export interface MenuSeparatorProps
extends MenuSeparatorOwnProps,
Omit<SeparatorProps, keyof MenuSeparatorOwnProps> {}
// @public (undocumented)
export const MenuTrigger: (props: MenuTriggerProps) => JSX_2.Element;
+102 -226
View File
@@ -33,8 +33,18 @@ import {
Virtualizer,
ListLayout,
} from 'react-aria-components';
import { useStyles } from '../../hooks/useStyles';
import { MenuDefinition } from './definition';
import { useDefinition } from '../../hooks/useDefinition';
import {
MenuDefinition,
MenuListBoxDefinition,
MenuAutocompleteDefinition,
MenuAutocompleteListboxDefinition,
MenuItemDefinition,
MenuListBoxItemDefinition,
MenuSectionDefinition,
MenuSeparatorDefinition,
MenuEmptyStateDefinition,
} from './definition';
import type {
MenuTriggerProps,
SubmenuTriggerProps,
@@ -56,8 +66,6 @@ import {
isInternalLink,
createRoutingRegistration,
} from '../InternalLinkProvider';
import styles from './Menu.module.css';
import clsx from 'clsx';
import { Box } from '../Box';
import { BgReset } from '../../hooks/useBg';
@@ -68,13 +76,9 @@ const { RoutingProvider, useRoutingRegistrationEffect } =
const rowHeight = 32;
const MenuEmptyState = () => {
const { classNames } = useStyles(MenuDefinition);
const { ownProps } = useDefinition(MenuEmptyStateDefinition, {});
return (
<div className={clsx(classNames.emptyState, styles[classNames.emptyState])}>
No results found.
</div>
);
return <div className={ownProps.classes.root}>No results found.</div>;
};
/** @public */
@@ -89,43 +93,26 @@ export const SubmenuTrigger = (props: SubmenuTriggerProps) => {
/** @public */
export const Menu = (props: MenuProps<object>) => {
const { classNames, cleanedProps } = useStyles(MenuDefinition, props);
const {
className,
placement = 'bottom start',
virtualized = false,
maxWidth,
maxHeight,
style,
...rest
} = cleanedProps;
const { ownProps, restProps } = useDefinition(MenuDefinition, props);
const { classes, placement, virtualized, maxWidth, maxHeight, style } =
ownProps;
let newMaxWidth = maxWidth || (virtualized ? '260px' : 'undefined');
const menuContent = (
<RAMenu
className={clsx(classNames.content, styles[classNames.content])}
className={classes.content}
renderEmptyState={() => <MenuEmptyState />}
style={{ width: newMaxWidth, maxHeight, ...style }}
{...rest}
{...restProps}
/>
);
return (
<RoutingProvider>
<RAPopover
className={clsx(
classNames.popover,
styles[classNames.popover],
className,
)}
placement={placement}
>
<RAPopover className={classes.root} placement={placement}>
<BgReset>
<Box
bg="neutral"
className={clsx(classNames.inner, styles[classNames.inner])}
>
<Box bg="neutral" className={classes.inner}>
{virtualized ? (
<Virtualizer
layout={ListLayout}
@@ -147,42 +134,31 @@ export const Menu = (props: MenuProps<object>) => {
/** @public */
export const MenuListBox = (props: MenuListBoxProps<object>) => {
const { classNames, cleanedProps } = useStyles(MenuDefinition, props);
const { ownProps, restProps } = useDefinition(MenuListBoxDefinition, props);
const {
className,
selectionMode = 'single',
placement = 'bottom start',
virtualized = false,
classes,
selectionMode,
placement,
virtualized,
maxWidth,
maxHeight,
style,
...rest
} = cleanedProps;
} = ownProps;
let newMaxWidth = maxWidth || (virtualized ? '260px' : 'undefined');
const listBoxContent = (
<RAListBox
className={clsx(classNames.content, styles[classNames.content])}
className={classes.content}
selectionMode={selectionMode}
style={{ width: newMaxWidth, maxHeight, ...style }}
{...rest}
{...restProps}
/>
);
return (
<RAPopover
className={clsx(
classNames.popover,
styles[classNames.popover],
className,
)}
placement={placement}
>
<RAPopover className={classes.root} placement={placement}>
<BgReset>
<Box
bg="neutral"
className={clsx(classNames.inner, styles[classNames.inner])}
>
<Box bg="neutral" className={classes.inner}>
{virtualized ? (
<Virtualizer
layout={ListLayout}
@@ -203,64 +179,46 @@ export const MenuListBox = (props: MenuListBoxProps<object>) => {
/** @public */
export const MenuAutocomplete = (props: MenuAutocompleteProps<object>) => {
const { classNames, cleanedProps } = useStyles(MenuDefinition, props);
const { ownProps, restProps } = useDefinition(
MenuAutocompleteDefinition,
props,
);
const {
className,
placement = 'bottom start',
virtualized = false,
classes,
placement,
virtualized,
maxWidth,
maxHeight,
style,
...rest
} = cleanedProps;
placeholder,
} = ownProps;
const { contains } = useFilter({ sensitivity: 'base' });
let newMaxWidth = maxWidth || (virtualized ? '260px' : 'undefined');
const menuContent = (
<RAMenu
className={clsx(classNames.content, styles[classNames.content])}
className={classes.content}
renderEmptyState={() => <MenuEmptyState />}
style={{ width: newMaxWidth, maxHeight, ...style }}
{...rest}
{...restProps}
/>
);
return (
<RoutingProvider>
<RAPopover
className={clsx(
classNames.popover,
styles[classNames.popover],
className,
)}
placement={placement}
>
<RAPopover className={classes.root} placement={placement}>
<BgReset>
<Box
bg="neutral"
className={clsx(classNames.inner, styles[classNames.inner])}
>
<Box bg="neutral" className={classes.inner}>
<RAAutocomplete filter={contains}>
<RASearchField
className={clsx(
classNames.searchField,
styles[classNames.searchField],
)}
aria-label={props.placeholder || 'Search'}
className={classes.searchField}
aria-label={placeholder || 'Search'}
>
<RAInput
className={clsx(
classNames.searchFieldInput,
styles[classNames.searchFieldInput],
)}
placeholder={props.placeholder || 'Search...'}
className={classes.searchFieldInput}
placeholder={placeholder || 'Search...'}
/>
<RAButton
className={clsx(
classNames.searchFieldClear,
styles[classNames.searchFieldClear],
)}
>
<RAButton className={classes.searchFieldClear}>
<RiCloseCircleLine />
</RAButton>
</RASearchField>
@@ -288,65 +246,47 @@ export const MenuAutocomplete = (props: MenuAutocompleteProps<object>) => {
export const MenuAutocompleteListbox = (
props: MenuAutocompleteListBoxProps<object>,
) => {
const { classNames, cleanedProps } = useStyles(MenuDefinition, props);
const { ownProps, restProps } = useDefinition(
MenuAutocompleteListboxDefinition,
props,
);
const {
className,
selectionMode = 'single',
placement = 'bottom start',
virtualized = false,
classes,
selectionMode,
placement,
virtualized,
maxWidth,
maxHeight,
style,
...rest
} = cleanedProps;
placeholder,
} = ownProps;
const { contains } = useFilter({ sensitivity: 'base' });
let newMaxWidth = maxWidth || (virtualized ? '260px' : 'undefined');
const listBoxContent = (
<RAListBox
className={clsx(classNames.content, styles[classNames.content])}
className={classes.content}
renderEmptyState={() => <MenuEmptyState />}
selectionMode={selectionMode}
style={{ width: newMaxWidth, maxHeight, ...style }}
{...rest}
{...restProps}
/>
);
return (
<RAPopover
className={clsx(
classNames.popover,
styles[classNames.popover],
className,
)}
placement={placement}
>
<RAPopover className={classes.root} placement={placement}>
<BgReset>
<Box
bg="neutral"
className={clsx(classNames.inner, styles[classNames.inner])}
>
<Box bg="neutral" className={classes.inner}>
<RAAutocomplete filter={contains}>
<RASearchField
className={clsx(
classNames.searchField,
styles[classNames.searchField],
)}
aria-label={props.placeholder || 'Search'}
className={classes.searchField}
aria-label={placeholder || 'Search'}
>
<RAInput
className={clsx(
classNames.searchFieldInput,
styles[classNames.searchFieldInput],
)}
placeholder={props.placeholder || 'Search...'}
className={classes.searchFieldInput}
placeholder={placeholder || 'Search...'}
/>
<RAButton
className={clsx(
classNames.searchFieldClear,
styles[classNames.searchFieldClear],
)}
>
<RAButton className={classes.searchFieldClear}>
<RiCloseCircleLine />
</RAButton>
</RASearchField>
@@ -371,15 +311,11 @@ export const MenuAutocompleteListbox = (
/** @public */
export const MenuItem = (props: MenuItemProps) => {
const { classNames, cleanedProps } = useStyles(MenuDefinition, props);
const {
className,
iconStart,
color = 'primary',
children,
href,
...rest
} = cleanedProps;
const { ownProps, restProps, dataAttributes } = useDefinition(
MenuItemDefinition,
props,
);
const { classes, iconStart, children, href } = ownProps;
useRoutingRegistrationEffect(href);
@@ -387,30 +323,18 @@ export const MenuItem = (props: MenuItemProps) => {
if (href && !isInternalLink(href)) {
return (
<RAMenuItem
className={clsx(classNames.item, styles[classNames.item], className)}
data-color={color}
className={classes.root}
{...dataAttributes}
textValue={typeof children === 'string' ? children : undefined}
onAction={() => window.open(href, '_blank', 'noopener,noreferrer')}
{...rest}
{...restProps}
>
<div
className={clsx(
classNames.itemWrapper,
styles[classNames.itemWrapper],
)}
>
<div
className={clsx(
classNames.itemContent,
styles[classNames.itemContent],
)}
>
<div className={classes.itemWrapper}>
<div className={classes.itemContent}>
{iconStart}
{children}
</div>
<div
className={clsx(classNames.itemArrow, styles[classNames.itemArrow])}
>
<div className={classes.itemArrow}>
<RiArrowRightSLine />
</div>
</div>
@@ -420,27 +344,18 @@ export const MenuItem = (props: MenuItemProps) => {
return (
<RAMenuItem
className={clsx(classNames.item, styles[classNames.item], className)}
data-color={color}
className={classes.root}
{...dataAttributes}
href={href}
textValue={typeof children === 'string' ? children : undefined}
{...rest}
{...restProps}
>
<div
className={clsx(classNames.itemWrapper, styles[classNames.itemWrapper])}
>
<div
className={clsx(
classNames.itemContent,
styles[classNames.itemContent],
)}
>
<div className={classes.itemWrapper}>
<div className={classes.itemContent}>
{iconStart}
{children}
</div>
<div
className={clsx(classNames.itemArrow, styles[classNames.itemArrow])}
>
<div className={classes.itemArrow}>
<RiArrowRightSLine />
</div>
</div>
@@ -450,36 +365,21 @@ export const MenuItem = (props: MenuItemProps) => {
/** @public */
export const MenuListBoxItem = (props: MenuListBoxItemProps) => {
const { classNames, cleanedProps } = useStyles(MenuDefinition, props);
const { children, className, ...rest } = cleanedProps;
const { ownProps, restProps } = useDefinition(
MenuListBoxItemDefinition,
props,
);
const { classes, children } = ownProps;
return (
<RAListBoxItem
textValue={
typeof props.children === 'string' ? props.children : undefined
}
className={clsx(
classNames.itemListBox,
styles[classNames.itemListBox],
className,
)}
{...rest}
textValue={typeof children === 'string' ? children : undefined}
className={classes.root}
{...restProps}
>
<div
className={clsx(classNames.itemWrapper, styles[classNames.itemWrapper])}
>
<div
className={clsx(
classNames.itemContent,
styles[classNames.itemContent],
)}
>
<div
className={clsx(
classNames.itemListBoxCheck,
styles[classNames.itemListBoxCheck],
)}
>
<div className={classes.itemWrapper}>
<div className={classes.itemContent}>
<div className={classes.check}>
<RiCheckLine />
</div>
{children}
@@ -491,26 +391,12 @@ export const MenuListBoxItem = (props: MenuListBoxItemProps) => {
/** @public */
export const MenuSection = (props: MenuSectionProps<object>) => {
const { classNames, cleanedProps } = useStyles(MenuDefinition, props);
const { children, className, title, ...rest } = cleanedProps;
const { ownProps, restProps } = useDefinition(MenuSectionDefinition, props);
const { classes, children, title } = ownProps;
return (
<RAMenuSection
className={clsx(
classNames.section,
styles[classNames.section],
className,
)}
{...rest}
>
<RAMenuHeader
className={clsx(
classNames.sectionHeader,
styles[classNames.sectionHeader],
)}
>
{title}
</RAMenuHeader>
<RAMenuSection className={classes.root} {...restProps}>
<RAMenuHeader className={classes.header}>{title}</RAMenuHeader>
{children}
</RAMenuSection>
);
@@ -518,17 +404,7 @@ export const MenuSection = (props: MenuSectionProps<object>) => {
/** @public */
export const MenuSeparator = (props: MenuSeparatorProps) => {
const { classNames, cleanedProps } = useStyles(MenuDefinition, props);
const { className, ...rest } = cleanedProps;
const { ownProps, restProps } = useDefinition(MenuSeparatorDefinition, props);
return (
<RAMenuSeparator
className={clsx(
classNames.separator,
styles[classNames.separator],
className,
)}
{...rest}
/>
);
return <RAMenuSeparator className={ownProps.classes.root} {...restProps} />;
};
+157 -15
View File
@@ -14,30 +14,172 @@
* limitations under the License.
*/
import type { ComponentDefinition } from '../../types';
import { defineComponent } from '../../hooks/useDefinition';
import type {
MenuOwnProps,
MenuListBoxOwnProps,
MenuAutocompleteOwnProps,
MenuAutocompleteListBoxOwnProps,
MenuItemOwnProps,
MenuListBoxItemOwnProps,
MenuSectionOwnProps,
MenuSeparatorOwnProps,
} from './types';
import styles from './Menu.module.css';
/**
* Component definition for Menu
* @public
*/
export const MenuDefinition = {
export const MenuDefinition = defineComponent<MenuOwnProps>()({
styles,
classNames: {
root: 'bui-Menu',
popover: 'bui-MenuPopover',
root: 'bui-MenuPopover',
inner: 'bui-MenuInner',
content: 'bui-MenuContent',
section: 'bui-MenuSection',
sectionHeader: 'bui-MenuSectionHeader',
item: 'bui-MenuItem',
itemListBox: 'bui-MenuItemListBox',
itemListBoxCheck: 'bui-MenuItemListBoxCheck',
},
propDefs: {
placement: { default: 'bottom start' },
virtualized: { default: false },
maxWidth: {},
maxHeight: {},
style: {},
className: {},
},
});
/** @internal */
export const MenuListBoxDefinition = defineComponent<MenuListBoxOwnProps>()({
styles,
classNames: {
root: 'bui-MenuPopover',
inner: 'bui-MenuInner',
content: 'bui-MenuContent',
},
propDefs: {
placement: { default: 'bottom start' },
selectionMode: { default: 'single' },
virtualized: { default: false },
maxWidth: {},
maxHeight: {},
style: {},
className: {},
},
});
/** @internal */
export const MenuAutocompleteDefinition =
defineComponent<MenuAutocompleteOwnProps>()({
styles,
classNames: {
root: 'bui-MenuPopover',
inner: 'bui-MenuInner',
content: 'bui-MenuContent',
searchField: 'bui-MenuSearchField',
searchFieldInput: 'bui-MenuSearchFieldInput',
searchFieldClear: 'bui-MenuSearchFieldClear',
},
propDefs: {
placeholder: {},
placement: { default: 'bottom start' },
virtualized: { default: false },
maxWidth: {},
maxHeight: {},
style: {},
className: {},
},
});
/** @internal */
export const MenuAutocompleteListboxDefinition =
defineComponent<MenuAutocompleteListBoxOwnProps>()({
styles,
classNames: {
root: 'bui-MenuPopover',
inner: 'bui-MenuInner',
content: 'bui-MenuContent',
searchField: 'bui-MenuSearchField',
searchFieldInput: 'bui-MenuSearchFieldInput',
searchFieldClear: 'bui-MenuSearchFieldClear',
},
propDefs: {
placeholder: {},
placement: { default: 'bottom start' },
selectionMode: { default: 'single' },
virtualized: { default: false },
maxWidth: {},
maxHeight: {},
style: {},
className: {},
},
});
/** @internal */
export const MenuItemDefinition = defineComponent<MenuItemOwnProps>()({
styles,
classNames: {
root: 'bui-MenuItem',
itemWrapper: 'bui-MenuItemWrapper',
itemContent: 'bui-MenuItemContent',
itemArrow: 'bui-MenuItemArrow',
separator: 'bui-MenuSeparator',
searchField: 'bui-MenuSearchField',
searchFieldInput: 'bui-MenuSearchFieldInput',
searchFieldClear: 'bui-MenuSearchFieldClear',
emptyState: 'bui-MenuEmptyState',
},
} as const satisfies ComponentDefinition;
propDefs: {
iconStart: {},
children: {},
color: { dataAttribute: true, default: 'primary' },
href: {},
className: {},
},
});
/** @internal */
export const MenuListBoxItemDefinition =
defineComponent<MenuListBoxItemOwnProps>()({
styles,
classNames: {
root: 'bui-MenuItemListBox',
itemWrapper: 'bui-MenuItemWrapper',
itemContent: 'bui-MenuItemContent',
check: 'bui-MenuItemListBoxCheck',
},
propDefs: {
children: {},
className: {},
},
});
/** @internal */
export const MenuSectionDefinition = defineComponent<MenuSectionOwnProps>()({
styles,
classNames: {
root: 'bui-MenuSection',
header: 'bui-MenuSectionHeader',
},
propDefs: {
title: {},
children: {},
className: {},
},
});
/** @internal */
export const MenuSeparatorDefinition = defineComponent<MenuSeparatorOwnProps>()(
{
styles,
classNames: {
root: 'bui-MenuSeparator',
},
propDefs: {
className: {},
},
},
);
/** @internal */
export const MenuEmptyStateDefinition = defineComponent<{}>()({
styles,
classNames: {
root: 'bui-MenuEmptyState',
},
propDefs: {},
});
+8
View File
@@ -31,11 +31,19 @@ export type {
MenuTriggerProps,
SubmenuTriggerProps,
MenuProps,
MenuOwnProps,
MenuListBoxProps,
MenuListBoxOwnProps,
MenuAutocompleteProps,
MenuAutocompleteOwnProps,
MenuAutocompleteListBoxProps,
MenuAutocompleteListBoxOwnProps,
MenuItemProps,
MenuItemOwnProps,
MenuListBoxItemProps,
MenuListBoxItemOwnProps,
MenuSectionProps,
MenuSectionOwnProps,
MenuSeparatorProps,
MenuSeparatorOwnProps,
} from './types';
+73 -31
View File
@@ -33,70 +33,112 @@ export interface MenuTriggerProps extends RAMenuTriggerProps {}
export interface SubmenuTriggerProps extends RAMenuSubmenuTriggerProps {}
/** @public */
export interface MenuProps<T>
extends RAMenuProps<T>,
Omit<RAMenuProps<T>, 'children'> {
export type MenuOwnProps = {
placement?: RAPopoverProps['placement'];
virtualized?: boolean;
maxWidth?: string;
maxHeight?: string;
}
style?: React.CSSProperties;
className?: string;
};
/** @public */
export interface MenuProps<T>
extends MenuOwnProps,
Omit<RAMenuProps<T>, keyof MenuOwnProps> {}
/** @public */
export type MenuListBoxOwnProps = {
placement?: RAPopoverProps['placement'];
selectionMode?: RAListBoxProps<object>['selectionMode'];
virtualized?: boolean;
maxWidth?: string;
maxHeight?: string;
style?: React.CSSProperties;
className?: string;
};
/** @public */
export interface MenuListBoxProps<T>
extends RAListBoxProps<T>,
Omit<RAListBoxProps<T>, 'children'> {
extends MenuListBoxOwnProps,
Omit<RAListBoxProps<T>, keyof MenuListBoxOwnProps> {}
/** @public */
export type MenuAutocompleteOwnProps = {
placeholder?: string;
placement?: RAPopoverProps['placement'];
virtualized?: boolean;
maxWidth?: string;
maxHeight?: string;
}
style?: React.CSSProperties;
className?: string;
};
/** @public */
export interface MenuAutocompleteProps<T>
extends RAMenuProps<T>,
Omit<RAMenuProps<T>, 'children'> {
extends MenuAutocompleteOwnProps,
Omit<RAMenuProps<T>, keyof MenuAutocompleteOwnProps> {}
/** @public */
export type MenuAutocompleteListBoxOwnProps = {
placeholder?: string;
placement?: RAPopoverProps['placement'];
selectionMode?: RAListBoxProps<object>['selectionMode'];
virtualized?: boolean;
maxWidth?: string;
maxHeight?: string;
}
style?: React.CSSProperties;
className?: string;
};
/** @public */
export interface MenuAutocompleteListBoxProps<T>
extends RAListBoxProps<T>,
Omit<RAListBoxProps<T>, 'children'> {
placeholder?: string;
placement?: RAPopoverProps['placement'];
virtualized?: boolean;
maxWidth?: string;
maxHeight?: string;
}
extends MenuAutocompleteListBoxOwnProps,
Omit<RAListBoxProps<T>, keyof MenuAutocompleteListBoxOwnProps> {}
/** @public */
export interface MenuItemProps
extends RAMenuItemProps,
Omit<RAMenuItemProps, 'children'> {
export type MenuItemOwnProps = {
iconStart?: React.ReactNode;
children: React.ReactNode;
color?: 'primary' | 'danger';
}
href?: RAMenuItemProps['href'];
className?: string;
};
/** @public */
export interface MenuItemProps
extends MenuItemOwnProps,
Omit<RAMenuItemProps, keyof MenuItemOwnProps> {}
/** @public */
export type MenuListBoxItemOwnProps = {
children: React.ReactNode;
className?: string;
};
/** @public */
export interface MenuListBoxItemProps
extends RAListBoxItemProps,
Omit<RAListBoxItemProps, 'children'> {
extends MenuListBoxItemOwnProps,
Omit<RAListBoxItemProps, keyof MenuListBoxItemOwnProps> {}
/** @public */
export type MenuSectionOwnProps = {
title: string;
children: React.ReactNode;
}
className?: string;
};
/** @public */
export interface MenuSectionProps<T>
extends RAMenuSectionProps<T>,
Omit<RAMenuSectionProps<T>, 'children'> {
title: string;
children: React.ReactNode;
}
extends MenuSectionOwnProps,
Omit<RAMenuSectionProps<T>, keyof MenuSectionOwnProps> {}
/** @public */
export interface MenuSeparatorProps extends RAMenuSeparatorProps {}
export type MenuSeparatorOwnProps = {
className?: string;
};
/** @public */
export interface MenuSeparatorProps
extends MenuSeparatorOwnProps,
Omit<RAMenuSeparatorProps, keyof MenuSeparatorOwnProps> {}