<IconMenu>
ThisEnterprise Edition component offers an alternative menu user interface. It renders a reduced menu bar with a sliding panel for second-level menu items. This menu saves a lot of screen real estate, and allows for sub menus of any level of complexity.
Sometimes, even menus with sub-menus are not enough to organize the navigation.ra-navigation
offers an alternative UI for that case: a vertical bar with small items, where the menu label renders underneath the icon. Clicking on any of those items opens a panel containing as many navigation links as you like, laid out as you wish.
Test it live onthe Enterprise Edition Storybook.
Usage
Create a custom menu component using the<IconMenu>
and<IconMenu.Item>
components from thera-navigation
package:
// in src/MyMenu.jsimport{IconMenu}from"@react-admin/ra-navigation";importDashboardIconfrom'@mui/icons-material/Dashboard';importMusicIconfrom'@mui/icons-material/MusicNote';importPeopleIconfrom'@mui/icons-material/People';constMyMenu=()=>(<IconMenuvariant="categories"><IconMenu.Itemname="dashboard"to="/"label="Dashboard"icon={<DashboardIcon/>}/><IconMenu.Itemname="songs"to="/songs"label="Songs"icon={<MusicIcon/>}/>{/* The empty filter is required to avoid falling back to the previously set filter */}<IconMenu.Itemname="artists"to="/artists"label="Artists"icon={<PeopleIcon/>}/></IconMenu>);
Then, create a custom layout usingthe<Layout>
component and pass your custom menu component to it. Make sure you wrap the layout with the<AppLocationContext>
component.
// in src/MyLayout.jsimport{Layout}from'react-admin';import{AppLocationContext}from'@react-admin/ra-navigation';import{MyMenu}from'./MyMenu';exportconstMyLayout=({children})=>(<AppLocationContext><Layoutmenu={MyMenu}>{children}</Layout></AppLocationContext>);
<AppLocationContext>
is necessary becausera-navigation
doesn’t use the URL to detect the current location. Instead, page componentsdeclare their location using a custom hook (useDefineAppLocation()
). This allows complex site maps, with multiple levels of nesting. Checkthe ra-navigation documentation to learn more about App Location.
Finally, pass this custom layout to the<Admin>
component. You should apply the theme provided by ra-navigation:
// in src/App.jsimport{Admin,Resource}from"react-admin";import{theme}from'@react-admin/ra-navigation';import{MyLayout}from'./MyLayout';constApp=()=>(<Adminlayout={MyLayout}dataProvider={...}theme={theme}> // ...</Admin>);
In order to adjust the size of the React-Admin<Sidebar>
component according to the categories, you should either apply thetheme
provided by the@react-admin/ra-navigation
package (as above), or merge it in your own custom theme.
importmergefrom'lodash/merge';import{defaultTheme}from'react-admin';import{ThemeOptions}from'@react-admin/ra-navigation';exportconsttheme:ThemeOptions=merge({},defaultTheme,{sidebar:{width:96,closedWidth:48,},overrides:{RaSidebar:{fixed:{zIndex:1200,},},},});
Tip: With<IconMenu />
, labels may disappear when the sidebar is in reduced mode. This is because of the internal workings of react-admin. That’s why we recommend implementing your own<AppBar />
, and hiding the Hamburger Button.<IconMenu />
is thin enough not to interfere with the navigation anyway.
Props
Prop | Required | Type | Default | Description |
---|---|---|---|---|
children | Optional | ReactNode | - | The Menu Item Links to be rendered. |
sx | Optional | SxProps | - | Style overrides, powered by MUI System |
Additional props are passed down to the root<div>
component.
children
Pass<IconMenu.Item>
children to<IconMenu>
to define the main menu entries.
// in src/MyMenu.jsimport{IconMenu}from"@react-admin/ra-navigation";importDashboardIconfrom'@mui/icons-material/Dashboard';importMusicIconfrom'@mui/icons-material/MusicNote';importPeopleIconfrom'@mui/icons-material/People';constMyMenu=()=>(<IconMenu><IconMenu.Itemname="dashboard"to="/"label="Dashboard"icon={<DashboardIcon/>}/><IconMenu.Itemname="songs"to="/songs"label="Songs"icon={<MusicIcon/>}/><IconMenu.Itemname="artists"to="/artists"label="Artists"icon={<PeopleIcon/>}/></IconMenu>);
Checkthe<IconMenu.Item>
section for more information.
sx
: CSS API
Pass ansx
prop to customize the style of the main component and the underlying elements.
exportconstMyMenu=()=>(<IconMenusx={{marginTop:0}}> // ...</IconMenu>);
To override the style of<IconMenu>
using theapplication-wide style overrides, use theRaMenuRoot
key.
<IconMenu.Item>
The<IconMenu.Item>
component displays a menu item with a label and an icon.
<IconMenu.Itemname="dashboard"to="/"label="Dashboard"icon={<DashboardIcon/>}/>
It requires the following props:
name
: the name of the location to match. This is used to highlight the current location.to
: the location to link to.label
: The menu item label.icon
: the icon to display.
It accepts optional props:
children
: Content of a sliding panel displayed when the menu is clicked (seeAdding sub menus below)sx
: Style overrides, powered by MUI System
Additional props are passed down tothe underling Material UI<listItem>
component.
Adding Sub Menus
You can define the content of the sliding panel revealed when the user clicks on a menu by adding children to<IconMenu.Item>
.<IconMenu>
renders its children inside a Material UI<Card>
, so it’s common to wrap the content in<CardContent>
.
For instance, here is how to add a sub menu to the Artists menu with one entry for each artist category:
import{IconMenu,MenuItemList,MenuItemNode,}from"@react-admin/ra-navigation";importDashboardIconfrom'@mui/icons-material/Dashboard';importMusicIconfrom'@mui/icons-material/MusicNote';importPeopleIconfrom'@mui/icons-material/People';constMyMenu=()=>(<IconMenu><IconMenu.Itemname="dashboard"to="/"label="Dashboard"icon={<DashboardIcon/>}/><IconMenu.Itemname="songs"to="/songs"label="Songs"icon={<MusicIcon/>}/><IconMenu.Itemname="artists"to="/artists"label="Artists"icon={<PeopleIcon/>}><CardContent>{/* to get consistent spacing */}<Typographyvariant="h3"gutterBottom> Artist Categories</Typography>{/* Note that we must wrap our MenuItemNode components in a MenuItemList */}<MenuItemList><MenuItemNodename="artists.rock"to={'/artists?filter={"type":"rock"}'}label="Rock"/><MenuItemNodename="artists.jazz"to={'/artists?filter={"type":"jazz"}'}label="Jazz"/><MenuItemNodename="artists.classical"to={'/artists?filter={"type":"classical"}'}label="Rock"/></MenuItemList></CardContent></IconMenu.Item></IconMenu>);
Creating Menu Items For Resources
If you want to render a custom menu item and the default resource menu items, use theuseResourceDefinitions
hook to retrieve the list of resources and create one menu item per resource.
// in src/MyMenu.jsimport{createElement}from'react';import{useResourceDefinitions}from'react-admin';import{IconMenu}from"@react-admin/ra-navigation";importLabelIconfrom'@mui/icons-material/Label';exportconstMyMenu=()=>{constresources=useResourceDefinitions();return(<IconMenu>{Object.keys(resources).map(name=>(<IconMenu.Itemkey={name}name={name}to={`/${name}`}label={resources[name].options&&resources[name].options.label||name}icon={createElement(resources[name].icon)}/>))}<IconMenu.Itemname="custom.route"to="/custom-route"label="Miscellaneous"icon={<LabelIcon/>}/></IconMenu>);};