AppShell

Responsive shell for your application with header and navbar
Import

Usage

AppShell is a layout component that can be used to create a common Header - Navbar - Content layout pattern. AppShell, Header and Navbar components include bare minimum default styles to simplify customization.

Your application goes here
import { AppShell, Navbar, Header } from '@mantine/core';
function Demo() {
return (
<AppShell
padding="md"
navbar={<Navbar width={{ base: 300 }} height={500} padding="xs">{/* Navbar content */}</Navbar>}
header={<Header height={60} padding="xs">{/* Header content */}</Header>}
styles={(theme) => ({
main: { backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[8] : theme.colors.gray[0] },
})}
>
{/* Your application here */}
</AppShell>
);
}

Responsive styles

Open responsive example in new tab
import { useState } from 'react';
import { AppShell, Burger, Header, MediaQuery, Navbar, Text, useMantineTheme } from '@mantine/core';
function Demo() {
const [opened, setOpened] = useState(false);
const theme = useMantineTheme();
return (
<AppShell
// navbarOffsetBreakpoint controls when navbar should no longer be offset with padding-left
navbarOffsetBreakpoint="sm"
// fixed prop on AppShell will be automatically added to Header and Navbar
fixed
navbar={
<Navbar
padding="md"
// Breakpoint at which navbar will be hidden if hidden prop is true
hiddenBreakpoint="sm"
// Hides navbar when viewport size is less than value specified in hiddenBreakpoint
hidden={!opened}
// when viewport size is less than theme.breakpoints.sm navbar width is 100%
// viewport size > theme.breakpoints.sm – width is 300px
// viewport size > theme.breakpoints.lg – width is 400px
width={{ sm: 300, lg: 400 }}
>
<Text>Application navbar</Text>
</Navbar>
}
header={
<Header height={70} padding="md">
{/* Handle other responsive styles with MediaQuery component or createStyles function */}
<div style={{ display: 'flex', alignItems: 'center', height: '100%' }}>
<MediaQuery largerThan="sm" styles={{ display: 'none' }}>
<Burger
opened={opened}
onClick={() => setOpened((o) => !o)}
size="sm"
color={theme.colors.gray[6]}
mr="xl"
/>
</MediaQuery>
<Text>Application header</Text>
</div>
</Header>
}
>
<Text>Resize app to see responsive navbar in action</Text>
</AppShell>
);
}

Navbar component

Navbar can be used outside of AppShell context:

<Navbar height={600} padding="xs" width={{ base: 300 }}>
<Navbar.Section><Brand /></Navbar.Section>
<Navbar.Section grow mt="lg"><MainLinks /></Navbar.Section>
<Navbar.Section><User /></Navbar.Section>
</Navbar>

Navbar.Section

<Navbar>
{/* First section with normal height (depends on section content) */}
<Navbar.Section>First section</Navbar.Section>
{/* Grow section will take all available space that is not taken by first and last sections */}
<Navbar.Section grow>Grow section</Navbar.Section>
{/* Last section with normal height (depends on section content) */}
<Navbar.Section>Last section</Navbar.Section>
</Navbar>

Responsive width

<Navbar
width={{
// Base width – used when viewport is larger than theme.breakpoints.lg
base: 400,
breakpoints: {
// When viewport is smaller than theme.breakpoints.lg and larger than theme.breakpoints.sm
lg: 300,
// When viewport is smaller than theme.breakpoints.sm
sm: '100%',
},
}}
/>

Fixed position

To make Navbar fixed (like in Mantine docs) set fixed and position props:

<Navbar fixed position={{ top: 0, left: 0 }} />

Navbar with custom scrollbars

Navbar.Section can be used with ScrollArea component:

import { Navbar, ScrollArea } from '@mantine/core';
function Demo() {
return (
<Navbar height={600} padding={10} width={{ base: 300 }}>
<Navbar.Section mt="xs"><Brand /></Navbar.Section>
<Navbar.Section
grow
component={ScrollArea}
ml={-10}
mr={-10}
sx={{ paddingLeft: 10, paddingRight: 10 }}
>
{/* scrollable content here */}
</Navbar.Section>
<Navbar.Section><User /></Navbar.Section>
</Navbar>
);
}

Wrapping Navbar and Header components

AppShell component requires Navbar and Header components to be direct children at navbar and header props. In addition, width and height need to be explicitly set on the wrapping Navbar or Header element respectively. To use custom components instead of Navbar or Header:

import { AppShell, HeaderProps, Navbar, NavbarProps } from '@mantine/core';
function CustomNavbar(props: Omit<NavbarProps, 'children'>) {
return <Navbar {...props}>Custom navbar</Navbar>;
}
function CustomHeader(props: Omit<HeaderProps, 'children'>) {
return <Header {...props}>Custom header</Header>;
}
function App() {
return (
<AppShell
navbar={<CustomNavbar width={{ base: 300 }} height={500} padding="xs" />}
header={<CustomHeader height={70} padding="xs" />}
>
App content
</AppShell>
);
}

Semantic elements

  • Both Header and Navbar components root element is nav
  • AppShell wraps content with main tag – !important do not use main tag inside AppShell
Build fully functional accessible web applications faster than ever
Feedback
Your feedback is most valuable contribution to the project, please share how you use Mantine, what features are missing and what is done good
Leave feedback