---
title: SideNavbarComponent
---

The `SideNavbarComponent` renders a vertical navigation sidebar for the app shell. It supports navigation entries, a logo/title area, bottom navigation, and an optional collapsible mode that reduces the sidebar to icon-only display.

## Configuration Options

All options are defined by the `SideNavbarOptions` interface.

| Option | Type | Default | Description |
|---|---|---|---|
| `width` | `number` | `280` | Width of the sidebar in pixels when expanded. |
| `collapsedWidth` | `number` | `64` | Width of the sidebar in pixels when collapsed. |
| `collapsed` | `boolean` | `false` | When `true`, the sidebar collapses to show only icons. Text labels, headers, language selectors, bottom content, and sub-entries are hidden. |
| `onToggleCollapse` | `() => void` | — | Callback invoked when the user clicks the collapse/expand toggle button. If omitted, the toggle button is not rendered. |
| `bgColor` | `string` | — | Background color of the sidebar. |
| `textColor` | `string` | — | Text color for sidebar content. |
| `sidebarLogo` | `string` | — | URL of a logo image shown at the top of the sidebar. Hidden when collapsed. |
| `title` | `string` | — | Title text shown at the top of the sidebar. Hidden when collapsed. |
| `navigation` | `Navigation` | — | Primary navigation entries. |
| `bottomNavigation` | `Navigation` | — | Navigation entries pinned to the bottom of the sidebar. |
| `bottomContent` | `Snippet` | — | A Svelte snippet rendered below the primary navigation entries. Hidden when collapsed. |

## Collapsed Mode

When `collapsed` is `true`, the sidebar shrinks to `collapsedWidth` (default `64px`) and hides all text, showing only entry icons. A smooth CSS transition (`200ms ease-in-out`) animates the width change.

In collapsed mode:

- Navigation entry icons remain visible and are centered.
- Each icon entry gains a right-side tooltip displaying its label, so users can still identify entries without text.
- Section headers, the language selector, sub-entries, and `bottomContent` are hidden.
- The logo and title area are hidden.
- The collapse toggle button shows a tooltip with the "expand" label.

## Collapse Toggle Button

When `onToggleCollapse` is provided, a toggle button is rendered at the bottom of the sidebar. Clicking it invokes the callback. It is accessible via `data-testid="sidebar-collapse-toggle"` and includes an appropriate `aria-label` that reflects the current state.

## Persisting Collapse State

The sidebar itself is stateless with respect to collapse — it accepts `collapsed` as a prop. To persist the collapsed state across page loads, use `sidebarCollapseService` from the client package. This service stores the user's preference in `localStorage` under the key `sidebar-collapsed`, ensuring the sidebar restores its last known state on the next visit.

The service exposes two members:

| Member | Description |
|---|---|
| `collapsed` | Reactive boolean state reflecting the current collapsed value. |
| `initialize()` | Reads the stored value from `localStorage` and sets the initial state. Call this on mount. |
| `toggle()` | Flips the collapsed state and writes the new value to `localStorage`. |

### Initializing the Service

Call `sidebarCollapseService.initialize()` on mount to restore the stored preference:

```svelte
<script>
  import { sidebarCollapseService } from '@smallstack/client';
  import { onMount } from 'svelte';

  onMount(() => {
    sidebarCollapseService.initialize();
  });
</script>
```

`initialize()` is safe to call in SSR contexts — it checks for `browser` before accessing `localStorage` and does nothing server-side.

### Wiring to the Sidebar

Pass the reactive `collapsed` state and the `toggle` method to the sidebar options:

```svelte
sidebar={{
  navigation: myNavigation,
  width: 280,
  textColor: "var(--color-primary-content)",
  collapsed: sidebarCollapseService.collapsed,
  onToggleCollapse: () => sidebarCollapseService.toggle()
}}
```

## Example

```svelte
<AppShellComponent
  showSidebar={true}
  sidebar={{
    navigation: mainNavigation,
    bottomNavigation: bottomNavigation,
    width: 280,
    collapsedWidth: 64,
    textColor: "var(--color-primary-content)",
    collapsed: sidebarCollapseService.collapsed,
    onToggleCollapse: () => sidebarCollapseService.toggle()
  }}
/>
```

## Accessibility

- The collapse toggle button has an `aria-label` that changes between the expand and collapse labels depending on current state.
- Collapsed navigation entries expose their labels via `data-tip` tooltips (DaisyUI `tooltip tooltip-right`), ensuring keyboard and pointer users can identify each entry.
