Icon Menu
Icon Menu is a combination of Icon Button and Menu List Item.
Example
function MyMenuIcon () { const companyItems = [ {id: '1', label: 'Another company', icon: 'Camera'}, {id: '2', label: 'Blue company', icon: 'Bell'}, {id: '3', label: 'Delta company', icon: 'Clock'} ] const [currentItemID, setCurrentItemID] = useState(companyItems[0].id); return ( <IconMenu iconName='Key' isSelectable={true}> <IconMenu.Header> <Input aria-label="Search" type="search" placeholder="Search" css={{ width: '100%' }} /> </IconMenu.Header> {companyItems.map((item, i) => { return ( <IconMenu.MenuItem key={i} id={item.id} icon={item.icon} isActive={item.id === currentItemID} onClick={() => setCurrentItemID(item.id)}> {item.label} </IconMenu.MenuItem> ); })} <IconMenu.Action> <Button label="Change Account" size="small" /> </IconMenu.Action> <IconMenu.Footer> <Button iconName="CogWheel" iconAlignment="left" label="Account Settings" size="small" css={{ marginRight: '14px' }} /> <Button iconName="LogOut" iconAlignment="left" label="Logout" size="small" /> </IconMenu.Footer> </IconMenu> ) }
Sub Component
<IconMenu /> has 5 sub components:
<IconMenu.MenuItem />supports list menu items<IconMenu.Header />supports layout, e.g: search box, title.<IconMenu.Content />supports layout.<IconMenu.Action />supports layout.<IconMenu.Footer />supports layout.
Variant
Icon Button
The component supports to customize the icon button, such as: iconName, iconSize, iconKind.
function MyMenuIcon () { const companyItems = [ {label: 'Another company', icon: 'Camera'}, {label: 'Blue company', icon: 'Bell'}, {label: 'Delta company', icon: 'Clock'} ] const IconMenuAction = ({iconName, iconSize, iconKind}) => { return ( <IconMenu iconName={iconName} iconSize={iconSize} iconKind={iconKind} > {companyItems.map((item, i) => { return ( <IconMenu.MenuItem key={i} icon={item.icon} onClick={() => console.log('clicked', item.label)}> {item.label} </IconMenu.MenuItem> ); })} </IconMenu> ) } return ( <div style={{display: 'flex', gap: '20px'}}> <IconMenuAction iconName='Question' iconSize='small' /> <IconMenuAction iconName='Key' iconSize='small' iconKind='negative'/> <IconMenuAction iconName='Person' /> <IconMenuAction iconName='Person' iconKind='primary'/> </div> ) }
Menu Position
The component supports to customize the menu position, such as: placement, offSet.
If no specifying the placement, the placement will be auto.
function MyMenuIcon () { const companyItems = [ {label: 'Another company', icon: 'Camera'}, {label: 'Blue company', icon: 'Bell'}, {label: 'Delta company', icon: 'Clock'} ] const IconMenuAction = ({placement, offSet}) => { return ( <IconMenu iconName='Person' placement={placement} offSet={offSet}> {companyItems.map((item, i) => { return ( <IconMenu.MenuItem key={i} icon={item.icon} onClick={() => console.log('clicked', item.label)}> {item.label} </IconMenu.MenuItem> ); })} </IconMenu> ) } return ( <div style={{display: 'flex', gap: '20px'}}> <IconMenuAction placement="left-start" /> <IconMenuAction placement="bottom-start" /> <IconMenuAction offSet={20} /> </div> ) }
Menu Items
The component supports to render items as a menu list with MenuItem with following features:
-
It allows item to be checked by adding
isSelectabletoIconMenuandisActiveto selectedMenuItem. -
It also allows to disable an item by adding
isDisabledtoMenuItem. -
It also allows to display loading state by adding
isLoadingtoMenuItem. -
Menu will be closed after clicking an item by default. To prevent this behavior, you can add
closeMenuOnClick={false}toMenuItem.
function MyMenuIcon () { const companyItems = [ {id: '1', label: 'Another company'}, {id: '2', label: 'Blue company'}, {id: '3', label: 'Delta company'}, {id: '4', label: 'Beta company', isDisabled: true} ] const [currentItemID, setCurrentItemID] = useState(companyItems[0].id); return ( <div style={{ display: 'flex', gap: '10px' }}> <span>{companyItems.find(item => item.id === currentItemID).label}</span> <IconMenu iconName='Data' isSelectable={true}> {companyItems.map((item, i) => { return ( <IconMenu.MenuItem closeMenuOnClick={false} key={i} id={item.id} isActive={item.id === currentItemID} isDisabled={item.isDisabled} onClick={() => setCurrentItemID(item.id)}> {item.label} </IconMenu.MenuItem> ); })} </IconMenu> </div> ) }
Layouts
The component supports different padding layout: Header, Content, Action, Footer.
function MyMenuIcon () { return ( <IconMenu iconName='Key' isSelectable={true}> <IconMenu.Header> <Input aria-label="Search" type="search" placeholder="Search" css={{ width: '100%' }} /> </IconMenu.Header> <IconMenu.Content> <div> <Text type="body1">Jason Olexander McQueen</Text> <Text type="body2">Very Long Company Name LLC</Text> </div> </IconMenu.Content> <IconMenu.Action> <Button label="Change Account" size="small" /> </IconMenu.Action> <IconMenu.Footer> <Button iconName="CogWheel" iconAlignment="left" label="Account Settings" size="small" css={{ marginRight: '14px' }} /> <Button iconName="LogOut" iconAlignment="left" label="Logout" size="small" /> </IconMenu.Footer> </IconMenu> ) }
Loading State
This component supports to display loading state by adding isLoading to MenuItem.
function MyMenuIcon () { const companyItems = [ {id: '1', label: 'Another company', icon: 'Camera', isLoading: true}, {id: '2', label: 'Blue company', icon: 'Bell', isLoading: true}, {id: '3', label: 'Delta company', icon: 'Clock', isLoading: true} ] const [currentItemID, setCurrentItemID] = useState(companyItems[0].id); return ( <IconMenu iconName='Person' isSelectable={true}> <IconMenu.Header> <Text type="headline4">Account Setting</Text> </IconMenu.Header> {companyItems.map((item, i) => { return ( <IconMenu.MenuItem key={i} id={item.id} icon={item.icon} isActive={item.id === currentItemID} isLoading={item.isLoading} onClick={() => setCurrentItemID(item.id)}> {item.label} </IconMenu.MenuItem> ); })} <IconMenu.Action> <Button iconName="LogOut" iconAlignment="left" label="Logout" size="small" /> </IconMenu.Action> </IconMenu> ) }
Link Support
This component supports rendering menu items as a link (anchor element or external Link component from react-router-dom) while maintaining the appearance of a normal menu item.
This feature is useful when you want menu items to navigate to different pages or routes, while supporting features like cmd+click to open in new tab.
Using with anchor element
function MyMenuIcon () { const menuItems = [ {label: 'Releases', href: '/docs/components/releases', icon: 'Table'}, {label: 'Home', href: '/', icon: 'Image'}, {label: 'Tokens', href: '/docs/design-tokens/introduction', icon: 'AppGrid'} ] return ( <IconMenu iconName='CogWheel'> {menuItems.map((item, i) => { return ( <IconMenu.MenuItem key={i} icon={item.icon} href={item.href}> {item.label} </IconMenu.MenuItem> ); })} </IconMenu> ) }
Using with react-router-dom Link
You can use external link components like react-router-dom Link by passing the component to the as prop and the path to the to prop.
import { Link } from 'react-router-dom';
function MyMenuIcon () {
const menuItems = [
{label: 'Releases', href: '/docs/components/releases', icon: 'Table'},
{label: 'Home', href: '/', icon: 'Image'},
{label: 'Tokens', href: '/', icon: 'AppGrid'}
]
return (
<IconMenu iconName='CogWheel'>
{menuItems.map((item, i) => {
return (
<IconMenu.MenuItem
key={i}
icon={item.icon}
as={Link}
to={item.to}>
{item.label}
</IconMenu.MenuItem>
);
})}
</IconMenu>
)
}
Open State
The component supports to manage the open state with several props
isMenuOpento set open state of menu.onToggleto inform the open state of menu after clicking on icon button or menu item.closeMenuOutsideto close the menu when clicking outside. By default, menu is closed when clicking outside. To prevent this behavior, you can addcloseMenuOutside={false}to component.onClickto overwrite the onClick event of Icon Button. Please be careful if using this prop, you should handle the open state by yourself.
onToggle doesn't work along with closeMenuOutside, closeMenuOnClick and onClick.
function MyMenuIcon () { const [isOpen, setIsOpen] = useState(false); const companyItems = [ {id: '1', label: 'Another company', icon: 'Camera'}, {id: '2', label: 'Blue company', icon: 'Bell'}, {id: '3', label: 'Delta company', icon: 'Clock'} ] const [currentItemID, setCurrentItemID] = useState(companyItems[0].id); const onMenuToggle = (isVisible) => { console.log('is menu open', isVisible) } const handleClick = (id) => { setCurrentItemID(id); setIsOpen(false); } return ( <div style={{ display: 'flex', gap: '10px' }}> <span>{companyItems.find(item => item.id === currentItemID).label}</span> <IconMenu iconName='Data' isMenuOpen={isOpen} onToggle={onMenuToggle} closeMenuOutside={false} > {companyItems.map((item, i) => { return ( <IconMenu.MenuItem key={i} id={item.id} icon={item.icon} isActive={item.id === currentItemID} onClick={() => handleClick(item.id)}> {item.label} </IconMenu.MenuItem> ); })} </IconMenu> </div> ) }
function MyMenuIcon () { const [isOpen, setIsOpen] = useState(false); const companyItems = [ {id: '1', label: 'Another company', icon: 'Camera'}, {id: '2', label: 'Blue company', icon: 'Bell'}, {id: '3', label: 'Delta company', icon: 'Clock'} ] const [currentItemID, setCurrentItemID] = useState(companyItems[0].id); return ( <div style={{ display: 'flex', gap: '10px' }}> <span>{companyItems.find(item => item.id === currentItemID).label}</span> <IconMenu iconName='Data' isMenuOpen={isOpen} onClick={(isOpen) => setIsOpen(!isOpen)} > {companyItems.map((item, i) => { return ( <IconMenu.MenuItem key={i} id={item.id} icon={item.icon} isActive={item.id === currentItemID} closeMenuOnClick={false}> {item.label} </IconMenu.MenuItem> ); })} </IconMenu> </div> ) }
Custom Icon Element
The component is using IconButton to trigger the menu by default. But you can customise the icon with other Icon Components such as: BrandIcon, and Icon by adding customIconElement to <IconMenu>.
function MyMenuIcon () { const companyItems = [ {label: 'Another company', icon: 'Camera'}, {label: 'Blue company', icon: 'Bell'}, {label: 'Delta company', icon: 'Clock'} ] const IconMenuAction = ({customIcon}) => { return ( <IconMenu customIcon={customIcon} > {companyItems.map((item, i) => { return ( <IconMenu.MenuItem key={i} icon={item.icon} onClick={() => console.log('clicked', item.label)}> {item.label} </IconMenu.MenuItem> ); })} </IconMenu> ) } return ( <div style={{display: 'flex', gap: '20px'}}> <IconMenuAction customIcon={<BrandIcon type="appview" />} /> <IconMenuAction customIcon={<Icon name="Plus" color='#255EEE' size='large' />} /> </div> ) }
You can also use App Icon to trigger menu by adding customIconElement to <IconMenu>. It's an external component (mfe-components).
import { AppIcon } from '@adjust/mfe-components ';
function MyMenuIcon () {
const companyItems = [
{label: 'Another company', icon: 'Camera'},
{label: 'Blue company', icon: 'Bell'},
{label: 'Delta company', icon: 'Clock'}
]
const IconMenuAction = ({customIcon}) => {
return (
<IconMenu
customIcon={customIcon}
>
{companyItems.map((item, i) => {
return (
<IconMenu.MenuItem
key={i}
icon={item.icon}
onClick={() => console.log('clicked', item.label)}>
{item.label}
</IconMenu.MenuItem>
);
})}
</IconMenu>
)
}
return (
<IconMenuAction customIcon={<AppIcon appId="com.adjust.insights" appName="adjust Insights" size="small" />} />
)
}
Props
IconMenu
| Name | Type | Default |
|---|---|---|
iconName Name of Icon Button | "AddValue" | "Adjust" | "AIAgent" | "AppGrid" | "ArrowCircleLeft" | "ArrowCircleRight" | "ArrowDown"... | — |
iconSize Size of Icon Button |
| "medium" |
iconKind Kind of Icon Button |
| "light" |
isSelectable allow checked state of menu item |
| false |
itemSize row size of menu item |
| "small" |
isMenuOpen open state of menu |
| — |
onToggle a callback to inform the open state of menu after clicking on icon button or menu item. onToggle doesn't work along with closeMenuOutside, closeMenuOnClick and onClick |
| — |
onClick onClick event to overwrite the behavior of Icon Button's onClick |
| — |
closeMenuOutside menu is closed if clicking outside |
| true |
width width of menu |
| — |
placement placement of menu |
| — |
offSet offset of menu |
| 1 |
aria-label aria-label of Icon Button |
| — |
aria-labelledby aria-labelledby of Icon Button |
| — |
children sub components |
| — |
dataTestId test id of components |
| "icon-menu-test-id" |
customIcon Allow to customize Icon to trigger menu: BrandIcon, AppIcon and Icon |
| — |
data-{foo} Data attributes can be used by testing libraries to retrieve components or assert their existence |
| — |
| * - the prop is required. |
IconMenu.MenuItem
| Name | Type | Default |
|---|---|---|
id id of menu item |
| — |
isActive active (checked) state of menu item |
| false |
isDisabled menu item is disabled |
| — |
isLoading menu item is loading |
| — |
icon icon name of menu item | "AddValue" | "Adjust" | "AIAgent" | "AppGrid" | "ArrowCircleLeft" | "ArrowCircleRight" | "ArrowDown"... | — |
onClick onClick handler of menu item |
| — |
closeMenuOnClick menu is closed after clicking |
| true |
children sub components |
| — |
dataTestId test id of menu item |
| "`icon-menu-item-${id || '0'}`" |
as Allow to use external link component, such as: react-router-dom Link |
| — |
to Path for external link component |
| — |
href URL for anchor element |
| — |
data-{foo} Data attributes can be used by testing libraries to retrieve components or assert their existence |
| — |
| * - the prop is required. |