diff --git a/packages/components/src/menu/README.md b/packages/components/src/menu/README.md
index a0fe52d060b2a1..b34e21696459d5 100644
--- a/packages/components/src/menu/README.md
+++ b/packages/components/src/menu/README.md
@@ -72,6 +72,9 @@ The placement of the menu popover.
### Menu.TriggerButton
+Renders a menu button that toggles the visibility of a sibling
+`Menu.Popover` component when clicked or when using arrow keys.
+
#### Props
##### `accessibleWhenDisabled`
@@ -125,6 +128,14 @@ merged.
### Menu.Popover
+Renders a dropdown menu element that's controlled by a sibling
+`Menu.TriggerButton` component. It renders a popover and automatically
+focuses on items when the menu is shown.
+
+The only valid children of `Menu.Popover` are `Menu.Item`,
+`Menu.RadioItem`, `Menu.CheckboxItem`, `Menu.Group`, `Menu.Separator`,
+and `Menu` (for nested dropdown menus).
+
#### Props
##### `children`
@@ -185,6 +196,11 @@ negative values to make the popover shift to the opposite side.
### Menu.Item
+Renders a menu item inside the `Menu.Popover` or `Menu.Group` components.
+
+It can optionally contain one instance of the `Menu.ItemLabel` component
+and one instance of the `Menu.ItemHelpText` component.
+
#### Props
##### `children`
@@ -244,6 +260,12 @@ The contents of the menu item's suffix, such as a keyboard shortcut.
### Menu.RadioItem
+Renders a radio menu item inside the `Menu.Popover` or `Menu.Group`
+components.
+
+It can optionally contain one instance of the `Menu.ItemLabel` component
+and one instance of the `Menu.ItemHelpText` component.
+
#### Props
##### `children`
@@ -336,6 +358,12 @@ The radio item's value.
### Menu.CheckboxItem
+Renders a checkbox menu item inside the `Menu.Popover` or `Menu.Group`
+components.
+
+It can optionally contain one instance of the `Menu.ItemLabel` component
+and one instance of the `Menu.ItemHelpText` component.
+
#### Props
##### `children`
@@ -429,6 +457,9 @@ associated to the same `name`.
### Menu.ItemLabel
+Renders a menu item's label text. It should be wrapped with `Menu.Item`,
+`Menu.RadioItem`, or `Menu.CheckboxItem`.
+
#### Props
##### `as`
@@ -440,6 +471,9 @@ The HTML element or React component to render the component as.
### Menu.ItemHelpText
+Renders a menu item's help text. It should be wrapped with `Menu.Item`,
+`Menu.RadioItem`, or `Menu.CheckboxItem`.
+
#### Props
##### `as`
@@ -451,6 +485,11 @@ The HTML element or React component to render the component as.
### Menu.Group
+Renders a group for menu items.
+
+It should contain one instance of `Menu.GroupLabel` and one or more
+instances of `Menu.Item`, `Menu.RadioItem`, or `Menu.CheckboxItem`.
+
#### Props
##### `children`
@@ -464,6 +503,11 @@ The contents of the menu group, which should include one instance of the
### Menu.GroupLabel
+Renders a label in a menu group.
+
+This component should be wrapped with `Menu.Group` so the
+`aria-labelledby` is correctly set on the group element.
+
#### Props
##### `children`
@@ -476,10 +520,17 @@ label for the menu group.
### Menu.Separator
+Renders a divider between menu items or menu groups.
+
#### Props
### Menu.SubmenuTriggerItem
+Renders a menu item that toggles the visibility of a sibling
+`Menu.Popover` component when clicked or when using arrow keys.
+
+This component is used to create a nested dropdown menu.
+
#### Props
##### `children`
diff --git a/packages/components/src/menu/checkbox-item.tsx b/packages/components/src/menu/checkbox-item.tsx
index 69339387c3add5..a3ae4d77085986 100644
--- a/packages/components/src/menu/checkbox-item.tsx
+++ b/packages/components/src/menu/checkbox-item.tsx
@@ -13,18 +13,18 @@ import { Icon, check } from '@wordpress/icons';
* Internal dependencies
*/
import type { WordPressComponentProps } from '../context';
-import { MenuContext } from './context';
-import type { MenuCheckboxItemProps } from './types';
+import { Context } from './context';
+import type { CheckboxItemProps } from './types';
import * as Styled from './styles';
-export const MenuCheckboxItem = forwardRef<
+export const CheckboxItem = forwardRef<
HTMLDivElement,
- WordPressComponentProps< MenuCheckboxItemProps, 'div', false >
->( function MenuCheckboxItem(
+ WordPressComponentProps< CheckboxItemProps, 'div', false >
+>( function CheckboxItem(
{ suffix, children, disabled = false, hideOnClick = false, ...props },
ref
) {
- const menuContext = useContext( MenuContext );
+ const menuContext = useContext( Context );
if ( ! menuContext?.store ) {
throw new Error(
@@ -33,7 +33,7 @@ export const MenuCheckboxItem = forwardRef<
}
return (
-
-
-
+
+
{ children }
-
+
{ suffix && (
{ suffix }
) }
-
-
+
+
);
} );
diff --git a/packages/components/src/menu/context.tsx b/packages/components/src/menu/context.tsx
index 1205015c57cbee..fa38f2c75aea61 100644
--- a/packages/components/src/menu/context.tsx
+++ b/packages/components/src/menu/context.tsx
@@ -6,8 +6,6 @@ import { createContext } from '@wordpress/element';
/**
* Internal dependencies
*/
-import type { MenuContext as MenuContextType } from './types';
+import type { ContextProps } from './types';
-export const MenuContext = createContext< MenuContextType | undefined >(
- undefined
-);
+export const Context = createContext< ContextProps | undefined >( undefined );
diff --git a/packages/components/src/menu/docs-manifest.json b/packages/components/src/menu/docs-manifest.json
index 50e92189a39990..c47fd97e8e09f7 100644
--- a/packages/components/src/menu/docs-manifest.json
+++ b/packages/components/src/menu/docs-manifest.json
@@ -4,57 +4,57 @@
"filePath": "./index.tsx",
"subcomponents": [
{
- "displayName": "MenuTriggerButton",
+ "displayName": "TriggerButton",
"preferredDisplayName": "Menu.TriggerButton",
"filePath": "./trigger-button.tsx"
},
{
- "displayName": "MenuPopover",
+ "displayName": "Popover",
"preferredDisplayName": "Menu.Popover",
"filePath": "./popover.tsx"
},
{
- "displayName": "MenuItem",
+ "displayName": "Item",
"preferredDisplayName": "Menu.Item",
"filePath": "./item.tsx"
},
{
- "displayName": "MenuRadioItem",
+ "displayName": "RadioItem",
"preferredDisplayName": "Menu.RadioItem",
"filePath": "./radio-item.tsx"
},
{
- "displayName": "MenuCheckboxItem",
+ "displayName": "CheckboxItem",
"preferredDisplayName": "Menu.CheckboxItem",
"filePath": "./checkbox-item.tsx"
},
{
- "displayName": "MenuItemLabel",
+ "displayName": "ItemLabel",
"preferredDisplayName": "Menu.ItemLabel",
"filePath": "./item-label.tsx"
},
{
- "displayName": "MenuItemHelpText",
+ "displayName": "ItemHelpText",
"preferredDisplayName": "Menu.ItemHelpText",
"filePath": "./item-help-text.tsx"
},
{
- "displayName": "MenuGroup",
+ "displayName": "Group",
"preferredDisplayName": "Menu.Group",
"filePath": "./group.tsx"
},
{
- "displayName": "MenuGroupLabel",
+ "displayName": "GroupLabel",
"preferredDisplayName": "Menu.GroupLabel",
"filePath": "./group-label.tsx"
},
{
- "displayName": "MenuSeparator",
+ "displayName": "Separator",
"preferredDisplayName": "Menu.Separator",
"filePath": "./separator.tsx"
},
{
- "displayName": "MenuSubmenuTriggerItem",
+ "displayName": "SubmenuTriggerItem",
"preferredDisplayName": "Menu.SubmenuTriggerItem",
"filePath": "./submenu-trigger-item.tsx"
}
diff --git a/packages/components/src/menu/group-label.tsx b/packages/components/src/menu/group-label.tsx
index 5bf081880cb1d7..ce6ecb06900d06 100644
--- a/packages/components/src/menu/group-label.tsx
+++ b/packages/components/src/menu/group-label.tsx
@@ -7,16 +7,16 @@ import { forwardRef, useContext } from '@wordpress/element';
* Internal dependencies
*/
import type { WordPressComponentProps } from '../context';
-import { MenuContext } from './context';
+import { Context } from './context';
import { Text } from '../text';
-import type { MenuGroupLabelProps } from './types';
+import type { GroupLabelProps } from './types';
import * as Styled from './styles';
-export const MenuGroupLabel = forwardRef<
+export const GroupLabel = forwardRef<
HTMLDivElement,
- WordPressComponentProps< MenuGroupLabelProps, 'div', false >
->( function MenuGroup( props, ref ) {
- const menuContext = useContext( MenuContext );
+ WordPressComponentProps< GroupLabelProps, 'div', false >
+>( function Group( props, ref ) {
+ const menuContext = useContext( Context );
if ( ! menuContext?.store ) {
throw new Error(
@@ -25,7 +25,7 @@ export const MenuGroupLabel = forwardRef<
}
return (
-
->( function MenuGroup( props, ref ) {
- const menuContext = useContext( MenuContext );
+ WordPressComponentProps< GroupProps, 'div', false >
+>( function Group( props, ref ) {
+ const menuContext = useContext( Context );
if ( ! menuContext?.store ) {
throw new Error(
@@ -24,10 +24,6 @@ export const MenuGroup = forwardRef<
}
return (
-
+
);
} );
diff --git a/packages/components/src/menu/index.tsx b/packages/components/src/menu/index.tsx
index 4a99533c9d07c4..0af9468a198bc4 100644
--- a/packages/components/src/menu/index.tsx
+++ b/packages/components/src/menu/index.tsx
@@ -13,19 +13,19 @@ import { isRTL as isRTLFn } from '@wordpress/i18n';
* Internal dependencies
*/
import { useContextSystem, contextConnectWithoutRef } from '../context';
-import type { MenuContext as MenuContextType, MenuProps } from './types';
-import { MenuContext } from './context';
-import { MenuItem } from './item';
-import { MenuCheckboxItem } from './checkbox-item';
-import { MenuRadioItem } from './radio-item';
-import { MenuGroup } from './group';
-import { MenuGroupLabel } from './group-label';
-import { MenuSeparator } from './separator';
-import { MenuItemLabel } from './item-label';
-import { MenuItemHelpText } from './item-help-text';
-import { MenuTriggerButton } from './trigger-button';
-import { MenuSubmenuTriggerItem } from './submenu-trigger-item';
-import { MenuPopover } from './popover';
+import type { ContextProps, Props } from './types';
+import { Context } from './context';
+import { Item } from './item';
+import { CheckboxItem } from './checkbox-item';
+import { RadioItem } from './radio-item';
+import { Group } from './group';
+import { GroupLabel } from './group-label';
+import { Separator } from './separator';
+import { ItemLabel } from './item-label';
+import { ItemHelpText } from './item-help-text';
+import { TriggerButton } from './trigger-button';
+import { SubmenuTriggerItem } from './submenu-trigger-item';
+import { Popover } from './popover';
/**
* Menu is a collection of React components that combine to render
@@ -37,7 +37,7 @@ import { MenuPopover } from './popover';
* rendering the `Menu.TriggerButton` (or the `Menu.SubmenuTriggerItem`)
* component, and the `Menu.Popover` component.
*/
-const UnconnectedMenu = ( props: MenuProps ) => {
+const UnconnectedMenu = ( props: Props ) => {
const {
children,
defaultOpen = false,
@@ -49,10 +49,10 @@ const UnconnectedMenu = ( props: MenuProps ) => {
variant,
} = useContextSystem<
// @ts-expect-error TODO: missing 'className' in MenuProps
- typeof props & Pick< MenuContextType, 'variant' >
+ typeof props & Pick< ContextProps, 'variant' >
>( props, 'Menu' );
- const parentContext = useContext( MenuContext );
+ const parentContext = useContext( Context );
const rtl = isRTLFn();
@@ -94,9 +94,7 @@ const UnconnectedMenu = ( props: MenuProps ) => {
);
return (
-
- { children }
-
+ { children }
);
};
@@ -113,7 +111,7 @@ const UnconnectedMenu = ( props: MenuProps ) => {
export const Menu = Object.assign(
contextConnectWithoutRef( UnconnectedMenu, 'Menu' ),
{
- Context: Object.assign( MenuContext, {
+ Context: Object.assign( Context, {
displayName: 'Menu.Context',
} ),
/**
@@ -122,7 +120,7 @@ export const Menu = Object.assign(
* It can optionally contain one instance of the `Menu.ItemLabel` component
* and one instance of the `Menu.ItemHelpText` component.
*/
- Item: Object.assign( MenuItem, {
+ Item: Object.assign( Item, {
displayName: 'Menu.Item',
} ),
/**
@@ -132,7 +130,7 @@ export const Menu = Object.assign(
* It can optionally contain one instance of the `Menu.ItemLabel` component
* and one instance of the `Menu.ItemHelpText` component.
*/
- RadioItem: Object.assign( MenuRadioItem, {
+ RadioItem: Object.assign( RadioItem, {
displayName: 'Menu.RadioItem',
} ),
/**
@@ -142,7 +140,7 @@ export const Menu = Object.assign(
* It can optionally contain one instance of the `Menu.ItemLabel` component
* and one instance of the `Menu.ItemHelpText` component.
*/
- CheckboxItem: Object.assign( MenuCheckboxItem, {
+ CheckboxItem: Object.assign( CheckboxItem, {
displayName: 'Menu.CheckboxItem',
} ),
/**
@@ -151,7 +149,7 @@ export const Menu = Object.assign(
* It should contain one instance of `Menu.GroupLabel` and one or more
* instances of `Menu.Item`, `Menu.RadioItem`, or `Menu.CheckboxItem`.
*/
- Group: Object.assign( MenuGroup, {
+ Group: Object.assign( Group, {
displayName: 'Menu.Group',
} ),
/**
@@ -160,27 +158,27 @@ export const Menu = Object.assign(
* This component should be wrapped with `Menu.Group` so the
* `aria-labelledby` is correctly set on the group element.
*/
- GroupLabel: Object.assign( MenuGroupLabel, {
+ GroupLabel: Object.assign( GroupLabel, {
displayName: 'Menu.GroupLabel',
} ),
/**
* Renders a divider between menu items or menu groups.
*/
- Separator: Object.assign( MenuSeparator, {
+ Separator: Object.assign( Separator, {
displayName: 'Menu.Separator',
} ),
/**
* Renders a menu item's label text. It should be wrapped with `Menu.Item`,
* `Menu.RadioItem`, or `Menu.CheckboxItem`.
*/
- ItemLabel: Object.assign( MenuItemLabel, {
+ ItemLabel: Object.assign( ItemLabel, {
displayName: 'Menu.ItemLabel',
} ),
/**
* Renders a menu item's help text. It should be wrapped with `Menu.Item`,
* `Menu.RadioItem`, or `Menu.CheckboxItem`.
*/
- ItemHelpText: Object.assign( MenuItemHelpText, {
+ ItemHelpText: Object.assign( ItemHelpText, {
displayName: 'Menu.ItemHelpText',
} ),
/**
@@ -192,14 +190,14 @@ export const Menu = Object.assign(
* `Menu.RadioItem`, `Menu.CheckboxItem`, `Menu.Group`, `Menu.Separator`,
* and `Menu` (for nested dropdown menus).
*/
- Popover: Object.assign( MenuPopover, {
+ Popover: Object.assign( Popover, {
displayName: 'Menu.Popover',
} ),
/**
* Renders a menu button that toggles the visibility of a sibling
* `Menu.Popover` component when clicked or when using arrow keys.
*/
- TriggerButton: Object.assign( MenuTriggerButton, {
+ TriggerButton: Object.assign( TriggerButton, {
displayName: 'Menu.TriggerButton',
} ),
/**
@@ -208,7 +206,7 @@ export const Menu = Object.assign(
*
* This component is used to create a nested dropdown menu.
*/
- SubmenuTriggerItem: Object.assign( MenuSubmenuTriggerItem, {
+ SubmenuTriggerItem: Object.assign( SubmenuTriggerItem, {
displayName: 'Menu.SubmenuTriggerItem',
} ),
}
diff --git a/packages/components/src/menu/item-help-text.tsx b/packages/components/src/menu/item-help-text.tsx
index 13d14c294125bd..e47c54d702342f 100644
--- a/packages/components/src/menu/item-help-text.tsx
+++ b/packages/components/src/menu/item-help-text.tsx
@@ -7,14 +7,14 @@ import { forwardRef, useContext } from '@wordpress/element';
* Internal dependencies
*/
import type { WordPressComponentProps } from '../context';
-import { MenuContext } from './context';
+import { Context } from './context';
import * as Styled from './styles';
-export const MenuItemHelpText = forwardRef<
+export const ItemHelpText = forwardRef<
HTMLSpanElement,
WordPressComponentProps< { children: React.ReactNode }, 'span', true >
->( function MenuItemHelpText( props, ref ) {
- const menuContext = useContext( MenuContext );
+>( function ItemHelpText( props, ref ) {
+ const menuContext = useContext( Context );
if ( ! menuContext?.store ) {
throw new Error(
@@ -22,7 +22,5 @@ export const MenuItemHelpText = forwardRef<
);
}
- return (
-
- );
+ return ;
} );
diff --git a/packages/components/src/menu/item-label.tsx b/packages/components/src/menu/item-label.tsx
index 4f5f80e547861f..3a3367f4b481fe 100644
--- a/packages/components/src/menu/item-label.tsx
+++ b/packages/components/src/menu/item-label.tsx
@@ -7,14 +7,14 @@ import { forwardRef, useContext } from '@wordpress/element';
* Internal dependencies
*/
import type { WordPressComponentProps } from '../context';
-import { MenuContext } from './context';
+import { Context } from './context';
import * as Styled from './styles';
-export const MenuItemLabel = forwardRef<
+export const ItemLabel = forwardRef<
HTMLSpanElement,
WordPressComponentProps< { children: React.ReactNode }, 'span', true >
->( function MenuItemLabel( props, ref ) {
- const menuContext = useContext( MenuContext );
+>( function ItemLabel( props, ref ) {
+ const menuContext = useContext( Context );
if ( ! menuContext?.store ) {
throw new Error(
@@ -22,7 +22,5 @@ export const MenuItemLabel = forwardRef<
);
}
- return (
-
- );
+ return ;
} );
diff --git a/packages/components/src/menu/item.tsx b/packages/components/src/menu/item.tsx
index a716cbcc89654c..560d20c30436ce 100644
--- a/packages/components/src/menu/item.tsx
+++ b/packages/components/src/menu/item.tsx
@@ -7,14 +7,14 @@ import { forwardRef, useContext } from '@wordpress/element';
* Internal dependencies
*/
import type { WordPressComponentProps } from '../context';
-import type { MenuItemProps } from './types';
+import type { ItemProps } from './types';
import * as Styled from './styles';
-import { MenuContext } from './context';
+import { Context } from './context';
-export const MenuItem = forwardRef<
+export const Item = forwardRef<
HTMLDivElement,
- WordPressComponentProps< MenuItemProps, 'div', false >
->( function MenuItem(
+ WordPressComponentProps< ItemProps, 'div', false >
+>( function Item(
{
prefix,
suffix,
@@ -26,7 +26,7 @@ export const MenuItem = forwardRef<
},
ref
) {
- const menuContext = useContext( MenuContext );
+ const menuContext = useContext( Context );
if ( ! menuContext?.store ) {
throw new Error(
@@ -41,7 +41,7 @@ export const MenuItem = forwardRef<
const computedStore = store ?? menuContext.store;
return (
-
{ prefix }
-
-
+
+
{ children }
-
+
{ suffix && (
{ suffix }
) }
-
-
+
+
);
} );
diff --git a/packages/components/src/menu/popover.tsx b/packages/components/src/menu/popover.tsx
index 19972a31027ce1..6a3ad9eb683b51 100644
--- a/packages/components/src/menu/popover.tsx
+++ b/packages/components/src/menu/popover.tsx
@@ -17,18 +17,18 @@ import {
* Internal dependencies
*/
import type { WordPressComponentProps } from '../context';
-import type { MenuPopoverProps } from './types';
+import type { PopoverProps } from './types';
import * as Styled from './styles';
-import { MenuContext } from './context';
+import { Context } from './context';
-export const MenuPopover = forwardRef<
+export const Popover = forwardRef<
HTMLDivElement,
- WordPressComponentProps< MenuPopoverProps, 'div', false >
->( function MenuPopover(
+ WordPressComponentProps< PopoverProps, 'div', false >
+>( function Popover(
{ gutter, children, shift, modal = true, ...otherProps },
ref
) {
- const menuContext = useContext( MenuContext );
+ const menuContext = useContext( Context );
// Extract the side from the applied placement — useful for animations.
// Using `currentPlacement` instead of `placement` to make sure that we
@@ -92,9 +92,9 @@ export const MenuPopover = forwardRef<
// container scales with a different factor than its contents.
// The {...renderProps} are passed to the inner wrapper, so that the
// menu element is the direct parent of the menu item elements.
-
-
-
+
+
+
) }
>
{ children }
diff --git a/packages/components/src/menu/radio-item.tsx b/packages/components/src/menu/radio-item.tsx
index 28b3199d7d36b8..1da6d573c26852 100644
--- a/packages/components/src/menu/radio-item.tsx
+++ b/packages/components/src/menu/radio-item.tsx
@@ -13,8 +13,8 @@ import { Icon } from '@wordpress/icons';
* Internal dependencies
*/
import type { WordPressComponentProps } from '../context';
-import { MenuContext } from './context';
-import type { MenuRadioItemProps } from './types';
+import { Context } from './context';
+import type { RadioItemProps } from './types';
import * as Styled from './styles';
import { SVG, Circle } from '@wordpress/primitives';
@@ -24,14 +24,14 @@ const radioCheck = (
);
-export const MenuRadioItem = forwardRef<
+export const RadioItem = forwardRef<
HTMLDivElement,
- WordPressComponentProps< MenuRadioItemProps, 'div', false >
->( function MenuRadioItem(
+ WordPressComponentProps< RadioItemProps, 'div', false >
+>( function RadioItem(
{ suffix, children, disabled = false, hideOnClick = false, ...props },
ref
) {
- const menuContext = useContext( MenuContext );
+ const menuContext = useContext( Context );
if ( ! menuContext?.store ) {
throw new Error(
@@ -40,7 +40,7 @@ export const MenuRadioItem = forwardRef<
}
return (
-
-
-
+
+
{ children }
-
+
{ suffix && (
{ suffix }
) }
-
-
+
+
);
} );
diff --git a/packages/components/src/menu/separator.tsx b/packages/components/src/menu/separator.tsx
index 57cff572c287a0..bdf79c8bb472a2 100644
--- a/packages/components/src/menu/separator.tsx
+++ b/packages/components/src/menu/separator.tsx
@@ -7,15 +7,15 @@ import { forwardRef, useContext } from '@wordpress/element';
* Internal dependencies
*/
import type { WordPressComponentProps } from '../context';
-import { MenuContext } from './context';
-import type { MenuSeparatorProps } from './types';
+import { Context } from './context';
+import type { SeparatorProps } from './types';
import * as Styled from './styles';
-export const MenuSeparator = forwardRef<
+export const Separator = forwardRef<
HTMLHRElement,
- WordPressComponentProps< MenuSeparatorProps, 'hr', false >
->( function MenuSeparator( props, ref ) {
- const menuContext = useContext( MenuContext );
+ WordPressComponentProps< SeparatorProps, 'hr', false >
+>( function Separator( props, ref ) {
+ const menuContext = useContext( Context );
if ( ! menuContext?.store ) {
throw new Error(
@@ -24,7 +24,7 @@ export const MenuSeparator = forwardRef<
}
return (
- = {
id: 'components-menu',
@@ -67,7 +67,7 @@ const meta: Meta< typeof Menu > = {
};
export default meta;
-export const Default: StoryFn< typeof Menu > = ( props: MenuProps ) => (
+export const Default: StoryFn< typeof Menu > = ( props: Props ) => (