Menu
A list of options to help users navigate, or perform actions.Neutral selected states
When the platform-dst-tokens-finesse feature flag is enabled, this component uses the new neutral treatment for selected states.
Default
The menu is a collection of composable menu components to help with wayfinding.
Use menu groups, sections and heading items to structure the menu.
The button item component renders a menu item wrapped in a button tag <button>. Use this component
when you have an action that does something other than navigating to a new page or context.
Link item
The link item component renders a menu item wrapped in an anchor tag <a>. This is the most common
type of menu item, as most menu items are used to send people to another location.
For menu items that do something else, use the button item component instead.
If you need to use a specific router component for route transitions, you'll want to compose them together using the custom item component.
import React, { type MouseEvent, useState } from 'react';
import LinkItem from '@atlaskit/menu/link-item';
// Legacy example: this prop type is deprecated with @atlaskit/side-navigation.
// Use @atlaskit/navigation-system for new side navigation.
import { type LinkItemProps } from '@atlaskit/menu/types';
import { Box } from '@atlaskit/primitives/compiled/box';
import ImgIcon from '../common/img-icon';
import koala from '../icons/koala.png';
const useLinkItemComputedProps = (initialSelectedHref?: string) => {
const [currentHref, setCurrentHref] = useState<string | undefined>(initialSelectedHref);
const getComputedProps = ({ href, ...restProps }: LinkItemProps) => ({
href,
...restProps,
isSelected: currentHref === href,
onClick: () => setCurrentHref(href),
});
return getComputedProps;
};
export default (): React.JSX.Element => {
const getComputedProps = useLinkItemComputedProps('#link-item2');
return (
/**
* It is not normally acceptable to add click handlers to non-interactive elements
* as this is an accessibility anti-pattern. However, because this instance is
* for performance reasons (to avoid multiple click handlers) and not creating an
* inaccessible custom element, we can add role="presentation" so that there is
* no negative impacts to assistive technologies.
*/
<Box onClick={(e: MouseEvent) => e.preventDefault()} role="presentation">
<LinkItem {...getComputedProps({ href: '#link-item1' })}>Customer Feedback</LinkItem>
<LinkItem {...getComputedProps({ href: '#link-item2' })}>Customer Feedback</LinkItem>
<LinkItem {...getComputedProps({ href: '#link-item3' })} isDisabled>
Customer Feedback
</LinkItem>
<LinkItem {...getComputedProps({ href: '#link-item4' })} description="Classic service desk">
Customer Feedback
</LinkItem>
<LinkItem
{...getComputedProps({ href: '#link-item5' })}
iconBefore={<ImgIcon src={koala} alt={'A koala'} />}
description="Classic service desk"
>
Customer Feedback
</LinkItem>
<LinkItem {...getComputedProps({ href: 'https://atlassian.design' })} testId="link-item">
Atlassian Design
</LinkItem>
</Box>
);
};Custom item
Use custom item when you want to create a item using a your own component that inherits the look and feel of a menu item. For example, to use your own router link component. Your custom component will be given all overflow props passed to the custom item component.
import { cssMap, jsx } from '@compiled/react';
import CustomItem from '@atlaskit/menu/custom-item';
// Legacy example: this prop type is deprecated with @atlaskit/side-navigation.
// Use @atlaskit/navigation-system for new side navigation.
import { type CustomItemComponentProps } from '@atlaskit/menu/types';
import { Box } from '@atlaskit/primitives/compiled/box';
import Slack from '../icons/slack';
type CustomComponentWithHrefProps = CustomItemComponentProps & {
href: string;
};
const CustomComponent = ({ children, href, ...props }: CustomComponentWithHrefProps) => {
return (
<a href={href} {...props}>
{children}
</a>
);
};
const styles = cssMap({
root: {
position: 'relative',
overflow: 'hidden',
userSelect: 'none',
},
interactive: {
'&::before': {
content: '""',
position: 'absolute',
insetInlineStart: 0,
insetBlockStart: 0,
insetBlockEnd: 0,
width: 3,
transform: 'translateX(-1px)',
transition: 'transform 70ms ease-in-out',
backgroundColor: '#4C9AFF',
},
'&:hover::before': {
transform: 'translateX(0)',
},
},
});
const _default: () => JSX.Element = () => (
/**
* It is not normally acceptable to add click handlers to non-interactive elements
* as this is an accessibility anti-pattern. However, because this instance is
* for performance reasons (to avoid multiple click handlers) and not creating an
* inaccessible custom element, we can add role="presentation" so that there is
* no negative impacts to assistive technologies.
*/
<Box onClick={(e: React.MouseEvent) => e.preventDefault()} role="presentation">
<CustomItem
href="/navigation-system"
component={CustomComponent}
css={[styles.root, styles.interactive]}
>
CustomItem
</CustomItem>
<CustomItem
href="/navigation-system-1"
isSelected
component={CustomComponent}
css={[styles.root, styles.interactive]}
>
isSelected CustomItem
</CustomItem>
<CustomItem
href="/navigation-system-2"
isDisabled
component={CustomComponent}
css={styles.root}
>
isDisabled CustomItem
</CustomItem>
<CustomItem
href="/navigation-system-3"
component={CustomComponent}
iconBefore={<Slack />}
css={[styles.root, styles.interactive]}
>
iconBefore CustomItem
</CustomItem>
<CustomItem
href="/navigation-system-4"
component={CustomComponent}
iconBefore={<Slack />}
description="Next-gen software project"
css={[styles.root, styles.interactive]}
>
iconBefore and description CustomItem
</CustomItem>
</Box>
);
export default _default;Section and heading item
When there are a large number of items in a menu, allowing users who navigate with a screen reader to skip over sections can greatly improve the user experience. This behavior is done by default with this component by setting a group role and label.
import React from 'react';
import ButtonItem from '@atlaskit/menu/button-item';
import MenuGroup from '@atlaskit/menu/menu-group';
import Section from '@atlaskit/menu/section';
import MenuGroupContainer from '../common/menu-group-container';
export default (): React.JSX.Element => (
<MenuGroupContainer>
<MenuGroup>
<Section title="Actions">
<ButtonItem>Create article</ButtonItem>
</Section>
<Section>
<ButtonItem>Create article</ButtonItem>
</Section>
</MenuGroup>
</MenuGroupContainer>
);Custom heading item
It may be necessary to manually set the HeadingItem; in these cases the below code provides an
example of how to maintain accessibility.
import React from 'react';
import ButtonItem from '@atlaskit/menu/button-item';
import HeadingItem from '@atlaskit/menu/heading-item';
import MenuGroup from '@atlaskit/menu/menu-group';
import Section from '@atlaskit/menu/section';
import MenuGroupContainer from '../common/menu-group-container';
export default (): React.JSX.Element => (
<MenuGroupContainer>
<MenuGroup>
<Section aria-labelledby="actions">
<HeadingItem id="actions" aria-hidden>
Actions
</HeadingItem>
<ButtonItem>Create article</ButtonItem>
</Section>
</MenuGroup>
</MenuGroupContainer>
);Heading item level
Using headingLevel prop to change the level of the heading. The default heading level is h2.
Make sure that headings are in the correct order relative to the pages the menu is on, and don’t
skip levels.
import React from 'react';
import HeadingItem from '@atlaskit/menu/heading-item';
import MenuGroup from '@atlaskit/menu/menu-group';
import Section from '@atlaskit/menu/section';
import MenuGroupContainer from '../common/menu-group-container';
export default (): React.JSX.Element => (
<MenuGroupContainer>
<MenuGroup>
<Section>
<HeadingItem>Heading level 2 (default)</HeadingItem>
</Section>
<Section>
<HeadingItem headingLevel={3}>Heading level 3</HeadingItem>
</Section>
<Section>
<HeadingItem headingLevel={4}>Heading level 4</HeadingItem>
</Section>
<Section>
<HeadingItem headingLevel={5}>Heading level 5</HeadingItem>
</Section>
<Section>
<HeadingItem headingLevel={6}>Heading level 6</HeadingItem>
</Section>
</MenuGroup>
</MenuGroupContainer>
);Density
The menu group can be configured to accept different spacing values. Applying a compact spacing
value will trim the gutters and whitespace, for higher density content.
Scrolling
Menus can be scrollable to fit a fixed height or space.
Scrollable sections
For menus with distinct sections, it's possible to have some scrollable sections.
Scrollable sections don't have as much visual affordance, and should be reserved for user-generated content where the number of menu items isn't known.
Loading
To defer loading the entire menu, the contents can be rendered as skeleton placeholders while the items load asynchronously.