Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Doc] Update docs for <Breadcrumb> #9640

Merged
merged 3 commits into from
Feb 5, 2024
Merged
Changes from all commits
Commits
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
100 changes: 78 additions & 22 deletions docs/Breadcrumb.md
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ title: "The Breadcrumb Component"

# `<Breadcrumb>`

This [Enterprise Edition](https://marmelab.com/ra-enterprise)<img class="icon" src="./img/premium.svg" /> component renders a breadcrumb path that automatically adapts to the page location. It helps users navigate large web applications.
This [Enterprise Edition](https://marmelab.com/ra-enterprise)<img class="icon" src="./img/premium.svg" /> component renders a breadcrumb path that automatically adapts to the page location. It helps users navigate large web applications.

<video controls autoplay playsinline muted loop width="100%">
<source src="https://marmelab.com/ra-enterprise/modules/assets/ra-navigation/latest/breadcumb-nested-resource.webm" type="video/webm" />
@@ -38,10 +38,12 @@ export const MyLayout = ({ children, ...rest }) => (
);
```

**Tip**: The layout must be wrapped with `<AppLocationContext>`, as `<Breadcrumb>` reads the app location from this context and not the URL. Layout components from `ra-navigation` ([`<ContainerLayout>`](./ContainerLayout.md) or `<SolarLayout>`) already include that context, so it's not necessary to include it in the custom layout.

**Tip**: The layout must be wrapped with `<AppLocationContext>`, as `<Breadcrumb>` reads the app location from this context and not the URL. Layout components from `ra-navigation` ([`<ContainerLayout>`](./ContainerLayout.md) or `<SolarLayout>`) already include that context, so it's not necessary to include it in the custom layout.

**Tip:** The `ra-enterprise` package exports an alternative `<Layout>`, which contains a pre-configured `<Breadcrumb>` that renders breadcrumb paths for all resources.

Next, set this custom layout as the [`<Admin layout>`](./Admin.md#layout) component:

```jsx
import { Admin } from 'react-admin';
import { DataProvider } from './dataProvider';
@@ -105,10 +107,10 @@ export const MyLayout = ({ children, ...rest }) => (

With this setup, the breadcrumb on the post pages now renders as:

- "Dashboard / Posts" on the Post List page
- "Dashboard / Posts / Lorem ipsum" on the Post Edition page with id = 1
- "Dashboard / Posts / Lorem ipsum" on the Post Show page with id = 1
- "Dashboard / Posts / Create" on the Post Creation page
- "🏠️ / Posts" on the Post List page
- "🏠️ / Posts / Lorem ipsum" on the Post Edition page with id = 1
- "🏠️ / Posts / Lorem ipsum" on the Post Show page with id = 1
- "🏠️ / Posts / Create" on the Post Creation page

You can customize the breadcrumb path of each page, as well as add custom pages to the breadcrumb, by adding `children` to the `<Breadcrumb>` component. See [the `children` section](#children) below for more information.

@@ -125,15 +127,23 @@ You don't need to define the app location for CRUD pages as react-admin does it
- Edit: `[resource].edit`. The location also contains the current `record`
- Show: `[resource].show`. The location also contains the current `record`

However, you can customize these default app locations in your CRUD pages, and you must [define the location for custom pages](#adding-custom-pages).
However, you can customize these default app locations in your CRUD pages, and you must [define the location for custom pages](#adding-custom-pages).

To leverage the provided components such as the [`<Breadcrumb>`](#breadcrumb) or [`<MultiLevelMenu>`](./MultiLevelMenu), the layout must be wrapped with `<AppLocationContext>`.

Layout components from `ra-navigation` ([`<ContainerLayout>`](./ContainerLayout) or [`<SolarLayout>`](./SolarLayout)) already include that context, so you can skip that step if you are using one of these layouts.

If, however, you are using the default `<Layout>` component from `react-admin`, or a custom layout, you must wrap it with `<AppLocationContext>`:

## Props

| Prop | Required | Type | Default | Description |
| ----------- | -------- | ------------------- | -------- | -------------------------------------- |
| `children` | Optional | `ReactNode` | - | The Breadcrumb Items to be rendered. |
| `separator` | Optional | `string | function` | ' / ' | The character user as separator |
| `sx` | Optional | `SxProps` | - | Style overrides, powered by MUI System |
| Prop | Required | Type | Default | Description |
| -------------- | -------- | ------------------ | ------- | ------------------------------------------------------------------------------------ |
| `children` | Optional | `ReactNode` | - | The Breadcrumb Items to be rendered. |
| `dashboard` | Optional | `ReactNode` | - | The dashboard component, used to determine if the Admin has a dashboard. |
| `hasDashboard` | Optional | boolean | - | Alternative to `dashboard`. Set to `true` to add a dashboard item to the breadcrumb. |
| `separator` | Optional | string or function | ' / ' | The character user as separator |
| `sx` | Optional | `SxProps` | - | Style overrides, powered by MUI System |

Additional props are passed down to the root `<nav>` component.

@@ -451,7 +461,51 @@ const MyBreadcrumb = () => (
);
```

Check the [`<Breadcrumb.ResourceItem>`](#breadcrumbresourceitem) section for more information.
Check the [`<Breadcrumb.ResourceItem>`](#breadcrumbresourceitem) section for more information.

## `<Breadcrumb.DashboardItem>`

A version of the `<Breadcrumb.Item>` dedicated to the dashboard.

It is convenient for customizing the dashboard item label.

```tsx
const MyBreadcrumbCustomHome = () => (
<Breadcrumb hasDashboard>
<Breadcrumb.DashboardItem label="My Home">
<Breadcrumb.ResourceItem resource="posts" />
<Breadcrumb.ResourceItem resource="comments" />
</Breadcrumb.DashboardItem>
</Breadcrumb>
);
```

Just like with `<Breadcrumb.Item>`, you can also use a React component as label:

```tsx
import { Breadcrumb } from '@react-admin/ra-navigation';
import { Box, Stack } from '@mui/material';
import { visuallyHidden } from '@mui/utils';
import CabinIcon from '@mui/icons-material/Cabin';

const MyBreadcrumbCustomHome = () => (
<Breadcrumb hasDashboard>
<Breadcrumb.DashboardItem
label={
<Stack direction="row" alignItems="center" spacing={1}>
<CabinIcon />
<Box sx={visuallyHidden}>Dashboard</Box>
</Stack>
}
>
<Breadcrumb.ResourceItem resource="posts" />
<Breadcrumb.ResourceItem resource="comments" />
</Breadcrumb.DashboardItem>
</Breadcrumb>
);
```

**Tip:** It's a good practice to include a visually hidden placeholder ('Dashboard' in this example) for screen readers when using an icon as label.

## Using A Dashboard As The Root

@@ -474,12 +528,14 @@ export const MyLayout = ({ children, ...rest }) => (

By doing this, the breadcrumb will now show respectively:

- "Dashboard / Posts" on the Post List page
- "Dashboard / Posts / Show #1" on the Post Show page with id = 1
- "Dashboard / Posts / Edit #1" on the Post Edition page with id = 1
- "Dashboard / Posts / Create" on the Post Creation page
- "🏠️ / Posts" on the Post List page
- "🏠️ / Posts / Show #1" on the Post Show page with id = 1
- "🏠️ / Posts / Edit #1" on the Post Edition page with id = 1
- "🏠️ / Posts / Create" on the Post Creation page

**Tip:** Even though it is rendered as a 'home' icon (🏠️), the dashboard breadcrumb item also contains the hidden placeholder text 'Dashboard', for screen readers. If you want to customize this text, e.g. to rename "Dashboard" to "Home", provide a [custom translation](https://marmelab.com/react-admin/Translation.html) for the `ra.page.dashboard` message.

If you want to customize the dashboard breadcrumb item label, e.g. to rename "Dashboard" to "Home", provide a [custom translation](./Translation.md) for the `ra.page.dashboard` message.
If you want to customize the dashboard breadcrumb item label, e.g. to rename "Dashboard" to "Home", provide a [custom translation](./Translation.md) for the `ra.page.dashboard` message.

## Adding Custom Pages

@@ -604,7 +660,7 @@ const App = () => (

## Nested Resources

When using [nested resources](./Resource.md#nested-resources), you should create breadcrumb items for the sub-resources.
When using [nested resources](./Resource.md#nested-resources), you should create breadcrumb items for the sub-resources.

For instance, the screencast at the top of this page shows a `songs` resource nested in an `artists` resource, using the following routes:

@@ -838,4 +894,4 @@ const MyBreadcrumb = () => (
);
```

As you see, you can compose Breadcrumb item elements at will.
As you see, you can compose Breadcrumb item elements at will.
38 changes: 33 additions & 5 deletions docs/IconMenu.md
Original file line number Diff line number Diff line change
@@ -13,10 +13,13 @@ This [Enterprise Edition](https://marmelab.com/ra-enterprise)<img class="icon" s
Your browser does not support the video tag.
</video>

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](https://storybook.ra-enterprise.marmelab.com/?path=/story/ra-navigation-iconmenu--basic).

## Usage


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

```jsx
@@ -28,15 +31,16 @@ import MusicIcon from '@mui/icons-material/MusicNote';
import PeopleIcon from '@mui/icons-material/People';

const MyMenu = () => (
<IconMenu>
<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](./Layout.md) and pass your custom menu component to it. Make sure you wrap the layout with the `<AppLocationContext>` component.
Then, create a custom layout using [the `<Layout>` component](./Layout.md) and pass your custom menu component to it. Make sure you wrap the layout with the `<AppLocationContext>` component.

```jsx
// in src/MyLayout.js
@@ -52,7 +56,7 @@ export const MyLayout = (props) => (
);
```

`<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](https://marmelab.com/ra-enterprise/modules/ra-navigation) to learn more about App Location.
`<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](https://marmelab.com/ra-enterprise/modules/ra-navigation) to learn more about App Location.

Finally, pass this custom layout to the `<Admin>` component. You should apply the theme provided by ra-navigation:

@@ -74,6 +78,30 @@ const App = () => (
);
```

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.

```tsx
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 |
@@ -127,7 +155,7 @@ To override the style of `<IconMenu>` using the [application-wide style override
The `<IconMenu.Item>` component displays a menu item with a label and an icon.

```jsx
<IconMenu.Item
<IconMenu.Item
name="dashboard"
to="/"
label="Dashboard"
@@ -212,7 +240,7 @@ import LabelIcon from '@mui/icons-material/Label';

export const MyMenu = () => {
const resources = useResourceDefinitions();

return (
<IconMenu>
{Object.keys(resources).map(name => (
27 changes: 16 additions & 11 deletions docs/MultiLevelMenu.md
Original file line number Diff line number Diff line change
@@ -5,7 +5,11 @@ title: "The MultiLevelMenu Component"

# `<MultiLevelMenu>`

This [Enterprise Edition](https://marmelab.com/ra-enterprise)<img class="icon" src="./img/premium.svg" /> component adds support for nested sub menus in the left navigation bar.
This [Enterprise Edition](https://marmelab.com/ra-enterprise)<img class="icon" src="./img/premium.svg" /> component adds support for nested sub menus in the left navigation bar.

![MultiLevelMenu](./img/multilevelmenu.png)

When a React-admin application grows significantly, the default menu might not be the best solution. The `<MultiLevelMenu>` can help unclutter the navigation: it renders a menu with an infinite number of levels and sub-menus. Menu Items that are not at the top level are rendered inside a collapsible panel.

<video controls autoplay playsinline muted loop>
<source src="https://marmelab.com/ra-enterprise/modules/assets/ra-multilevelmenu-item.webm" type="video/webm" />
@@ -50,7 +54,7 @@ const MyMenu = () => (

Note that each `<MultiLevelMenu.Item>` requires a unique `name` attribute.

Then, create a custom layout using [the `<Layout>` component](./Layout.md) and pass your custom menu component to it. Make sure you wrap the layout with the `<AppLocationContext>` component.
Then, create a custom layout using [the `<Layout>` component](./Layout.md) and pass your custom menu component to it. Make sure you wrap the layout with the `<AppLocationContext>` component.

```jsx
// in src/MyLayout.js
@@ -66,7 +70,7 @@ export const MyLayout = (props) => (
);
```

`<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. That's the reason why each `<MultiLevelMenu.Item>` requires a unique `name`, that matches a particular page location.
`<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. That's the reason why each `<MultiLevelMenu.Item>` requires a unique `name`, that matches a particular page location.

You can set the `AppLocation` for a given page like so:

@@ -89,7 +93,7 @@ And then use this `AppLocation` as `name` for `<MultiLevelMenu.Item>`:
>
```

Check [the ra-navigation documentation](https://marmelab.com/ra-enterprise/modules/ra-navigation) to learn more about App Location.
Check [the ra-navigation documentation](https://marmelab.com/ra-enterprise/modules/ra-navigation) to learn more about App Location.

Finally, pass this custom layout to the `<Admin>` component

@@ -111,11 +115,12 @@ const App = () => (

## Props

| Prop | Required | Type | Default | Description |
| ------------- | -------- | ----------- | -------- | -------------------------------------- |
| `children` | Optional | `ReactNode` | - | The Menu Items to be rendered. |
| `initialOpen` | Optional | `boolean` | `false` | Whether the menu is initially open. |
| `sx` | Optional | `SxProps` | - | Style overrides, powered by MUI System |
| Prop | Required | Type | Default | Description |
| -------------- | -------- | ----------- | -------- | ------------------------------------------------------------- |
| `children` | Optional | `ReactNode` | - | The Menu Items to be rendered. |
| `initialOpen` | Optional | `boolean` | `false` | Whether the menu is initially open. |
| `openItemList` | Optional | `Array` | - | List of names of menu items that should be opened by default. |
| `sx` | Optional | `SxProps` | - | Style overrides, powered by MUI System |

Additional props are passed down to the root `<div>` component.

@@ -175,7 +180,7 @@ To override the style of `<MultiLevelMenu>` using the [application-wide style ov
The `<MultiLevelMenu.Item>` component displays a menu item with a label and an icon.

```jsx
<MultiLevelMenu.Item
<MultiLevelMenu.Item
name="dashboard"
to="/"
label="Dashboard"
@@ -210,7 +215,7 @@ import LabelIcon from '@mui/icons-material/Label';

export const MyMenu = () => {
const resources = useResourceDefinitions();

return (
<MultiLevelMenu>
{Object.keys(resources).map(name => (
Binary file added docs/img/multilevelmenu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading