Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
32f31b3
Use cases section
julauxen Jan 19, 2026
c0522fe
Anatomy and Types
julauxen Jan 19, 2026
fbb9363
Organizing "Organizing menu items" section
julauxen Jan 19, 2026
df9b6c6
Do and donts and cleanup
julauxen Jan 19, 2026
553159f
content guidelines and update to accessibility
julauxen Jan 19, 2026
ed911b5
description
julauxen Jan 19, 2026
28faadd
minor typo
julauxen Jan 20, 2026
ecdb480
splitting up the paragraph
julauxen Jan 20, 2026
fb95110
detail on icon only copy
julauxen Jan 20, 2026
2bf0aa0
adding anatomy diagram
luketa8 Jan 20, 2026
278cf4b
adjunsting arrows
luketa8 Jan 20, 2026
a7d6eb0
adjustments
luketa8 Jan 20, 2026
8971f1e
Update MenuAnatomy.js
luketa8 Jan 20, 2026
156f100
minor adjustments
luketa8 Jan 20, 2026
22b5866
removed anatomy to move to another branch
luketa8 Jan 21, 2026
34d9c83
implement task #5726 for Types section
Sulaymon333 Jan 27, 2026
d45073d
fix #5727 for menu page
Sulaymon333 Jan 27, 2026
0fc53e3
revert commits to main PR
Sulaymon333 Jan 30, 2026
1315067
Menu anatomy (#5713)
luketa8 Feb 5, 2026
fde60c6
Update menu.mdx
julauxen Feb 6, 2026
b4cbcc7
remove unused imports
Sulaymon333 Feb 9, 2026
7b81743
[Docs] Menu types section update (#5745)
Sulaymon333 Feb 9, 2026
44d86f9
merge with master
britt6612 Feb 12, 2026
1fba711
Merge branch 'master' of github.com:grommet/hpe-design-system into Me…
britt6612 Feb 13, 2026
92037ba
[Docs] Menu do-donts section update (#5746)
Sulaymon333 Feb 18, 2026
d970794
restore MenuAnatomy section inside menu.mdx
Sulaymon333 Feb 18, 2026
1fe99e3
Update menu.mdx
julauxen Feb 19, 2026
07a4d4c
Update apps/docs/src/data/structures/components.js
julauxen Feb 20, 2026
9fcfaa5
Update apps/docs/src/pages/components/menu.mdx
julauxen Feb 20, 2026
77d23f2
added background-back to example
halocline Feb 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/docs/src/data/structures/components.js
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,7 @@ export const components = [
accessibility: 'Passed WCAG 2.2 AA',
category: 'Controls',
description:
'Menu is a component that contains a list of actions. When a user clicks an item in the menu, the menu closes and the action is executed.',
'A menu presents a set of related actions from which a user may choose.',
seoDescription:
'Menu contains a list of actions. See some best UX practices .',
sections: [
Expand Down
187 changes: 187 additions & 0 deletions apps/docs/src/examples/components/menu/MenuAnatomy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
import React, { useContext } from 'react';
import { Box, Grid, Diagram, Stack, ThemeContext } from 'grommet';
import { Add } from '@hpe-design/icons-grommet';
import { Annotation } from '../../../layouts';
import {
MenuMockButton,
MenuMockContainer,
MenuMockItem,
MenuMockGroup,
} from './MenuMock';

const color = 'border';
const thickness = 'hair';
const type = 'direct';

const connections = [
{
anchor: 'horizontal',
type,
color,
thickness,
fromTarget: '1',
toTarget: 'menu-button',
},
{
anchor: 'vertical',
type,
color,
thickness,
fromTarget: '1a',
toTarget: 'menu-label',
},
{
anchor: 'vertical',
type,
color,
thickness,
fromTarget: '1b',
toTarget: 'menu-icon',
},
{
anchor: 'horizontal',
type,
color,
thickness,
fromTarget: '2',
toTarget: 'drop-container',
},
{
anchor: 'horizontal',
type,
color,
thickness,
fromTarget: '3',
toTarget: 'menu-item-target',
},
{
anchor: 'vertical',
type,
color,
thickness,
fromTarget: '3a',
toTarget: 'item-label',
},
{
anchor: 'vertical',
type,
color,
thickness,
fromTarget: '3b',
toTarget: 'item-icon',
},
{
anchor: 'horizontal',
type,
color,
thickness,
fromTarget: '4',
toTarget: 'divider-target',
},
];

const AnatomyGrid = ({ ...rest }) => (
<Grid
columns={['max-content', 'max-content', '5xsmall']}
rows={[
'5xsmall',
'flex',
'flex',
'flex',
'flex',
'flex',
'flex',
'flex',
'flex',
'flex',
'5xsmall',
]}
areas={[
['annotation-1a', 'annotation-1b', 'empty-0'],
['menu-area', 'menu-area', 'annotation-1'],
['menu-area', 'menu-area', 'empty-1'],
['menu-area', 'menu-area', 'annotation-2'],
['menu-area', 'menu-area', 'empty-2'],
['menu-area', 'menu-area', 'empty-3'],
['menu-area', 'menu-area', 'annotation-4'],
['menu-area', 'menu-area', 'empty-4'],
['menu-area', 'menu-area', 'empty-5'],
['menu-area', 'menu-area', 'annotation-3'],
['annotation-3a', 'annotation-3b', 'empty-6'],
]}
align="center"
justify="center"
{...rest}
/>
);

export const MenuAnatomy = () => {
const theme = useContext(ThemeContext);
const menuTheme = theme?.menu || {};
const dropTheme = theme?.global.drop || {};

const annotations = [
{ id: '1', gridArea: 'annotation-1', target: '1' },
{ id: '1a', gridArea: 'annotation-1a', target: '1a' },
{ id: '1b', gridArea: 'annotation-1b', target: '1b' },
{ id: '2', gridArea: 'annotation-2', target: '2' },
{ id: '3', gridArea: 'annotation-3', target: '3' },
{ id: '3a', gridArea: 'annotation-3a', target: '3a' },
{ id: '3b', gridArea: 'annotation-3b', target: '3b' },
{ id: '4', gridArea: 'annotation-4', target: '4' },
];

return (
<Stack margin={{ bottom: 'medium' }} interactiveChild="last">
<AnatomyGrid>
{annotations.map(({ id, gridArea, target, ...rest }) => (
<Annotation
key={id}
id={id}
target={target}
gridArea={gridArea}
{...rest}
/>
))}

{/* Menu anatomy mockup */}
<Box gridArea="menu-area" align="start">
{/* Adding bounding box to add dashed outline for clarity */}
<Box
border={{ style: 'dashed' }}
round="small"
margin={dropTheme.margin}
>
<MenuMockButton
round="small"
id="menu-button"
label={<Box id="menu-label">Menu</Box>}
icon={<Box id="menu-icon">{menuTheme.icons?.down.render()}</Box>}
/>
</Box>
<MenuMockContainer>
<MenuMockGroup id="drop-container">
<MenuMockItem label="Action" />
<MenuMockItem label="Action" />
<MenuMockItem label="Action" />
</MenuMockGroup>
<MenuMockGroup showDivider dividerProps={{ id: 'divider-target' }}>
<MenuMockItem label="Action" />
<MenuMockItem icon={<Add />} label="Action" />
{/* Adding bounding box to add dashed outline for clarity */}
<Box border={{ style: 'dashed' }} round="small">
<MenuMockItem
id="menu-item-target"
label={<Box id="item-label">Action</Box>}
icon={<Add id="item-icon" />}
reverse
/>
</Box>
</MenuMockGroup>
</MenuMockContainer>
</Box>
</AnatomyGrid>
<Diagram connections={connections} />
</Stack>
);
};
19 changes: 9 additions & 10 deletions apps/docs/src/examples/components/menu/MenuDangerousExample.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import PropTypes from 'prop-types';
import { Menu, Notification } from 'grommet';
import { Notification } from 'grommet';

import { useState } from 'react';
import { DestructiveConfirmation } from '../../templates';
import { MenuMock } from './MenuMock';

export const MenuDangerousExample = ({ bestPractice = true }) => {
const [showModal, setShowModal] = useState(false);
const [toast, setToast] = useState(false);

const items = [
{ label: 'View details', onClick: () => {} },
{ label: 'Edit profile', onClick: () => {} },
{ label: 'Apply blueprint', onClick: () => {} },
{ label: 'Edit' },
{ label: 'View servers' },
{
label: 'Delete',
onClick: () => {
Expand All @@ -23,9 +23,8 @@ export const MenuDangerousExample = ({ bestPractice = true }) => {

return (
<>
<Menu
<MenuMock
label="Actions"
open
items={
bestPractice
? [items.slice(0, items.length - 1), items.slice(-1)]
Expand All @@ -34,10 +33,10 @@ export const MenuDangerousExample = ({ bestPractice = true }) => {
/>
{showModal && (
<DestructiveConfirmation
title="Delete profile"
message={`This will permanently delete this profile,
title="Delete server"
message={`This will permanently delete this server,
including all history, located at:`}
path="/servers/profiles/KCHDvfcByKvvjymNheg"
path="/servers/KCHDvfcByKvvjymNheg"
setShowModal={setShowModal}
setToast={setToast}
/>
Expand All @@ -46,7 +45,7 @@ export const MenuDangerousExample = ({ bestPractice = true }) => {
<Notification
toast
status="normal"
message="Profile deleted."
message="Server deleted."
onClose={() => setToast(false)}
/>
)}
Expand Down
12 changes: 12 additions & 0 deletions apps/docs/src/examples/components/menu/MenuDefaultExample.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import { Menu } from 'grommet';

export const MenuDefaultExample = () => {
const items = [
{ label: 'Edit' },
{ label: 'View servers' },
{ label: 'Add servers' },
];

return <Menu label="Servers" items={items} alignSelf="start" />;
};
30 changes: 20 additions & 10 deletions apps/docs/src/examples/components/menu/MenuGroupingExample.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
import PropTypes from 'prop-types';
import { Menu } from 'grommet';
import { MenuMock } from './MenuMock';

export const MenuGroupingExample = ({ bestPractice = true }) => (
<Menu
label="Actions"
open
<MenuMock
label="Servers"
items={
bestPractice
? [
{ label: 'View', onClick: () => {} },
{ label: 'Add to group', onClick: () => {} },
{ label: 'Update firmware', onClick: () => {} },
[
{ label: 'Edit' },
{
label: 'View servers',
},
{ label: 'Add servers' },
{ label: 'Remove servers' },
],
[{ label: 'Update firmware' }, { label: 'Update BIOS settings' }],
[{ label: 'Delete' }],
]
: [
[{ label: 'View', onClick: () => {} }],
[{ label: 'Add to group', onClick: () => {} }],
[{ label: 'Update firmware', onClick: () => {} }],
[{ label: 'Edit' }],
[{ label: 'View servers' }],
[{ label: 'Add servers' }],
[{ label: 'Remove servers' }],
[{ label: 'Update firmware' }],
[{ label: 'Update BIOS settings' }],
[{ label: 'Delete' }],
]
}
/>
Expand Down
43 changes: 19 additions & 24 deletions apps/docs/src/examples/components/menu/MenuIconExample.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,26 @@
import React from 'react';
import { Box, List, Menu } from 'grommet';
import { More } from '@hpe-design/icons-grommet';
import { Box, Menu } from 'grommet';
import { More, Settings } from '@hpe-design/icons-grommet';

export const MenuIconExample = () => {
const data = ['User 1', 'User 2', 'User 3'];

return (
<Box width={{ max: 'xlarge' }} fill>
<List
data={data}
pad="xsmall"
action={() => (
<Box direction="row" align="center" gap="medium">
<Menu
icon={<More />}
hoverIndicator
items={[{ label: 'Deactivate' }, { label: 'Suspend' }]}
/>
</Box>
)}
>
{(datum, index) => (
<Box key={index} direction="row" align="center" justify="between">
{datum}
</Box>
)}
</List>
<Box direction="row" align="start" gap="small">
<Menu
icon={<More />}
items={[
{ label: 'Edit' },
{ label: 'View servers' },
{ label: 'Add servers' },
]}
/>
<Menu
icon={<Settings />}
items={[
{ label: 'Edit preferences' },
{ label: 'View system details' },
{ label: 'Reset system settings' },
]}
/>
</Box>
);
};
35 changes: 35 additions & 0 deletions apps/docs/src/examples/components/menu/MenuItemCountExample.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import PropTypes from 'prop-types';
import { MenuMock } from './MenuMock';

export const MenuItemCountExample = ({ bestPractice = true }) => (
<MenuMock
label="Servers"
items={
bestPractice
? [
{ label: 'Edit' },
{ label: 'View servers' },
{ label: 'Add servers' },
{ label: 'Remove servers' },
]
: [
[
{ label: 'Edit' },
{ label: 'View servers' },
{ label: 'Add servers' },
{ label: 'Remove servers' },
],
[
{ label: 'Reset servers' },
{ label: 'Update firmware' },
{ label: 'Update BIOS settings' },
],
[{ label: 'Delete' }],
]
}
/>
);

MenuItemCountExample.propTypes = {
bestPractice: PropTypes.bool,
};
Loading