Skip to content

Commit

Permalink
Merge pull request #5421 from marmelab/disable-user-menu
Browse files Browse the repository at this point in the history
Allow to disable the UserMenu without rewriting the AppBar
  • Loading branch information
fzaninotto committed Oct 22, 2020
2 parents aa639d9 + aad5d8a commit 31a3897
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 24 deletions.
46 changes: 28 additions & 18 deletions docs/Theming.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Here is an example customizing an `EditButton` component inside a `Datagrid`, us

{% raw %}
```jsx
import * as React from "react";
import * as React from 'react';
import { NumberField, List, Datagrid, TextField, EditButton } from 'react-admin';
import { makeStyles } from '@material-ui/core/styles';

Expand Down Expand Up @@ -50,7 +50,7 @@ Here is an example using the `classes` property of the `Filter` and `List` compo

{% raw %}
```jsx
import * as React from "react";
import * as React from 'react';
import {
BooleanField,
Datagrid,
Expand Down Expand Up @@ -146,7 +146,7 @@ Sometimes you want the format to depend on the value. The following example show

{% raw %}
```jsx
import * as React from "react";
import * as React from 'react';
import { NumberField, List, Datagrid, TextField, EditButton } from 'react-admin';
import { makeStyles } from '@material-ui/core/styles';
import classnames from 'classnames';
Expand Down Expand Up @@ -189,7 +189,7 @@ Furthermore, you may extract this highlighting strategy into a Higher Order Comp

{% raw %}
```jsx
import * as React from "react";
import * as React from 'react';
import { NumberField, List, Datagrid, TextField, EditButton } from 'react-admin';
import { makeStyles } from '@material-ui/core/styles';
import classnames from 'classnames';
Expand Down Expand Up @@ -244,7 +244,7 @@ const isSmall = useMediaQuery(theme => theme.breakpoints.down('sm'));
const isDesktop = useMediaQuery(theme => theme.breakpoints.up('md'));
```

You can also pass a custom media query as a screen.
You can also pass a custom media query as a screen.

```jsx
const isSmall = useMediaQuery('(min-width:600px)');
Expand All @@ -254,7 +254,7 @@ Here is an example for a responsive list of posts, displaying a `SimpleList` on

```jsx
// in src/posts.js
import * as React from "react";
import * as React from 'react';
import { useMediaQuery } from '@material-ui/core';
import { List, SimpleList, Datagrid, TextField, ReferenceField, EditButton } from 'react-admin';

Expand Down Expand Up @@ -413,7 +413,7 @@ export default MyLayout;
You can replace the default user menu by your own by setting the `userMenu` prop of the `<AppBar>` component. For instance, to add custom menu items, just decorate the default `<UserMenu>` by adding children to it:

```jsx
import * as React from "react";
import * as React from 'react';
import { AppBar, UserMenu, MenuItemLink } from 'react-admin';
import SettingsIcon from '@material-ui/icons/Settings';

Expand All @@ -438,6 +438,17 @@ const MyAppBar = props => <AppBar {...props} userMenu={<MyUserMenu />} />;
const MyLayout = props => <Layout {...props} appBar={MyAppBar} />;
```

You can also remove the `<UserMenu>` from the `<AppBar>` by passing `false` to the `userMenu` prop:

```jsx
import * as React from 'react';
import { AppBar } from 'react-admin';

const MyAppBar = props => <AppBar {...props} userMenu={false} />;

const MyLayout = props => <Layout {...props} appBar={MyAppBar} />;
```

You can also customize the default icon by setting the `icon` prop to the `<UserMenu />` component.

{% raw %}
Expand Down Expand Up @@ -561,7 +572,7 @@ const useStyles = makeStyles(theme => ({
},
}));

const MyLayout = ({
const MyLayout = ({
children,
dashboard,
logout,
Expand All @@ -570,11 +581,11 @@ const MyLayout = ({
const classes = useStyles();
const dispatch = useDispatch();
const open = useSelector(state => state.admin.ui.sidebarOpen);

useEffect(() => {
dispatch(setSidebarVisibility(true));
}, [setSidebarVisibility]);

return (
<div className={classes.root}>
<div className={classes.appFrame}>
Expand Down Expand Up @@ -606,7 +617,7 @@ MyLayout.propTypes = {
export default MyLayout;
```

**Tip**: Don't forget to render a `<Notification>` component in your custom layout, otherwise the undoable updates will never be sent to the server. That's because part of the "undo" logic of react-admin lies in the `<Notification>` component.
**Tip**: Don't forget to render a `<Notification>` component in your custom layout, otherwise the undoable updates will never be sent to the server. That's because part of the "undo" logic of react-admin lies in the `<Notification>` component.

## Adding a Breadcrumb

Expand Down Expand Up @@ -654,13 +665,13 @@ Check [the `ra-navigation` documentation](https://marmelab.com/ra-enterprise/mod

## Customizing the AppBar Content

By default, the react-admin `<AppBar>` component displays the page title. You can override this default by passing children to `<AppBar>` - they will replace the default title. And if you still want to include the page title, make sure you include an element with id `react-admin-title` in the top bar (this uses [React Portals](https://reactjs.org/docs/portals.html)).
By default, the react-admin `<AppBar>` component displays the page title. You can override this default by passing children to `<AppBar>` - they will replace the default title. And if you still want to include the page title, make sure you include an element with id `react-admin-title` in the top bar (this uses [React Portals](https://reactjs.org/docs/portals.html)).

Here is an example customization for `<AppBar>` to include a company logo in the center of the page header:

```jsx
// in src/MyAppBar.js
import * as React from "react";
import * as React from 'react';
import { AppBar } from 'react-admin';
import Typography from '@material-ui/core/Typography';
import { makeStyles } from '@material-ui/core/styles';
Expand Down Expand Up @@ -702,7 +713,7 @@ To use this custom `MyAppBar` component, pass it as prop to a custom `Layout`, a

```jsx
// in src/MyLayout.js
import * as React from "react";
import * as React from 'react';
import { Layout } from 'react-admin';
import MyAppBar from './MyAppBar';

Expand All @@ -726,18 +737,17 @@ const App = () => (

![custom AppBar](./img/custom_appbar.png)


**Tip**: You can change the color of the `<AppBar>` by setting the `color` prop to `default`, `inherit`, `primary`, `secondary` or `transparent`. The default value is `secondary`.

## Replacing The AppBar

For more drastic changes of the top component, you will probably want to create an `<AppBar>` from scratch instead of just passing children to react-admin's `<AppBar>`.
For more drastic changes of the top component, you will probably want to create an `<AppBar>` from scratch instead of just passing children to react-admin's `<AppBar>`.

By default, React-admin uses [Material-ui's `<AppBar>` component](https://material-ui.com/api/app-bar/) together with [react-headroom](https://github.com/KyleAMathews/react-headroom) to hide the `AppBar` on scroll. Here is an example top bar rebuilt from scratch to remove the "headroom" effect:

```jsx
// in src/MyAppBar.js
import * as React from "react";
import * as React from 'react';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
Expand Down Expand Up @@ -1015,7 +1025,7 @@ Whenever a client-side error happens in react-admin, the user sees a default err

```jsx
// in src/MyError.js
import * as React from "react";
import * as React from 'react';
import Button from '@material-ui/core/Button';
import ErrorIcon from '@material-ui/icons/Report';
import History from '@material-ui/icons/History';
Expand Down
25 changes: 19 additions & 6 deletions packages/ra-ui-materialui/src/layout/AppBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const useStyles = makeStyles(
* @param {string} color The color of the AppBar
* @param {Component} logout The logout button component that will be pass to the UserMenu component
* @param {boolean} open State of the <Admin/> Sidebar
* @param {Element} userMenu A custom user menu component for the AppBar. <UserMenu/> component by default
* @param {Element | boolean} userMenu A custom user menu component for the AppBar. <UserMenu/> component by default. Pass false to disable.
*
* @example
*
Expand All @@ -79,8 +79,17 @@ const useStyles = makeStyles(
* className={classes.title}
* id="react-admin-title"
* />
* </AppBar>
* );
* </AppBar>
* );
*};
*
* @example Without a user menu
*
* const MyAppBar = props => {
* const classes = useStyles();
* return (
* <AppBar {...props} userMenu={false} />
* );
*};
*/
const AppBar = (props: AppBarProps): JSX.Element => {
Expand Down Expand Up @@ -146,7 +155,11 @@ const AppBar = (props: AppBarProps): JSX.Element => {
children
)}
<LoadingIndicator />
{cloneElement(userMenu, { logout })}
{typeof userMenu === 'boolean'
? userMenu === true
? cloneElement(<DefaultUserMenu />, { logout })
: null
: cloneElement(userMenu, { logout })}
</Toolbar>
</MuiAppBar>
</HideOnScroll>
Expand All @@ -167,7 +180,7 @@ AppBar.propTypes = {
]),
logout: PropTypes.element,
open: PropTypes.bool,
userMenu: PropTypes.element,
userMenu: PropTypes.oneOfType([PropTypes.element, PropTypes.bool]),
};

AppBar.defaultProps = {
Expand All @@ -179,7 +192,7 @@ export interface AppBarProps extends Omit<MuiAppBarProps, 'title' | 'classes'> {
logout?: JSX.Element;
open?: boolean;
title?: string | JSX.Element;
userMenu?: JSX.Element;
userMenu?: JSX.Element | boolean;
}

export default AppBar;

0 comments on commit 31a3897

Please sign in to comment.