<IconMenu>

This Enterprise EditionReact Admin Enterprise Edition icon 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 on the Enterprise Edition Storybook.

Usage

Create a custom menu component using the <IconMenu> and <IconMenu.Item> components from the ra-navigation package:

// in src/MyMenu.js
import { IconMenu } from "@react-admin/ra-navigation";
import DashboardIcon from '@mui/icons-material/Dashboard';
import MusicIcon from '@mui/icons-material/MusicNote';
import PeopleIcon from '@mui/icons-material/People';
const MyMenu = () => (
 <IconMenu variant="categories">
 <IconMenu.Item name="dashboard" to="/" label="Dashboard" icon={<DashboardIcon />} />
 <IconMenu.Item name="songs" to="/songs" label="Songs" icon={<MusicIcon />} />
 {/* The empty filter is required to avoid falling back to the previously set filter */}
 <IconMenu.Item name="artists" to="/artists" label="Artists" icon={<PeopleIcon />} />
 </IconMenu>
);

Then, create a custom layout using the <Layout> component and pass your custom menu component to it. Make sure you wrap the layout with the <AppLocationContext> component.

// in src/MyLayout.js
import { Layout } from 'react-admin';
import { AppLocationContext } from '@react-admin/ra-navigation';
import { MyMenu } from './MyMenu';
export const MyLayout = ({ children }) => (
 <AppLocationContext>
 <Layout menu={MyMenu}>
 {children}
 </Layout>
 </AppLocationContext>
);

<AppLocationContext> is necessary because ra-navigation doesn’t use the URL to detect the current location. Instead, page components declare their location using a custom hook (useDefineAppLocation()). This allows complex site maps, with multiple levels of nesting. Check the 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.js
import { Admin, Resource } from "react-admin";
import { theme } from '@react-admin/ra-navigation';
import { MyLayout } from './MyLayout';
const App = () => (
 <Admin
 layout={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 the theme provided by the @react-admin/ra-navigation package (as above), or merge it in your own custom theme.

import merge from 'lodash/merge';
import { defaultTheme } from 'react-admin';
import { ThemeOptions } from '@react-admin/ra-navigation';
export const theme: 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.js
import { IconMenu } from "@react-admin/ra-navigation";
import DashboardIcon from '@mui/icons-material/Dashboard';
import MusicIcon from '@mui/icons-material/MusicNote';
import PeopleIcon from '@mui/icons-material/People';
const MyMenu = () => (
 <IconMenu>
 <IconMenu.Item name="dashboard" to="/" label="Dashboard" icon={<DashboardIcon />} />
 <IconMenu.Item name="songs" to="/songs" label="Songs" icon={<MusicIcon />} />
 <IconMenu.Item name="artists" to="/artists" label="Artists" icon={<PeopleIcon />} />
 </IconMenu>
);

Check the <IconMenu.Item> section for more information.

sx: CSS API

Pass an sx prop to customize the style of the main component and the underlying elements.

export const MyMenu = () => (
 <IconMenu sx={{ marginTop: 0 }}>
 // ...
 </IconMenu>
);

To override the style of <IconMenu> using the application-wide style overrides, use the RaMenuRoot key.

<IconMenu.Item>

The <IconMenu.Item> component displays a menu item with a label and an icon.

<IconMenu.Item
 name="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 (see Adding sub menus below)
  • sx: Style overrides, powered by MUI System

Additional props are passed down to the 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";
import DashboardIcon from '@mui/icons-material/Dashboard';
import MusicIcon from '@mui/icons-material/MusicNote';
import PeopleIcon from '@mui/icons-material/People';
const MyMenu = () => (
 <IconMenu>
 <IconMenu.Item name="dashboard" to="/" label="Dashboard" icon={<DashboardIcon />} />
 <IconMenu.Item name="songs" to="/songs" label="Songs" icon={<MusicIcon />} />
 <IconMenu.Item name="artists" to="/artists" label="Artists" icon={<PeopleIcon />}>
 <CardContent>
 {/* to get consistent spacing */}
 <Typography variant="h3" gutterBottom>
 Artist Categories
 </Typography>
 {/* Note that we must wrap our MenuItemNode components in a MenuItemList */}
 <MenuItemList>
 <MenuItemNode
 name="artists.rock"
 to={'/artists?filter={"type":"rock"}'}
 label="Rock"
 />
 <MenuItemNode
 name="artists.jazz"
 to={'/artists?filter={"type":"jazz"}'}
 label="Jazz"
 />
 <MenuItemNode
 name="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 the useResourceDefinitions hook to retrieve the list of resources and create one menu item per resource.

// in src/MyMenu.js
import { createElement } from 'react';
import { useResourceDefinitions } from 'react-admin';
import { IconMenu } from "@react-admin/ra-navigation";
import LabelIcon from '@mui/icons-material/Label';
export const MyMenu = () => {
 const resources = useResourceDefinitions();
 return (
 <IconMenu>
 {Object.keys(resources).map(name => (
 <IconMenu.Item
 key={name}
 name={name}
 to={`/${name}`}
 label={resources[name].options && resources[name].options.label || name}
 icon={createElement(resources[name].icon)}
 />
 ))}
 <IconMenu.Item name="custom.route" to="/custom-route" label="Miscellaneous" icon={<LabelIcon />} />
 </IconMenu>
 );
};

AltStyle によって変換されたページ (->オリジナル) /