# Sidebar Navigation
> A highly composable, hierarchical, vertical side navigation component.

## Import

```js
import { SidebarNavigation } from '@gemini-suite/vera-react';

// Optional hook
import { useSidebarNavigationContext } from '@gemini-suite/vera-react';

// Optional set of variables
import {
  SIDEBAR_NAVIGATION_MEDIUM_WIDTH_EXPANDED,
  SIDEBAR_NAVIGATION_MEDIUM_WIDTH_COLLAPSED,
  SIDEBAR_NAVIGATION_SMALL_WIDTH_EXPANDED,
  SIDEBAR_NAVIGATION_SMALL_WIDTH_COLLAPSED
} from '@gemini-suite/vera-react';
```

Sidebar Navigation is a compound component that consists of multiple parts to help you create different kinds of navigation.

- `SidebarNavigation.Root`: The wrapper that contains all the parts of a navigation and provides context for its children.
- `SidebarNavigation.Header`: The header of the navigation used to render components such as [Logo](/components/logo) and `SidebarNavigation.AppTitle`.
- `SidebarNavigation.AppTitle`: Wrapper for the app title.
- `SidebarNavigation.Body`: The scrollable body of the navigation. Used to render sections of navigation items.
- `SidebarNavigation.Section`: Signifies a segment of the navigation.
- `SidebarNavigation.Items`: Container for the navigation items.
- `SidebarNavigation.Item`: An individual navigation item. Each item is a link or action a user can take.
- `SidebarNavigation.ItemLabel`: An additional descriptor for navigation item. It renders [Label](/components/label) in expanded state and switches to [Hint Dot](/components/hint-dot) in collapsed state.
- `SidebarNavigation.Group`: An expandable grouping of nested `SidebarNavigation.Item`s.
- `SidebarNavigation.Footer`: The persistent footer at the bottom of the navigation. Typically used to render user-related items.
- `SidebarNavigation.Toggle`: The button that toggles between expanded and collapsed states of the navigation.

## Examples

<Callout variant="tip">

Examples below include `maxHeight: 60vh` CSS rule, to ensure optimal docs-browsing experience.
It should not be added in a real app environment.

Due to some limitations of the playground environment, it's recommended to [browse fullscreen examples in Storybook](https://next--698f15fa99e7b146f9002f64.chromatic.com/?path=/story/components-sidebarnavigation).

</Callout>

### Default

