The App Bar displays information and actions relating to the current screen.
The top App bar provides content and actions related to the current screen. It’s used for branding, screen titles, navigation, and actions.
It can transform into a contextual action bar or be used as a navbar.
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
import MenuIcon from '@mui/icons-material/Menu';
export default function ButtonAppBar() {
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<Toolbar>
<IconButton
size="large"
edge="start"
color="inherit"
aria-label="menu"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
News
</Typography>
<Button color="inherit">Login</Button>
</Toolbar>
</AppBar>
</Box>
);
}
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
import MenuIcon from '@mui/icons-material/Menu';
import AccountCircle from '@mui/icons-material/AccountCircle';
import Switch from '@mui/material/Switch';
import FormControlLabel from '@mui/material/FormControlLabel';
import FormGroup from '@mui/material/FormGroup';
import MenuItem from '@mui/material/MenuItem';
import Menu from '@mui/material/Menu';
export default function MenuAppBar() {
const [auth, setAuth] = React.useState(true);
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setAuth(event.target.checked);
};
const handleMenu = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<Box sx={{ flexGrow: 1 }}>
<FormGroup>
<FormControlLabel
control={
<Switch
checked={auth}
onChange={handleChange}
aria-label="login switch"
/>
}
label={auth ? 'Logout' : 'Login'}
/>
</FormGroup>
<AppBar position="static">
<Toolbar>
<IconButton
size="large"
edge="start"
color="inherit"
aria-label="menu"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Photos
</Typography>
{auth && (
<div>
<IconButton
size="large"
aria-label="account of current user"
aria-controls="menu-appbar"
aria-haspopup="true"
onClick={handleMenu}
color="inherit"
>
<AccountCircle />
</IconButton>
<Menu
id="menu-appbar"
anchorEl={anchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
</Menu>
</div>
)}
</Toolbar>
</AppBar>
</Box>
);
}
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography';
import Menu from '@mui/material/Menu';
import MenuIcon from '@mui/icons-material/Menu';
import Container from '@mui/material/Container';
import Avatar from '@mui/material/Avatar';
import Button from '@mui/material/Button';
import Tooltip from '@mui/material/Tooltip';
import MenuItem from '@mui/material/MenuItem';
import AdbIcon from '@mui/icons-material/Adb';
const pages = ['Products', 'Pricing', 'Blog'];
const settings = ['Profile', 'Account', 'Dashboard', 'Logout'];
function ResponsiveAppBar() {
const [anchorElNav, setAnchorElNav] = React.useState<null | HTMLElement>(null);
const [anchorElUser, setAnchorElUser] = React.useState<null | HTMLElement>(null);
const handleOpenNavMenu = (event: React.MouseEvent<HTMLElement>) => {
setAnchorElNav(event.currentTarget);
};
const handleOpenUserMenu = (event: React.MouseEvent<HTMLElement>) => {
setAnchorElUser(event.currentTarget);
};
const handleCloseNavMenu = () => {
setAnchorElNav(null);
};
const handleCloseUserMenu = () => {
setAnchorElUser(null);
};
return (
<AppBar position="static">
<Container maxWidth="xl">
<Toolbar disableGutters>
<AdbIcon sx={{ display: { xs: 'none', md: 'flex' }, mr: 1 }} />
<Typography
variant="h6"
noWrap
component="a"
href="#app-bar-with-responsive-menu"
sx={{
mr: 2,
display: { xs: 'none', md: 'flex' },
fontFamily: 'monospace',
fontWeight: 700,
letterSpacing: '.3rem',
color: 'inherit',
textDecoration: 'none',
}}
>
LOGO
</Typography>
<Box sx={{ flexGrow: 1, display: { xs: 'flex', md: 'none' } }}>
<IconButton
size="large"
aria-label="account of current user"
aria-controls="menu-appbar"
aria-haspopup="true"
onClick={handleOpenNavMenu}
color="inherit"
>
<MenuIcon />
</IconButton>
<Menu
id="menu-appbar"
anchorEl={anchorElNav}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'left',
}}
open={Boolean(anchorElNav)}
onClose={handleCloseNavMenu}
sx={{ display: { xs: 'block', md: 'none' } }}
>
{pages.map((page) => (
<MenuItem key={page} onClick={handleCloseNavMenu}>
<Typography sx={{ textAlign: 'center' }}>{page}</Typography>
</MenuItem>
))}
</Menu>
</Box>
<AdbIcon sx={{ display: { xs: 'flex', md: 'none' }, mr: 1 }} />
<Typography
variant="h5"
noWrap
component="a"
href="#app-bar-with-responsive-menu"
sx={{
mr: 2,
display: { xs: 'flex', md: 'none' },
flexGrow: 1,
fontFamily: 'monospace',
fontWeight: 700,
letterSpacing: '.3rem',
color: 'inherit',
textDecoration: 'none',
}}
>
LOGO
</Typography>
<Box sx={{ flexGrow: 1, display: { xs: 'none', md: 'flex' } }}>
{pages.map((page) => (
<Button
key={page}
onClick={handleCloseNavMenu}
sx={{ my: 2, color: 'white', display: 'block' }}
>
{page}
</Button>
))}
</Box>
<Box sx={{ flexGrow: 0 }}>
<Tooltip title="Open settings">
<IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
<Avatar alt="Remy Sharp" src="/static/images/avatar/2.jpg" />
</IconButton>
</Tooltip>
<Menu
sx={{ mt: '45px' }}
id="menu-appbar"
anchorEl={anchorElUser}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
open={Boolean(anchorElUser)}
onClose={handleCloseUserMenu}
>
{settings.map((setting) => (
<MenuItem key={setting} onClick={handleCloseUserMenu}>
<Typography sx={{ textAlign: 'center' }}>{setting}</Typography>
</MenuItem>
))}
</Menu>
</Box>
</Toolbar>
</Container>
</AppBar>
);
}
export default ResponsiveAppBar;
A side searchbar.
import * as React from 'react';
import { styled, alpha } from '@mui/material/styles';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography';
import InputBase from '@mui/material/InputBase';
import MenuIcon from '@mui/icons-material/Menu';
import SearchIcon from '@mui/icons-material/Search';
const Search = styled('div')(({ theme }) => ({
position: 'relative',
borderRadius: theme.shape.borderRadius,
backgroundColor: alpha(theme.palette.common.white, 0.15),
'&:hover': {
backgroundColor: alpha(theme.palette.common.white, 0.25),
},
marginLeft: 0,
width: '100%',
[theme.breakpoints.up('sm')]: {
marginLeft: theme.spacing(1),
width: 'auto',
},
}));
const SearchIconWrapper = styled('div')(({ theme }) => ({
padding: theme.spacing(0, 2),
height: '100%',
position: 'absolute',
pointerEvents: 'none',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}));
const StyledInputBase = styled(InputBase)(({ theme }) => ({
color: 'inherit',
width: '100%',
'& .MuiInputBase-input': {
padding: theme.spacing(1, 1, 1, 0),
// vertical padding + font size from searchIcon
paddingLeft: `calc(1em + ${theme.spacing(4)})`,
transition: theme.transitions.create('width'),
[theme.breakpoints.up('sm')]: {
width: '12ch',
'&:focus': {
width: '20ch',
},
},
},
}));
export default function SearchAppBar() {
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<Toolbar>
<IconButton
size="large"
edge="start"
color="inherit"
aria-label="open drawer"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<Typography
variant="h6"
noWrap
component="div"
sx={{ flexGrow: 1, display: { xs: 'none', sm: 'block' } }}
>
MUI
</Typography>
<Search>
<SearchIconWrapper>
<SearchIcon />
</SearchIconWrapper>
<StyledInputBase
placeholder="Search…"
inputProps={{ 'aria-label': 'search' }}
/>
</Search>
</Toolbar>
</AppBar>
</Box>
);
}
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import CssBaseline from '@mui/material/CssBaseline';
import Divider from '@mui/material/Divider';
import Drawer from '@mui/material/Drawer';
import IconButton from '@mui/material/IconButton';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemText from '@mui/material/ListItemText';
import MenuIcon from '@mui/icons-material/Menu';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
interface Props {
/**
* Injected by the documentation to work in an iframe.
* You won't need it on your project.
*/
window?: () => Window;
}
const drawerWidth = 240;
const navItems = ['Home', 'About', 'Contact'];
export default function DrawerAppBar(props: Props) {
const { window } = props;
const [mobileOpen, setMobileOpen] = React.useState(false);
const handleDrawerToggle = () => {
setMobileOpen((prevState) => !prevState);
};
const drawer = (
<Box onClick={handleDrawerToggle} sx={{ textAlign: 'center' }}>
<Typography variant="h6" sx={{ my: 2 }}>
MUI
</Typography>
<Divider />
<List>
{navItems.map((item) => (
<ListItem key={item} disablePadding>
<ListItemButton sx={{ textAlign: 'center' }}>
<ListItemText primary={item} />
</ListItemButton>
</ListItem>
))}
</List>
</Box>
);
const container = window !== undefined ? () => window().document.body : undefined;
return (
<Box sx={{ display: 'flex' }}>
<CssBaseline />
<AppBar component="nav">
<Toolbar>
<IconButton
color="inherit"
aria-label="open drawer"
edge="start"
onClick={handleDrawerToggle}
sx={{ mr: 2, display: { sm: 'none' } }}
>
<MenuIcon />
</IconButton>
<Typography
variant="h6"
component="div"
sx={{ flexGrow: 1, display: { xs: 'none', sm: 'block' } }}
>
MUI
</Typography>
<Box sx={{ display: { xs: 'none', sm: 'block' } }}>
{navItems.map((item) => (
<Button key={item} sx={{ color: '#fff' }}>
{item}
</Button>
))}
</Box>
</Toolbar>
</AppBar>
<nav>
<Drawer
container={container}
variant="temporary"
open={mobileOpen}
onClose={handleDrawerToggle}
ModalProps={{
keepMounted: true, // Better open performance on mobile.
}}
sx={{
display: { xs: 'block', sm: 'none' },
'& .MuiDrawer-paper': { boxSizing: 'border-box', width: drawerWidth },
}}
>
{drawer}
</Drawer>
</nav>
<Box component="main" sx={{ p: 3 }}>
<Toolbar />
<Typography>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Similique unde
fugit veniam eius, perspiciatis sunt? Corporis qui ducimus quibusdam,
aliquam dolore excepturi quae. Distinctio enim at eligendi perferendis in
cum quibusdam sed quae, accusantium et aperiam? Quod itaque exercitationem,
at ab sequi qui modi delectus quia corrupti alias distinctio nostrum.
Minima ex dolor modi inventore sapiente necessitatibus aliquam fuga et. Sed
numquam quibusdam at officia sapiente porro maxime corrupti perspiciatis
asperiores, exercitationem eius nostrum consequuntur iure aliquam itaque,
assumenda et! Quibusdam temporibus beatae doloremque voluptatum doloribus
soluta accusamus porro reprehenderit eos inventore facere, fugit, molestiae
ab officiis illo voluptates recusandae. Vel dolor nobis eius, ratione atque
soluta, aliquam fugit qui iste architecto perspiciatis. Nobis, voluptatem!
Cumque, eligendi unde aliquid minus quis sit debitis obcaecati error,
delectus quo eius exercitationem tempore. Delectus sapiente, provident
corporis dolorum quibusdam aut beatae repellendus est labore quisquam
praesentium repudiandae non vel laboriosam quo ab perferendis velit ipsa
deleniti modi! Ipsam, illo quod. Nesciunt commodi nihil corrupti cum non
fugiat praesentium doloremque architecto laborum aliquid. Quae, maxime
recusandae? Eveniet dolore molestiae dicta blanditiis est expedita eius
debitis cupiditate porro sed aspernatur quidem, repellat nihil quasi
praesentium quia eos, quibusdam provident. Incidunt tempore vel placeat
voluptate iure labore, repellendus beatae quia unde est aliquid dolor
molestias libero. Reiciendis similique exercitationem consequatur, nobis
placeat illo laudantium! Enim perferendis nulla soluta magni error,
provident repellat similique cupiditate ipsam, et tempore cumque quod! Qui,
iure suscipit tempora unde rerum autem saepe nisi vel cupiditate iusto.
Illum, corrupti? Fugiat quidem accusantium nulla. Aliquid inventore commodi
reprehenderit rerum reiciendis! Quidem alias repudiandae eaque eveniet
cumque nihil aliquam in expedita, impedit quas ipsum nesciunt ipsa ullam
consequuntur dignissimos numquam at nisi porro a, quaerat rem repellendus.
Voluptates perspiciatis, in pariatur impedit, nam facilis libero dolorem
dolores sunt inventore perferendis, aut sapiente modi nesciunt.
</Typography>
</Box>
</Box>
);
}
A primary searchbar.
import * as React from 'react';
import { styled, alpha } from '@mui/material/styles';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography';
import InputBase from '@mui/material/InputBase';
import Badge from '@mui/material/Badge';
import MenuItem from '@mui/material/MenuItem';
import Menu from '@mui/material/Menu';
import MenuIcon from '@mui/icons-material/Menu';
import SearchIcon from '@mui/icons-material/Search';
import AccountCircle from '@mui/icons-material/AccountCircle';
import MailIcon from '@mui/icons-material/Mail';
import NotificationsIcon from '@mui/icons-material/Notifications';
import MoreIcon from '@mui/icons-material/MoreVert';
const Search = styled('div')(({ theme }) => ({
position: 'relative',
borderRadius: theme.shape.borderRadius,
backgroundColor: alpha(theme.palette.common.white, 0.15),
'&:hover': {
backgroundColor: alpha(theme.palette.common.white, 0.25),
},
marginRight: theme.spacing(2),
marginLeft: 0,
width: '100%',
[theme.breakpoints.up('sm')]: {
marginLeft: theme.spacing(3),
width: 'auto',
},
}));
const SearchIconWrapper = styled('div')(({ theme }) => ({
padding: theme.spacing(0, 2),
height: '100%',
position: 'absolute',
pointerEvents: 'none',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}));
const StyledInputBase = styled(InputBase)(({ theme }) => ({
color: 'inherit',
'& .MuiInputBase-input': {
padding: theme.spacing(1, 1, 1, 0),
// vertical padding + font size from searchIcon
paddingLeft: `calc(1em + ${theme.spacing(4)})`,
transition: theme.transitions.create('width'),
width: '100%',
[theme.breakpoints.up('md')]: {
width: '20ch',
},
},
}));
export default function PrimarySearchAppBar() {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const [mobileMoreAnchorEl, setMobileMoreAnchorEl] =
React.useState<null | HTMLElement>(null);
const isMenuOpen = Boolean(anchorEl);
const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);
const handleProfileMenuOpen = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};
const handleMobileMenuClose = () => {
setMobileMoreAnchorEl(null);
};
const handleMenuClose = () => {
setAnchorEl(null);
handleMobileMenuClose();
};
const handleMobileMenuOpen = (event: React.MouseEvent<HTMLElement>) => {
setMobileMoreAnchorEl(event.currentTarget);
};
const menuId = 'primary-search-account-menu';
const renderMenu = (
<Menu
anchorEl={anchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
id={menuId}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
open={isMenuOpen}
onClose={handleMenuClose}
>
<MenuItem onClick={handleMenuClose}>Profile</MenuItem>
<MenuItem onClick={handleMenuClose}>My account</MenuItem>
</Menu>
);
const mobileMenuId = 'primary-search-account-menu-mobile';
const renderMobileMenu = (
<Menu
anchorEl={mobileMoreAnchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
id={mobileMenuId}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
open={isMobileMenuOpen}
onClose={handleMobileMenuClose}
>
<MenuItem>
<IconButton size="large" aria-label="show 4 new mails" color="inherit">
<Badge badgeContent={4} color="error">
<MailIcon />
</Badge>
</IconButton>
<p>Messages</p>
</MenuItem>
<MenuItem>
<IconButton
size="large"
aria-label="show 17 new notifications"
color="inherit"
>
<Badge badgeContent={17} color="error">
<NotificationsIcon />
</Badge>
</IconButton>
<p>Notifications</p>
</MenuItem>
<MenuItem onClick={handleProfileMenuOpen}>
<IconButton
size="large"
aria-label="account of current user"
aria-controls="primary-search-account-menu"
aria-haspopup="true"
color="inherit"
>
<AccountCircle />
</IconButton>
<p>Profile</p>
</MenuItem>
</Menu>
);
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<Toolbar>
<IconButton
size="large"
edge="start"
color="inherit"
aria-label="open drawer"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<Typography
variant="h6"
noWrap
component="div"
sx={{ display: { xs: 'none', sm: 'block' } }}
>
MUI
</Typography>
<Search>
<SearchIconWrapper>
<SearchIcon />
</SearchIconWrapper>
<StyledInputBase
placeholder="Search…"
inputProps={{ 'aria-label': 'search' }}
/>
</Search>
<Box sx={{ flexGrow: 1 }} />
<Box sx={{ display: { xs: 'none', md: 'flex' } }}>
<IconButton size="large" aria-label="show 4 new mails" color="inherit">
<Badge badgeContent={4} color="error">
<MailIcon />
</Badge>
</IconButton>
<IconButton
size="large"
aria-label="show 17 new notifications"
color="inherit"
>
<Badge badgeContent={17} color="error">
<NotificationsIcon />
</Badge>
</IconButton>
<IconButton
size="large"
edge="end"
aria-label="account of current user"
aria-controls={menuId}
aria-haspopup="true"
onClick={handleProfileMenuOpen}
color="inherit"
>
<AccountCircle />
</IconButton>
</Box>
<Box sx={{ display: { xs: 'flex', md: 'none' } }}>
<IconButton
size="large"
aria-label="show more"
aria-controls={mobileMenuId}
aria-haspopup="true"
onClick={handleMobileMenuOpen}
color="inherit"
>
<MoreIcon />
</IconButton>
</Box>
</Toolbar>
</AppBar>
{renderMobileMenu}
{renderMenu}
</Box>
);
}
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
import MenuIcon from '@mui/icons-material/Menu';
export default function DenseAppBar() {
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<Toolbar variant="dense">
<IconButton edge="start" color="inherit" aria-label="menu" sx={{ mr: 2 }}>
<MenuIcon />
</IconButton>
<Typography variant="h6" color="inherit" component="div">
Photos
</Typography>
</Toolbar>
</AppBar>
</Box>
);
}
A prominent app bar.
import * as React from 'react';
import { styled } from '@mui/material/styles';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography';
import MenuIcon from '@mui/icons-material/Menu';
import SearchIcon from '@mui/icons-material/Search';
import MoreIcon from '@mui/icons-material/MoreVert';
const StyledToolbar = styled(Toolbar)(({ theme }) => ({
alignItems: 'flex-start',
paddingTop: theme.spacing(1),
paddingBottom: theme.spacing(2),
// Override media queries injected by theme.mixins.toolbar
'@media all': {
minHeight: 128,
},
}));
export default function ProminentAppBar() {
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<StyledToolbar>
<IconButton
size="large"
edge="start"
color="inherit"
aria-label="open drawer"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<Typography
variant="h5"
noWrap
component="div"
sx={{ flexGrow: 1, alignSelf: 'flex-end' }}
>
MUI
</Typography>
<IconButton size="large" aria-label="search" color="inherit">
<SearchIcon />
</IconButton>
<IconButton
size="large"
aria-label="display more actions"
edge="end"
color="inherit"
>
<MoreIcon />
</IconButton>
</StyledToolbar>
</AppBar>
</Box>
);
}
import * as React from 'react';
import { styled } from '@mui/material/styles';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import CssBaseline from '@mui/material/CssBaseline';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
import Paper from '@mui/material/Paper';
import Fab from '@mui/material/Fab';
import List from '@mui/material/List';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemAvatar from '@mui/material/ListItemAvatar';
import ListItemText from '@mui/material/ListItemText';
import ListSubheader from '@mui/material/ListSubheader';
import Avatar from '@mui/material/Avatar';
import MenuIcon from '@mui/icons-material/Menu';
import AddIcon from '@mui/icons-material/Add';
import SearchIcon from '@mui/icons-material/Search';
import MoreIcon from '@mui/icons-material/MoreVert';
const messages = [
{
id: 1,
primary: 'Brunch this week?',
secondary: "I'll be in the neighbourhood this week. Let's grab a bite to eat",
person: '/static/images/avatar/5.jpg',
},
{
id: 2,
primary: 'Birthday Gift',
secondary: `Do you have a suggestion for a good present for John on his work
anniversary. I am really confused & would love your thoughts on it.`,
person: '/static/images/avatar/1.jpg',
},
{
id: 3,
primary: 'Recipe to try',
secondary: 'I am try out this new BBQ recipe, I think this might be amazing',
person: '/static/images/avatar/2.jpg',
},
{
id: 4,
primary: 'Yes!',
secondary: 'I have the tickets to the ReactConf for this year.',
person: '/static/images/avatar/3.jpg',
},
{
id: 5,
primary: "Doctor's Appointment",
secondary: 'My appointment for the doctor was rescheduled for next Saturday.',
person: '/static/images/avatar/4.jpg',
},
{
id: 6,
primary: 'Discussion',
secondary: `Menus that are generated by the bottom app bar (such as a bottom
navigation drawer or overflow menu) open as bottom sheets at a higher elevation
than the bar.`,
person: '/static/images/avatar/5.jpg',
},
{
id: 7,
primary: 'Summer BBQ',
secondary: `Who wants to have a cookout this weekend? I just got some furniture
for my backyard and would love to fire up the grill.`,
person: '/static/images/avatar/1.jpg',
},
];
const StyledFab = styled(Fab)({
position: 'absolute',
zIndex: 1,
top: -30,
left: 0,
right: 0,
margin: '0 auto',
});
export default function BottomAppBar() {
return (
<React.Fragment>
<CssBaseline />
<Paper square sx={{ pb: '50px' }}>
<Typography variant="h5" gutterBottom component="div" sx={{ p: 2, pb: 0 }}>
Inbox
</Typography>
<List sx={{ mb: 2 }}>
{messages.map(({ id, primary, secondary, person }) => (
<React.Fragment key={id}>
{id === 1 && (
<ListSubheader sx={{ bgcolor: 'background.paper' }}>
Today
</ListSubheader>
)}
{id === 3 && (
<ListSubheader sx={{ bgcolor: 'background.paper' }}>
Yesterday
</ListSubheader>
)}
<ListItemButton>
<ListItemAvatar>
<Avatar alt="Profile Picture" src={person} />
</ListItemAvatar>
<ListItemText primary={primary} secondary={secondary} />
</ListItemButton>
</React.Fragment>
))}
</List>
</Paper>
<AppBar position="fixed" color="primary" sx={{ top: 'auto', bottom: 0 }}>
<Toolbar>
<IconButton color="inherit" aria-label="open drawer">
<MenuIcon />
</IconButton>
<StyledFab color="secondary" aria-label="add">
<AddIcon />
</StyledFab>
<Box sx={{ flexGrow: 1 }} />
<IconButton color="inherit">
<SearchIcon />
</IconButton>
<IconButton color="inherit">
<MoreIcon />
</IconButton>
</Toolbar>
</AppBar>
</React.Fragment>
);
}
When you render the app bar position fixed, the dimension of the element doesn’t impact the rest of the page. This can cause some part of your content to be invisible, behind the app bar. Here are 3 possible solutions:
position="sticky"
instead of fixed.<Toolbar />
component:function App() {
return (
<React.Fragment>
<AppBar position="fixed">
<Toolbar>{/* content */}</Toolbar>
</AppBar>
<Toolbar />
</React.Fragment>
);
}
theme.mixins.toolbar
CSS:const Offset = styled('div')(({ theme }) => theme.mixins.toolbar);
function App() {
return (
<React.Fragment>
<AppBar position="fixed">
<Toolbar>{/* content */}</Toolbar>
</AppBar>
<Offset />
</React.Fragment>
);
}
You can use the useScrollTrigger()
hook to respond to user scroll actions.
The app bar hides on scroll down to leave more space for reading.
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import CssBaseline from '@mui/material/CssBaseline';
import useScrollTrigger from '@mui/material/useScrollTrigger';
import Box from '@mui/material/Box';
import Container from '@mui/material/Container';
import Slide from '@mui/material/Slide';
interface Props {
/**
* Injected by the documentation to work in an iframe.
* You won't need it on your project.
*/
window?: () => Window;
children?: React.ReactElement<unknown>;
}
function HideOnScroll(props: Props) {
const { children, window } = props;
// Note that you normally won't need to set the window ref as useScrollTrigger
// will default to window.
// This is only being set here because the demo is in an iframe.
const trigger = useScrollTrigger({
target: window ? window() : undefined,
});
return (
<Slide appear={false} direction="down" in={!trigger}>
{children ?? <div />}
</Slide>
);
}
export default function HideAppBar(props: Props) {
return (
<React.Fragment>
<CssBaseline />
<HideOnScroll {...props}>
<AppBar>
<Toolbar>
<Typography variant="h6" component="div">
Scroll to hide App bar
</Typography>
</Toolbar>
</AppBar>
</HideOnScroll>
<Toolbar />
<Container>
<Box sx={{ my: 2 }}>
{[...new Array(12)]
.map(
() => `Cras mattis consectetur purus sit amet fermentum.
Cras justo odio, dapibus ac facilisis in, egestas eget quam.
Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
Praesent commodo cursus magna, vel scelerisque nisl consectetur et.`,
)
.join('\n')}
</Box>
</Container>
</React.Fragment>
);
}
The app bar elevates on scroll to communicate that the user is not at the top of the page.
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import CssBaseline from '@mui/material/CssBaseline';
import useScrollTrigger from '@mui/material/useScrollTrigger';
import Box from '@mui/material/Box';
import Container from '@mui/material/Container';
interface Props {
/**
* Injected by the documentation to work in an iframe.
* You won't need it on your project.
*/
window?: () => Window;
children?: React.ReactElement<{ elevation?: number }>;
}
function ElevationScroll(props: Props) {
const { children, window } = props;
// Note that you normally won't need to set the window ref as useScrollTrigger
// will default to window.
// This is only being set here because the demo is in an iframe.
const trigger = useScrollTrigger({
disableHysteresis: true,
threshold: 0,
target: window ? window() : undefined,
});
return children
? React.cloneElement(children, {
elevation: trigger ? 4 : 0,
})
: null;
}
export default function ElevateAppBar(props: Props) {
return (
<React.Fragment>
<CssBaseline />
<ElevationScroll {...props}>
<AppBar>
<Toolbar>
<Typography variant="h6" component="div">
Scroll to elevate App bar
</Typography>
</Toolbar>
</AppBar>
</ElevationScroll>
<Toolbar />
<Container>
<Box sx={{ my: 2 }}>
{[...new Array(12)]
.map(
() => `Cras mattis consectetur purus sit amet fermentum.
Cras justo odio, dapibus ac facilisis in, egestas eget quam.
Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
Praesent commodo cursus magna, vel scelerisque nisl consectetur et.`,
)
.join('\n')}
</Box>
</Container>
</React.Fragment>
);
}
A floating action button appears on scroll to make it easy to get back to the top of the page.
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import CssBaseline from '@mui/material/CssBaseline';
import useScrollTrigger from '@mui/material/useScrollTrigger';
import Box from '@mui/material/Box';
import Container from '@mui/material/Container';
import Fab from '@mui/material/Fab';
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
import Fade from '@mui/material/Fade';
interface Props {
/**
* Injected by the documentation to work in an iframe.
* You won't need it on your project.
*/
window?: () => Window;
children?: React.ReactElement<unknown>;
}
function ScrollTop(props: Props) {
const { children, window } = props;
// Note that you normally won't need to set the window ref as useScrollTrigger
// will default to window.
// This is only being set here because the demo is in an iframe.
const trigger = useScrollTrigger({
target: window ? window() : undefined,
disableHysteresis: true,
threshold: 100,
});
const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
const anchor = (
(event.target as HTMLDivElement).ownerDocument || document
).querySelector('#back-to-top-anchor');
if (anchor) {
anchor.scrollIntoView({
block: 'center',
});
}
};
return (
<Fade in={trigger}>
<Box
onClick={handleClick}
role="presentation"
sx={{ position: 'fixed', bottom: 16, right: 16 }}
>
{children}
</Box>
</Fade>
);
}
export default function BackToTop(props: Props) {
return (
<React.Fragment>
<CssBaseline />
<AppBar>
<Toolbar>
<Typography variant="h6" component="div">
Scroll to see button
</Typography>
</Toolbar>
</AppBar>
<Toolbar id="back-to-top-anchor" />
<Container>
<Box sx={{ my: 2 }}>
{[...new Array(12)]
.map(
() => `Cras mattis consectetur purus sit amet fermentum.
Cras justo odio, dapibus ac facilisis in, egestas eget quam.
Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
Praesent commodo cursus magna, vel scelerisque nisl consectetur et.`,
)
.join('\n')}
</Box>
</Container>
<ScrollTop {...props}>
<Fab size="small" aria-label="scroll back to top">
<KeyboardArrowUpIcon />
</Fab>
</ScrollTop>
</React.Fragment>
);
}
useScrollTrigger([options]) => trigger
options
(object [optional]):
options.disableHysteresis
(bool [optional]): Defaults to false
. Disable the hysteresis. Ignore the scroll direction when determining the trigger
value.options.target
(Node [optional]): Defaults to window
.options.threshold
(number [optional]): Defaults to 100
. Change the trigger
value when the vertical scroll strictly crosses this threshold (exclusive).trigger
: Does the scroll position match the criteria?
import useScrollTrigger from '@mui/material/useScrollTrigger';
function HideOnScroll(props) {
const trigger = useScrollTrigger();
return (
<Slide in={!trigger}>
<div>Hello</div>
</Slide>
);
}
Following the Material Design guidelines, the color
prop has no effect on the appearance of the app bar in dark mode.
You can override this behavior by setting the enableColorOnDark
prop to true
.
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Stack from '@mui/material/Stack';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
import MenuIcon from '@mui/icons-material/Menu';
import { ThemeProvider, createTheme } from '@mui/material/styles';
function appBarLabel(label: string) {
return (
<Toolbar>
<IconButton edge="start" color="inherit" aria-label="menu" sx={{ mr: 2 }}>
<MenuIcon />
</IconButton>
<Typography variant="h6" noWrap component="div" sx={{ flexGrow: 1 }}>
{label}
</Typography>
</Toolbar>
);
}
const darkTheme = createTheme({
palette: {
mode: 'dark',
primary: {
main: '#1976d2',
},
},
});
export default function EnableColorOnDarkAppBar() {
return (
<Stack spacing={2} sx={{ flexGrow: 1 }}>
<ThemeProvider theme={darkTheme}>
<AppBar position="static" color="primary" enableColorOnDark>
{appBarLabel('enableColorOnDark')}
</AppBar>
<AppBar position="static" color="primary">
{appBarLabel('default')}
</AppBar>
</ThemeProvider>
</Stack>
);
}
The DashboardLayout component from @toolpad/core
is the starting point for dashboarding applications. It takes care of application layout, theming, navigation, and more. An example usage of this component:
import * as React from 'react';
import { extendTheme, styled } from '@mui/material/styles';
import DashboardIcon from '@mui/icons-material/Dashboard';
import ShoppingCartIcon from '@mui/icons-material/ShoppingCart';
import BarChartIcon from '@mui/icons-material/BarChart';
import DescriptionIcon from '@mui/icons-material/Description';
import LayersIcon from '@mui/icons-material/Layers';
import { AppProvider, Navigation, Router } from '@toolpad/core/AppProvider';
import { DashboardLayout } from '@toolpad/core/DashboardLayout';
import { PageContainer } from '@toolpad/core/PageContainer';
import Grid from '@mui/material/Grid2';
const NAVIGATION: Navigation = [
{
kind: 'header',
title: 'Main items',
},
{
segment: 'dashboard',
title: 'Dashboard',
icon: <DashboardIcon />,
},
{
segment: 'orders',
title: 'Orders',
icon: <ShoppingCartIcon />,
},
{
kind: 'divider',
},
{
kind: 'header',
title: 'Analytics',
},
{
segment: 'reports',
title: 'Reports',
icon: <BarChartIcon />,
children: [
{
segment: 'sales',
title: 'Sales',
icon: <DescriptionIcon />,
},
{
segment: 'traffic',
title: 'Traffic',
icon: <DescriptionIcon />,
},
],
},
{
segment: 'integrations',
title: 'Integrations',
icon: <LayersIcon />,
},
];
const demoTheme = extendTheme({
colorSchemes: { light: true, dark: true },
colorSchemeSelector: 'class',
breakpoints: {
values: {
xs: 0,
sm: 600,
md: 600,
lg: 1200,
xl: 1536,
},
},
});
function useDemoRouter(initialPath: string): Router {
const [pathname, setPathname] = React.useState(initialPath);
const router = React.useMemo(() => {
return {
pathname,
searchParams: new URLSearchParams(),
navigate: (path: string | URL) => setPathname(String(path)),
};
}, [pathname]);
return router;
}
const Skeleton = styled('div')<{ height: number }>(({ theme, height }) => ({
backgroundColor: theme.palette.action.hover,
borderRadius: theme.shape.borderRadius,
height,
content: '" "',
}));
export default function DashboardLayoutBasic(props: any) {
const { window } = props;
const router = useDemoRouter('/dashboard');
// Remove this const when copying and pasting into your project.
const demoWindow = window ? window() : undefined;
return (
<AppProvider
navigation={NAVIGATION}
router={router}
theme={demoTheme}
window={demoWindow}
>
<DashboardLayout>
<PageContainer>
<Grid container spacing={1}>
<Grid size={5} />
<Grid size={12}>
<Skeleton height={14} />
</Grid>
<Grid size={12}>
<Skeleton height={14} />
</Grid>
<Grid size={4}>
<Skeleton height={100} />
</Grid>
<Grid size={8}>
<Skeleton height={100} />
</Grid>
<Grid size={12}>
<Skeleton height={150} />
</Grid>
<Grid size={12}>
<Skeleton height={14} />
</Grid>
<Grid size={3}>
<Skeleton height={100} />
</Grid>
<Grid size={3}>
<Skeleton height={100} />
</Grid>
<Grid size={3}>
<Skeleton height={100} />
</Grid>
<Grid size={3}>
<Skeleton height={100} />
</Grid>
</Grid>
</PageContainer>
</DashboardLayout>
</AppProvider>
);
}