Appshell

Appshell is a mega layout component that aims to manage:

  • The banner, also called header, that appears at the top.
  • The navbar, that appears at a side, or one navbar and one sidebar, appearing on each side.
  • The main section, that appears below the banner and is surrounded by the sidebars, if any.

header: Appshell.Header

The app's banner that stands ontop. It may manage:

  • the burger button
  • the logo
  • the dark mode / light mode toggle

configure the header

We build a header config object and provide it to the AppShell header prop.

It is common to configure the height.

header={{ height: 70 }}

navbar: Appshell.Navbar

manages the left-side navbar.

  • On mobile, the navbar starts in a hidden state. We control the navbar display with a boolean state variable, that we plug into the collapsed prop. We toggle this boolean state with a burger button.
  • We scope such behaviour to mobile only by specifying the mobile property in collapsed. We provide a breakpoint from which the collapse property is no longer used. Similarly, we provide a hiddenFrom prop to the Burger button to ensure it disappear at the same break point.
const [mobileOpened, { toggle: toggleMobile }] = useDisclosure();

  return (
    <AppShell
      // ..
      navbar={{
				// ..
        collapsed: { mobile: !opened },
        breakpoint: 'sm',
      }}
    >
      <AppShell.Header>
        <Burger
          opened={opened}
          onClick={toggle}
          hiddenFrom="sm"
        />

navbar: allow toggling on desktop

We may allow the toggling behaviour in Desktop as well. In that case, we create two distinct boolean state variables, and use the desktop property in collapsed. But we need two distinct burgers, and desktop burger may become a static button that never shows a close icon.

const [mobileOpened, { toggle: toggleMobile }] = useDisclosure(false);
const [desktopOpened, { toggle: toggleDesktop }] = useDisclosure(true);

  return (
    <AppShell
      // ..
      navbar={{
				// ..
        collapsed: { mobile: !mobileOpened, desktop: !desktopOpened },
        breakpoint: 'sm',
      }}
    >
      <AppShell.Header>
        /* mobile burger */
				<Burger opened={mobileOpened} onClick={toggleMobile} hiddenFrom="sm"/>
        /* desktop burger */
				<Burger opened={false} onClick={toggleDesktop} visibleFrom="sm"/>

navbar: config

We provide the config object to the navbar prop of AppShell

navbar={{ width: 300, breakpoint: 'sm', collapsed: { mobile: !opened } }}
  • We may specify the bar width, using a raw value or an object with responsive values. It's only used in desktop, as the navbar is full screen in mobile.
  • breakpoint: when to use the mobile opened state versus the desktop opened state.
  • the collapsed prop to receive the boolean states.

navbar: implement top and bottom sections

We split the navbar into AppShell.Sections.

<AppShell.Navbar>
    <AppShell.Section grow> </AppShell.Section>
    <AppShell.Section> </AppShell.Section>
</AppShell.Navbar>

Appshell.Main

The container for the main panel. It's appropriate to set the main panel's background color here.

For light mode, the background is white.

We may pick a light gray such as gray.1, to allow white Papers to standout.

For dark mode, the background is dark.7???

<AppShell.Main bg={colorScheme === "dark" ? "dark.8" : "gray.1"}>{children}</AppShell.Main>

Configure subcomponents at Appshell level

the configuration object is required for each subcomponent.

<AppShell
      header={{ .. }}
      navbar={{ .. }}
      padding="md"
>..subcomponents..</AppShell>

Subcomponents, as children

AppShell.Header
AppShell.Navbar
AppShell.Main

related components

Burger
useDisclosure
earlymorning logo

© 2025 - All rights reserved

Appshell

Appshell is a mega layout component that aims to manage:

  • The banner, also called header, that appears at the top.
  • The navbar, that appears at a side, or one navbar and one sidebar, appearing on each side.
  • The main section, that appears below the banner and is surrounded by the sidebars, if any.

header: Appshell.Header

The app's banner that stands ontop. It may manage:

  • the burger button
  • the logo
  • the dark mode / light mode toggle

configure the header

We build a header config object and provide it to the AppShell header prop.

It is common to configure the height.

header={{ height: 70 }}

navbar: Appshell.Navbar

manages the left-side navbar.

  • On mobile, the navbar starts in a hidden state. We control the navbar display with a boolean state variable, that we plug into the collapsed prop. We toggle this boolean state with a burger button.
  • We scope such behaviour to mobile only by specifying the mobile property in collapsed. We provide a breakpoint from which the collapse property is no longer used. Similarly, we provide a hiddenFrom prop to the Burger button to ensure it disappear at the same break point.
const [mobileOpened, { toggle: toggleMobile }] = useDisclosure();

  return (
    <AppShell
      // ..
      navbar={{
				// ..
        collapsed: { mobile: !opened },
        breakpoint: 'sm',
      }}
    >
      <AppShell.Header>
        <Burger
          opened={opened}
          onClick={toggle}
          hiddenFrom="sm"
        />

navbar: allow toggling on desktop

We may allow the toggling behaviour in Desktop as well. In that case, we create two distinct boolean state variables, and use the desktop property in collapsed. But we need two distinct burgers, and desktop burger may become a static button that never shows a close icon.

const [mobileOpened, { toggle: toggleMobile }] = useDisclosure(false);
const [desktopOpened, { toggle: toggleDesktop }] = useDisclosure(true);

  return (
    <AppShell
      // ..
      navbar={{
				// ..
        collapsed: { mobile: !mobileOpened, desktop: !desktopOpened },
        breakpoint: 'sm',
      }}
    >
      <AppShell.Header>
        /* mobile burger */
				<Burger opened={mobileOpened} onClick={toggleMobile} hiddenFrom="sm"/>
        /* desktop burger */
				<Burger opened={false} onClick={toggleDesktop} visibleFrom="sm"/>

navbar: config

We provide the config object to the navbar prop of AppShell

navbar={{ width: 300, breakpoint: 'sm', collapsed: { mobile: !opened } }}
  • We may specify the bar width, using a raw value or an object with responsive values. It's only used in desktop, as the navbar is full screen in mobile.
  • breakpoint: when to use the mobile opened state versus the desktop opened state.
  • the collapsed prop to receive the boolean states.

navbar: implement top and bottom sections

We split the navbar into AppShell.Sections.

<AppShell.Navbar>
    <AppShell.Section grow> </AppShell.Section>
    <AppShell.Section> </AppShell.Section>
</AppShell.Navbar>

Appshell.Main

The container for the main panel. It's appropriate to set the main panel's background color here.

For light mode, the background is white.

We may pick a light gray such as gray.1, to allow white Papers to standout.

For dark mode, the background is dark.7???

<AppShell.Main bg={colorScheme === "dark" ? "dark.8" : "gray.1"}>{children}</AppShell.Main>

Configure subcomponents at Appshell level

the configuration object is required for each subcomponent.

<AppShell
      header={{ .. }}
      navbar={{ .. }}
      padding="md"
>..subcomponents..</AppShell>

Subcomponents, as children

AppShell.Header
AppShell.Navbar
AppShell.Main

related components

Burger
useDisclosure