**Sidebar Navigation** is commonly used to display the primary navigation in an application with [sidebar-based layout](/UX-patterns/framework/app-layouts#sidebar-based-layout).
The navigation items should represent different areas of your application, except for the footer part which is typically used for user actions such as logout. You can nest navigation items within sections and collapsible groups, to create logical grouping of navigation items.

- To provide the structure for the navigation component, including the actual sidebar use the [App Frame](/components/app-frame) or [App Frame With Sidebar](/components/app-frame-with-sidebar) components.
- `SidebarNavigation.Item` must be used inside `SidebarNavigation.Items`.
- `SidebarNavigation.Item` requires both label and icon (or custom visual) due to the visual style of the collapsed state.
- Nesting `SidebarNavigation.Group` inside `SidebarNavigation.Group` is not supported.
- Use `isActive` property on `SidebarNavigation.Item` to indicate that the item represents the current page. The item will be highlighted and scrolled into view. If the item is within `SidebarNavigation.Group`, the group will automatically open.
- If navigation items have too long labels, they truncate. The full label is revealed via a [Tooltip](/components/tooltip). However, it’s best to avoid long labels: keep them succinct and scannable.
- `SidebarNavigation.Body` can vertically scroll for longer navigation lists. Order items by importance, so that the higher priority items are visible without scrolling.

The example below shows all components composed together.

```jsx
<AppFrameWithSidebar.Root css={{ isolation: 'isolate', maxHeight: '60vh' }}>
  <AppFrameWithSidebar.Header
    paddingY="spacingM"
    paddingX={{ '@initial': 'spacingM', '@mqLargeAndUp': 'spacingL' }}
  >
    <Heading variant="delta" margin="none" overflowStrategy="truncate">
      {'View title'}
    </Heading>
  </AppFrameWithSidebar.Header>
  <AppFrameWithSidebar.Sidebar>
    <SidebarNavigation.Root aria-label="Main navigation" withSeparator>
      <SidebarNavigation.Header>
        <Logo variant="icon" label="Gemini Suite logo" />
        <SidebarNavigation.AppTitle>
          {'Product name'}
        </SidebarNavigation.AppTitle>
      </SidebarNavigation.Header>
      <SidebarNavigation.Body>
        <SidebarNavigation.Section title="Section name">
          <SidebarNavigation.Items>
            <SidebarNavigation.Item iconName="home" label="Dashboard" />
            <SidebarNavigation.Item
              iconName="creditCard"
              label="Very very long navigation item"
              trailingVisual={<SidebarNavigation.ItemLabel color="info" />}
            />
            <SidebarNavigation.Group iconName="cases" label="Group item">
              <SidebarNavigation.Item iconName="download" label="Sub item 1" />
              <SidebarNavigation.Item iconName="download" label="Sub item 2" />
            </SidebarNavigation.Group>
          </SidebarNavigation.Items>
        </SidebarNavigation.Section>
        <SidebarNavigation.Section title="Other Section">
          <SidebarNavigation.Items>
            <SidebarNavigation.Item
              iconName="shield"
              label="Navigation item"
              trailingVisual={
                <SidebarNavigation.ItemLabel color="danger">
                  {'54'}
                </SidebarNavigation.ItemLabel>
              }
            />
            <SidebarNavigation.Item
              iconName="themeMap"
              isDisabled
              label="Disabled navigation item"
            />
          </SidebarNavigation.Items>
        </SidebarNavigation.Section>
      </SidebarNavigation.Body>
      <SidebarNavigation.Footer>
        <SidebarNavigation.Section title="Footer section">
          <SidebarNavigation.Items>
            <SidebarNavigation.Item iconName="settings" label="Footer item" />
            <Menu.Root>
              <SidebarNavigation.Item
                as={Menu.Trigger}
                leadingVisual={
                  <Avatar.Root of="Torvald Halvor" size="small">
                    <Avatar.Initials />
                  </Avatar.Root>
                }
                label="Torvald Halvor"
              />
              <Menu.Content
                placement={Placement.TOP_LEFT}
                css={{
                  maxWidth: `calc(${SIDEBAR_NAVIGATION_MEDIUM_WIDTH_EXPANDED} - 1rem)`
                }}
              >
                <Flex gap="spacingM" padding="spacingS">
                  <Avatar.Root of="Torvald Halvor">
                    <Avatar.Initials />
                  </Avatar.Root>
                  <FlexItem shrinkPastContentSize>
                    {'Torvald Halvor'}
                    <Text
                      overflowStrategy="truncate"
                      as="div"
                      variant="zeta"
                      color="foregroundNeutralSubtle"
                    >
                      {'torvald.halvor@invera-tech.com'}
                    </Text>
                  </FlexItem>
                </Flex>
                <Menu.Separator />
                <Menu.Item startElement={<SvgIcon iconName="user" />}>
                  {'Manage account'}
                </Menu.Item>
                <Menu.Separator />
                <Menu.Item
                  intent="danger"
                  onSelect={() => {
                    alert('Log Out');
                  }}
                >
                  {'Log Out'}
                </Menu.Item>
              </Menu.Content>
            </Menu.Root>
          </SidebarNavigation.Items>
        </SidebarNavigation.Section>
      </SidebarNavigation.Footer>
      <SidebarNavigation.Toggle label="Toggle panel" />
    </SidebarNavigation.Root>
  </AppFrameWithSidebar.Sidebar>
  <AppFrameWithSidebar.Main
    padding={{
      '@initial': 'spacingM',
      '@mqLargeAndUp': 'spacingL'
    }}
    css={{
      display: 'grid',
      placeItems: 'center'
    }}
  >
    <Text color="foregroundNeutralModerate">{'Main content'}</Text>
  </AppFrameWithSidebar.Main>
</AppFrameWithSidebar.Root>
```

### With content overlap

By default, when you expand the sidebar navigation, it pushes app contents so that it's always visible.
In certain type of applications, for example where the entire viewport is a map canvas, you may want the sidebar navigation to slide over the map in its expanded state.
To do so, set `mode` property to `overlayContent`.

It's also recommended to set the `toggleOnHover` property, so that it's possible to toggle the sidebar navigation state with a convenient hover interaction.
Hover interaction will be enabled only for users whose primary input device is capable of hovering. Otherwise (i.e. touchscreen device) the component will fallback to show `SidebarNavigation.Toggle` at the bottom of the navigation panel.

```jsx
() => {
  const [userMenuContent, setUserMenuContent] = React.useState(null);

  return (
    <AppFrameWithSidebar.Root
      css={{
        // the following rules are added only to make the demo work in the playground
        // you shouldn't include them in your app
        isolation: 'isolate',
        position: 'relative',
        maxHeight: '60vh'
      }}
    >
      <AppFrameWithSidebar.Sidebar>
        <SidebarNavigation.Root
          aria-label="Main navigation"
          elevation="l"
          toggleOnHover
          mode="overlayContent"
          hoverArea={userMenuContent}
          css={{
            // the following override is added only to make the demo
            // work in the playground
            position: 'absolute'
          }}
        >
          <SidebarNavigation.Header>
            <Logo variant="icon" label="Gemini Suite logo" />
            <SidebarNavigation.AppTitle>
              {'Product name'}
            </SidebarNavigation.AppTitle>
          </SidebarNavigation.Header>
          <SidebarNavigation.Body>
            <SidebarNavigation.Items>
              <SidebarNavigation.Item iconName="home" label="Dashboard" />
              <SidebarNavigation.Item
                iconName="creditCard"
                label="Very very long navigation item"
                trailingVisual={<SidebarNavigation.ItemLabel color="info" />}
              />
              <SidebarNavigation.Group iconName="cases" label="Group item">
                <SidebarNavigation.Item
                  iconName="download"
                  label="Sub item 1"
                />
                <SidebarNavigation.Item
                  iconName="download"
                  label="Sub item 2"
                />
              </SidebarNavigation.Group>
            </SidebarNavigation.Items>
          </SidebarNavigation.Body>
          <SidebarNavigation.Footer>
            <SidebarNavigation.Section title="Footer section">
              <SidebarNavigation.Items>
                <SidebarNavigation.Item
                  iconName="settings"
                  label="Footer item"
                />
                <Menu.Root>
                  <SidebarNavigation.Item
                    as={Menu.Trigger}
                    leadingVisual={
                      <Avatar.Root of="Torvald Halvor" size="small">
                        <Avatar.Initials />
                      </Avatar.Root>
                    }
                    label="Torvald Halvor"
                  />
                  <Menu.Content
                    ref={setUserMenuContent}
                    placement={Placement.TOP_LEFT}
                    css={{
                      maxWidth: `calc(${SIDEBAR_NAVIGATION_MEDIUM_WIDTH_EXPANDED} - 1rem)`
                    }}
                  >
                    <Flex gap="spacingM" padding="spacingS">
                      <Avatar.Root of="Torvald Halvor">
                        <Avatar.Initials />
                      </Avatar.Root>
                      <FlexItem shrinkPastContentSize>
                        {'Torvald Halvor'}
                        <Text
                          overflowStrategy="truncate"
                          as="div"
                          variant="zeta"
                          color="foregroundNeutralSubtle"
                        >
                          {'torvald.halvor@invera-tech.com'}
                        </Text>
                      </FlexItem>
                    </Flex>
                    <Menu.Separator />
                    <Menu.Item startElement={<SvgIcon iconName="user" />}>
                      {'Manage account'}
                    </Menu.Item>
                    <Menu.Separator />
                    <Menu.Item
                      intent="danger"
                      onSelect={() => {
                        alert('Log Out');
                      }}
                    >
                      {'Log Out'}
                    </Menu.Item>
                  </Menu.Content>
                </Menu.Root>
              </SidebarNavigation.Items>
            </SidebarNavigation.Section>
          </SidebarNavigation.Footer>
          <SidebarNavigation.Toggle label="Toggle panel" />
        </SidebarNavigation.Root>
      </AppFrameWithSidebar.Sidebar>
      <AppFrameWithSidebar.Main
        padding={{
          '@initial': 'spacingM',
          '@mqLargeAndUp': 'spacingL'
        }}
        background="neutralSubtle"
        css={{
          display: 'grid',
          placeItems: 'center'
        }}
      >
        <Text color="foregroundNeutralModerate">{'Map content'}</Text>
      </AppFrameWithSidebar.Main>
    </AppFrameWithSidebar.Root>
  );
};
```

### Small size

**Sidebar navigation** is also available in `small` size for data-heavy or complex applications where increased density improves the user experience.

<Card
  href="https://next--698f15fa99e7b146f9002f64.chromatic.com/?path=/story/components-sidebarnavigation--small"
  title="See complete example in Storybook"
  actionIcon="externalLink"
/>

```jsx
<AppFrameWithSidebar.Root css={{ isolation: 'isolate', maxHeight: '60vh' }}>
  <AppFrameWithSidebar.Header
    size="small"
    paddingY="spacingS"
    paddingX="spacingM"
  >
    <Heading variant="epsilon" margin="none" overflowStrategy="truncate">
      {'View title'}
    </Heading>
  </AppFrameWithSidebar.Header>
  <AppFrameWithSidebar.Sidebar>
    <SidebarNavigation.Root
      aria-label="Small size navigation"
      withSeparator
      size="small"
    >
      <SidebarNavigation.Header>
        <Logo variant="icon" label="Gemini Suite logo" />
        <SidebarNavigation.AppTitle>
          {'Product name'}
        </SidebarNavigation.AppTitle>
      </SidebarNavigation.Header>
      <SidebarNavigation.Body>
        <SidebarNavigation.Section title="Section name">
          <SidebarNavigation.Items>
            <SidebarNavigation.Item iconName="home" label="Dashboard" />
            <SidebarNavigation.Item
              iconName="creditCard"
              label="Very very long navigation item"
              trailingVisual={<SidebarNavigation.ItemLabel color="info" />}
            />
            <SidebarNavigation.Group iconName="cases" label="Group item">
              <SidebarNavigation.Item iconName="download" label="Sub item 1" />
              <SidebarNavigation.Item iconName="download" label="Sub item 2" />
            </SidebarNavigation.Group>
          </SidebarNavigation.Items>
        </SidebarNavigation.Section>
        <SidebarNavigation.Section title="Other Section">
          <SidebarNavigation.Items>
            <SidebarNavigation.Item
              iconName="shield"
              label="Navigation item"
              trailingVisual={
                <SidebarNavigation.ItemLabel color="danger">
                  {'54'}
                </SidebarNavigation.ItemLabel>
              }
            />
            <SidebarNavigation.Item
              iconName="themeMap"
              isDisabled
              label="Disabled navigation item"
            />
          </SidebarNavigation.Items>
        </SidebarNavigation.Section>
      </SidebarNavigation.Body>
      <SidebarNavigation.Footer>
        <SidebarNavigation.Section title="Footer section">
          <SidebarNavigation.Items>
            <SidebarNavigation.Item iconName="settings" label="Footer item" />
            <Menu.Root>
              <SidebarNavigation.Item
                as={Menu.Trigger}
                leadingVisual={
                  <Avatar.Root of="Torvald Halvor" size="small">
                    <Avatar.Initials />
                  </Avatar.Root>
                }
                label="Torvald Halvor"
              />
              <Menu.Content
                size="small"
                placement={Placement.TOP_LEFT}
                css={{
                  maxWidth: `calc(${SIDEBAR_NAVIGATION_SMALL_WIDTH_EXPANDED} - 1rem)`
                }}
              >
                <Flex gap="spacingM" padding="spacingS">
                  <Avatar.Root of="Torvald Halvor">
                    <Avatar.Initials />
                  </Avatar.Root>
                  <FlexItem shrinkPastContentSize>
                    {'Torvald Halvor'}
                    <Text
                      overflowStrategy="truncate"
                      as="div"
                      variant="eta"
                      color="foregroundNeutralSubtle"
                    >
                      {'torvald.halvor@invera-tech.com'}
                    </Text>
                  </FlexItem>
                </Flex>
                <Menu.Separator />
                <Menu.Item startElement={<SvgIcon iconName="user" />}>
                  {'Manage account'}
                </Menu.Item>
                <Menu.Separator />
                <Menu.Item
                  intent="danger"
                  onSelect={() => {
                    alert('Log Out');
                  }}
                >
                  {'Log Out'}
                </Menu.Item>
              </Menu.Content>
            </Menu.Root>
          </SidebarNavigation.Items>
        </SidebarNavigation.Section>
      </SidebarNavigation.Footer>
      <SidebarNavigation.Toggle label="Toggle panel" />
    </SidebarNavigation.Root>
  </AppFrameWithSidebar.Sidebar>
  <AppFrameWithSidebar.Main
    padding="spacingM"
    css={{
      display: 'grid',
      placeItems: 'center'
    }}
  >
    <Text variant="zeta" color="foregroundNeutralModerate">
      {'Main content'}
    </Text>
  </AppFrameWithSidebar.Main>
</AppFrameWithSidebar.Root>
```

### Mobile version

On small screens, a mobile version of the navigation should be displayed inside a [Drawer with overlay](/components/drawer#drawer-with-overlay).
`Drawer.Trigger` is responsible for showing the mobile navigation and `Drawer.Close` acts as a dismiss button. [Drawer component](/components/drawer) comes with [many accessibility features](/components/drawer#accessibility-features) out of the box.

[Hidden utility](/components/utility/hidden) is used to control the presence of both mobile and desktop navigation experiences based on specified [breakpoints](/tokens/breakpoints).
Desktop navigation within the `AppFrame.Sidebar` is present on large viewport and above, while the mobile navigation toggle is only visible on viewports below large.

<Grid
  columns={{
    '@initial': '1',
    '@mqLargeAndUp': '2'
  }}
  columnGap="spacingL"
>
  <GridItem>
    <Card
      href="https://next--698f15fa99e7b146f9002f64.chromatic.com/?path=/story/components-sidebarnavigation--mobile"
      title="See complete example in Storybook"
      actionIcon="externalLink"
    />
  </GridItem>
  <GridItem>
    <Card
      href="https://github.com/Volue/vera/blob/next/react/src/components/SidebarNavigation/SidebarNavigation.stories.tsx#L613"
      title="Example source code"
      actionIcon="externalLink"
    />
  </GridItem>
</Grid>

```jsx
() => {
  const playgroundFrameRef = React.useRef();

  return (
    <AppFrame.Root
      ref={playgroundFrameRef}
      css={{
        // the following rules are added only to make the demo work in the playground
        // you shouldn't include them in your app
        isolation: 'isolate',
        position: 'relative',
        maxHeight: '60vh'
      }}
    >
      <AppFrameWithSidebar.Header
        paddingY="spacingM"
        paddingX={{ '@initial': 'spacingM', '@mqLargeAndUp': 'spacingL' }}
      >
        <Flex main="space-between">
          <FlexItem
            as={Hidden}
            shrink={0}
            marginY="-spacingXs"
            marginLeft="-spacingXs"
            hide={{
              '@initial': false
              // Hide the trigger for mobile version on larger viewport
              // '@mqLargeAndUp': true
            }}
          >
            <Drawer.Root>
              <Drawer.Trigger
                as={Button}
                withLoneIcon
                color="inverse"
                variant="ghost"
                aria-label="Open navigation"
                size="small"
              >
                <SvgIcon iconName="menu" size="medium" />
              </Drawer.Trigger>
              <Drawer.Portal containerRef={playgroundFrameRef}>
                <Drawer.Overlay
                  css={{
                    // the following override is added only to make the demo
                    // work in the playground
                    position: 'absolute !important'
                  }}
                />
                <Drawer.Content
                  side="left"
                  css={{
                    // the following override is added only to make the demo
                    // work in the playground
                    position: 'absolute'
                  }}
                  maxWidth={SIDEBAR_NAVIGATION_MEDIUM_WIDTH_EXPANDED}
                >
                  <SidebarNavigation.Root
                    aria-label="Main navigation"
                    withMotion={false}
                  >
                    <SidebarNavigation.Header>
                      <Logo variant="icon" label="Gemini Suite logo" />
                      <SidebarNavigation.AppTitle>
                        {'Product name'}
                      </SidebarNavigation.AppTitle>
                      <Drawer.Close
                        as={Button}
                        variant="ghost"
                        color="inverse"
                        withLoneIcon
                        aria-label="Close navigation"
                      >
                        <SvgIcon iconName="close" />
                      </Drawer.Close>
                    </SidebarNavigation.Header>
                    <SidebarNavigation.Body>
                      <SidebarNavigation.Items>
                        <SidebarNavigation.Item
                          iconName="home"
                          label="Dashboard"
                        />
                        <SidebarNavigation.Item
                          iconName="creditCard"
                          label="Very very long navigation item"
                          trailingVisual={
                            <SidebarNavigation.ItemLabel color="info" />
                          }
                        />
                        <SidebarNavigation.Group
                          iconName="cases"
                          label="Group item"
                        >
                          <SidebarNavigation.Item
                            iconName="download"
                            label="Sub item 1"
                          />
                          <SidebarNavigation.Item
                            iconName="download"
                            label="Sub item 2"
                          />
                        </SidebarNavigation.Group>
                      </SidebarNavigation.Items>
                    </SidebarNavigation.Body>
                    <SidebarNavigation.Footer>
                      <SidebarNavigation.Section title="Footer section">
                        <SidebarNavigation.Items>
                          <SidebarNavigation.Item
                            iconName="settings"
                            label="Footer item"
                          />
                          <Menu.Root>
                            <SidebarNavigation.Item
                              as={Menu.Trigger}
                              leadingVisual={
                                <Avatar.Root of="Torvald Halvor" size="small">
                                  <Avatar.Initials />
                                </Avatar.Root>
                              }
                              label="Torvald Halvor"
                            />
                            <Menu.Content
                              placement={Placement.TOP_LEFT}
                              css={{
                                maxWidth: `calc(${SIDEBAR_NAVIGATION_MEDIUM_WIDTH_EXPANDED} - 1rem)`
                              }}
                            >
                              <Flex gap="spacingM" padding="spacingS">
                                <Avatar.Root of="Torvald Halvor">
                                  <Avatar.Initials />
                                </Avatar.Root>
                                <FlexItem shrinkPastContentSize>
                                  {'Torvald Halvor'}
                                  <Text
                                    overflowStrategy="truncate"
                                    as="div"
                                    variant="zeta"
                                    color="foregroundNeutralSubtle"
                                  >
                                    {'torvald.halvor@invera-tech.com'}
                                  </Text>
                                </FlexItem>
                              </Flex>
                              <Menu.Separator />
                              <Menu.Item
                                startElement={<SvgIcon iconName="user" />}
                              >
                                {'Manage account'}
                              </Menu.Item>
                              <Menu.Separator />
                              <Menu.Item
                                intent="danger"
                                onSelect={() => {
                                  alert('Log Out');
                                }}
                              >
                                {'Log Out'}
                              </Menu.Item>
                            </Menu.Content>
                          </Menu.Root>
                        </SidebarNavigation.Items>
                      </SidebarNavigation.Section>
                    </SidebarNavigation.Footer>
                  </SidebarNavigation.Root>
                </Drawer.Content>
              </Drawer.Portal>
            </Drawer.Root>
          </FlexItem>
          <FlexItem flex="auto" shrinkPastContentSize>
            <Heading variant="delta" margin="none" overflowStrategy="truncate">
              {'View title'}
            </Heading>
          </FlexItem>
          <FlexItem shrink={0} marginY="-spacingXs">
            <Button leftIcon={<SvgIcon iconName="add" />}>{'Action'}</Button>
          </FlexItem>
        </Flex>
      </AppFrameWithSidebar.Header>
      <AppFrameWithSidebar.Sidebar
        as={Hidden}
        hide={{ '@initial': true, '@mqLargeAndUp': false }}
      >
        {/* Place your desktop version of the sidebar navigation below */}
        {/* <SidebarNavigation.Root /> */}
      </AppFrameWithSidebar.Sidebar>
      <AppFrameWithSidebar.Main
        padding={{
          '@initial': 'spacingM',
          '@mqLargeAndUp': 'spacingL'
        }}
        background="neutralSubtle"
        css={{
          display: 'grid',
          placeItems: 'center'
        }}
      >
        <Text color="foregroundNeutralModerate">{'Main content'}</Text>
      </AppFrameWithSidebar.Main>
    </AppFrameWithSidebar.Root>
  );
};
```

### Non-collapsible

For scenarios where collapsible navigation is unnecessary, you can use the `SidebarNavigation` component without the ability to collapse or expand.

This allows for simplifying the interface by using `SidebarNavigation.Item` components without icons or other leading visual elements.

<Callout variant="tip">

Use visuals consistently. Avoid mixing items that have leading visuals with items that don't.

</Callout>

```jsx
<AppFrame.Root
  css={{
    // the following rules are added only to make the demo work in the playground
    // you shouldn't include them in your app
    maxHeight: '60vh'
  }}
>
  <AppFrame.AppHeader>
    <AppHeader.Root>
      <AppHeader.Logo />
      <AppHeader.Title>{'Product Name'}</AppHeader.Title>
    </AppHeader.Root>
  </AppFrame.AppHeader>
  <AppFrame.Sidebar>
    <SidebarNavigation.Root
      withMotion={false}
      withSeparator
      aria-label="Main navigation"
    >
      <SidebarNavigation.Body>
        <SidebarNavigation.Section title="Section name">
          <SidebarNavigation.Items>
            <SidebarNavigation.Item label="Dashboard" />
            <SidebarNavigation.Item
              label="Very very long navigation item"
              trailingVisual={<SidebarNavigation.ItemLabel color="info" />}
            />
            <SidebarNavigation.Group label="Group item" defaultIsOpen>
              <SidebarNavigation.Item label="Sub item 1" />
              <SidebarNavigation.Item label="Sub item 2" />
            </SidebarNavigation.Group>
            <SidebarNavigation.Group label="Group item 2">
              <SidebarNavigation.Item label="Sub item 2.1" />
              <SidebarNavigation.Item label="Sub item 2.2" />
            </SidebarNavigation.Group>
          </SidebarNavigation.Items>
        </SidebarNavigation.Section>
        <SidebarNavigation.Section title="Other Section">
          <SidebarNavigation.Items>
            <SidebarNavigation.Item
              label="Navigation item 1"
              trailingVisual={
                <SidebarNavigation.ItemLabel color="danger">
                  {'54'}
                </SidebarNavigation.ItemLabel>
              }
            />
            <SidebarNavigation.Item
              isDisabled
              label="Disabled navigation item"
            />
          </SidebarNavigation.Items>
        </SidebarNavigation.Section>
      </SidebarNavigation.Body>
    </SidebarNavigation.Root>
  </AppFrame.Sidebar>
  <AppFrame.Main
    padding={{
      '@initial': 'spacingM',
      '@mqLargeAndUp': 'spacingL'
    }}
    css={{
      display: 'grid',
      placeItems: 'center'
    }}
  >
    <Text color="foregroundNeutralModerate">{'Main content'}</Text>
  </AppFrame.Main>
</AppFrame.Root>
```

When using [Nav Bar](/components/nav-bar) as your primary navigation, non-collapsible sidebar navigation can also be used as a secondary level navigation to alternate among related views within the same context.

<Card
  href="https://next--698f15fa99e7b146f9002f64.chromatic.com/?path=/story/demos-applayouts-headerbased--content-sidebar"
  title="Combined navigation example"
  actionIcon="externalLink"
/>

### With routing

If you need to use the `Link` component provided by your routing package (e.g. [React Router](https://reactrouter.com/en/main) or [Next.js](https://nextjs.org/docs/api-reference/next/link)), it's recommended to compose it with `SidebarNavigation.Item` via a custom component:

```jsx
import { Link, useMatch, useResolvedPath } from 'react-router-dom';
import { SidebarNavigation } from '@gemini-suite/vera-react';

function SidebarNavigationItem({ to, ...props }) {
  const resolved = useResolvedPath(to);
  const isActive = Boolean(useMatch({ path: resolved.pathname, end: true }));

  return (
    <SidebarNavigation.Item as={Link} to={to} isActive={isActive} {...props} />
  );
}

function App() {
  return (
    <SidebarNavigation.Root>
      <SidebarNavigation.Header />
      <SidebarNavigation.Body>
        <SidebarNavigation.Items>
          <SidebarNavigationItem label="Dashboard" iconName="home" to="/" />
          <SidebarNavigationItem label="Maps" iconName="themeMap" to="/maps" />
          <SidebarNavigationItem
            label="Attachments"
            iconName="attachment"
            to="/attachments"
          />
        </SidebarNavigation.Items>
      </SidebarNavigation.Body>
      <SidebarNavigation.Footer />
    </SidebarNavigation.Root>
  );
}
```

<Grid
  columns={{
    '@initial': '1',
    '@mqLargeAndUp': '2'
  }}
  columnGap="spacingL"
>
  <GridItem>
    <Card
      href="https://next--698f15fa99e7b146f9002f64.chromatic.com/?path=/story/components-sidebarnavigation--with-router"
      title="See complete example in Storybook"
      actionIcon="externalLink"
    />
  </GridItem>
  <GridItem>
    <Card
      href="https://github.com/Volue/vera/blob/next/react/src/components/SidebarNavigation/SidebarNavigation.stories.tsx#L881"
      title="Example source code"
      actionIcon="externalLink"
    />
  </GridItem>
</Grid>

---

## API Reference

### SidebarNavigation.Root

| Name                 | Type                                | Default       | Description                                                                                                                                                                                                                                                                                                                                                                            | Required |
| -------------------- | ----------------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css`                | `StitchesCss`                       |               | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants.                                                                                                                                          |          |
| `isExpanded`         | `boolean`                           | `true`        | The controlled expanded state of the sidebar. Use in conjunction with `onIsExpandedChange`.                                                                                                                                                                                                                                                                                            |          |
| `defaultIsExpanded`  | `boolean`                           |               | The initial expanded state of the sidebar when it's first rendered. Use when you do not need to control expanded state.                                                                                                                                                                                                                                                                |          |
| `onIsExpandedChange` | `(isExpanded: boolean) => void`     |               | Event handler called when the expanded state of the sidebar navigation changes.                                                                                                                                                                                                                                                                                                        |          |
| `size`               | `"small" \| "medium"`               | `"medium"`    | The size of the sidebar navigation.                                                                                                                                                                                                                                                                                                                                                    |          |
| `expandedWidth`      | `CSSProperties['width']`            | `"17rem"`     | Can be used to override width of the sidebar navigation in its expanded state. Default expanded width is exported as `SIDEBAR_NAVIGATION_MEDIUM_WIDTH_EXPANDED` variable for `medium` size and `SIDEBAR_NAVIGATION_SMALL_WIDTH_EXPANDED` for `small` size.                                                                                                                             |          |
| `withMotion`         | `boolean`                           | `true`        | When `true` sidebar navigation animates between collapsed and expanded states. Animation helps user keep track of things as they change. Use `false` only when you are having performance issues.                                                                                                                                                                                      |          |
| `withSeparator`      | `boolean`                           | `false`       | When `true`, a separator is visible at the right edge of `SidebarNavigation.Header`. Useful when the navigation header is rendered next to a view-specific header.                                                                                                                                                                                                                     |          |
| `toggleOnHover`      | `boolean`                           | `false`       | When `true` expand/collapse button is hidden and sidebar navigation automatically opens when user hovers over it.                                                                                                                                                                                                                                                                      |          |
| `mode`               | `"pushContent" \| "overlayContent"` | `pushContent` | `pushContent` makes the sidebar push the contents of the app, so that it is always visible. With `overlayContent`, expanded sidebar sits on top of the content beneath it.                                                                                                                                                                                                             |          |
| `hoverArea`          | `Element \| Element[]`              |               | Enables extending default hoverable area of the sidebar navigation. Useful when `toggleOnHover` is `true` and there are components using [Portals](/components/utility/portal), such as [Menu](/components/menu) inside sidebar navigation. Pass a portaled element or a list of elements, to prevent sidebar navigation from loosing hover state when hovering over portaled content. |          |
| `elevation`          | `"m" \| "l" \| "none"`              | `"none"`      | Size of the shadow behind sidebar navigation imitating elevation of the component.                                                                                                                                                                                                                                                                                                     |          |
| `aria-label`         | `string`                            |               | Used to provide a better description of the sidebar navigation for assistive tech users.                                                                                                                                                                                                                                                                                               | Yes      |

### SidebarNavigation.Header

| Name  | Type          | Default | Description                                                                                                                                                                                                                                   | Required |
| ----- | ------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css` | `StitchesCss` |         | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants. |          |

### SidebarNavigation.AppTitle

| Name      | Type                              | Default | Description                                                                                                                                                                                                                                   | Required |
| --------- | --------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css`     | `StitchesCss`                     |         | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants. |          |
| `variant` | `"epsilon" \| "delta" \| "gamma"` | `delta` | Size variant of the title. Use `epsilon` only for unusually long application title.                                                                                                                                                           |          |

### SidebarNavigation.Body

| Name  | Type           | Default      | Description                                                                                                                                                                                                                                   | Required |
| ----- | -------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css` | `StitchesCss`  |              | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants. |          |
| `gap` | `SpacingToken` | `"spacingM"` | Spacing between the elements inside the body component.                                                                                                                                                                                       |          |

### SidebarNavigation.Section

| Name    | Type           | Default      | Description                                                                                                                                                                                                                                   | Required |
| ------- | -------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css`   | `StitchesCss`  |              | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants. |          |
| `gap`   | `SpacingToken` | `"spacingS"` | Spacing between the elements inside the section component.                                                                                                                                                                                    |          |
| `title` | `string`       |              | Title visible above children of the section in expanded state.                                                                                                                                                                                | Yes      |

### SidebarNavigation.Items

| Name  | Type           | Default       | Description                                                                                                                                                                                                                                   | Required |
| ----- | -------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css` | `StitchesCss`  |               | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants. |          |
| `gap` | `SpacingToken` | `"spacingXs"` | Spacing between the elements inside the component.                                                                                                                                                                                            |          |

### SidebarNavigation.Item

| Name             | Type                                                      | Default  | Description                                                                                                                                                                                                                                                                                  | Required |
| ---------------- | --------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `as`             | `keyof JSX.IntrinsicElements \| React.ComponentType<any>` | `button` | Change the component to a different HTML tag or custom component. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.   For more details, read our [Composition](/get-started/composition#polymorphism) guide. |          |
| `css`            | `StitchesCss`                                             |          | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants.                                                |          |
| `label`          | `string`                                                  |          | Label of the navigation item.                                                                                                                                                                                                                                                                | Yes      |
| `iconName`       | `IconToken`                                               |          | The name of the icon to display. When missing, element defined in `leadingVisual` prop is displayed.                                                                                                                                                                                         |          |
| `isActive`       | `boolean`                                                 | `false`  | Set to `true` to represent the currently active page. The item is highlighted and scrolled into view. If the item is within `SidebarNavigation.Group`, the group will automatically open.                                                                                                    |          |
| `isDisabled`     | `boolean`                                                 | `false`  | When `true`, the item will be disabled, preventing the user from interacting with it.                                                                                                                                                                                                        |          |
| `leadingVisual`  | `React.ReactNode`                                         |          | Visual positioned on the left edge of the item.                                                                                                                                                                                                                                              |          |
| `trailingVisual` | `React.ReactNode`                                         |          | Visual positioned on the right edge of the item.                                                                                                                                                                                                                                             |          |

### SidebarNavigation.ItemLabel

| Name       | Type                                                                    | Default     | Description                                                                                                                                                                                                                                                                                  | Required |
| ---------- | ----------------------------------------------------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `as`       | `keyof JSX.IntrinsicElements \| React.ComponentType<any>`               | `div`       | Change the component to a different HTML tag or custom component. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.   For more details, read our [Composition](/get-started/composition#polymorphism) guide. |          |
| `css`      | `StitchesCss`                                                           |             | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants.                                                |          |
| `color`    | `"neutral" \| "accent" \| "success" \| "danger" \| "info" \| "warning"` | `"neutral"` | The color of the label and the dot indicator.                                                                                                                                                                                                                                                |          |
| `size`     | `"small" \| "medium"`                                                   | `"medium"`  | The size of the label. If not set, follows the size of `SidebarNavigation`.                                                                                                                                                                                                                  |          |
| `children` | `React.ReactNode`                                                       |             | The children to render within underlying [Label](/components/label) in navigation expanded state. When not provided, [HintDot](/components/hint-dot) is always used instead of [Label](/components/label).                                                                                   |          |

### SidebarNavigation.Group

| Name            | Type              | Default       | Description                                                                                                                                                                                                                                   | Required |
| --------------- | ----------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css`           | `StitchesCss`     |               | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants. |          |
| `label`         | `string`          |               | Label of the navigation item group.                                                                                                                                                                                                           | Yes      |
| `iconName`      | `IconToken`       |               | The name of the icon to display. When missing, element defined in `leadingVisual` prop is displayed.                                                                                                                                          | Yes      |
| `defaultIsOpen` | `boolean`         | `false`       | The initial open state of the group when it's first rendered.                                                                                                                                                                                 |          |
| `gap`           | `SpacingToken`    | `"spacingXs"` | Spacing between the elements inside the group.                                                                                                                                                                                                |          |
| `leadingVisual` | `React.ReactNode` |               | Visual positioned on the left edge of the item.                                                                                                                                                                                               |          |
| `isDisabled`    | `boolean`         | `false`       | When `true`, the item will be disabled, preventing the user from interacting with it.                                                                                                                                                         |          |

### SidebarNavigation.Footer

| Name  | Type           | Default      | Description                                                                                                                                                                                                                                   | Required |
| ----- | -------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css` | `StitchesCss`  |              | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants. |          |
| `gap` | `SpacingToken` | `"spacingM"` | Spacing between the elements inside the footer component.                                                                                                                                                                                     |          |

### SidebarNavigation.Toggle

| Name    | Type          | Default | Description                                                                                                                                                                                                                                   | Required |
| ------- | ------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css`   | `StitchesCss` |         | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants. |          |
| `label` | `string`      |         | Label of the toggle to help identify it's purpose when assistive tech is used.                                                                                                                                                                | Yes      |
