# Sidebar

The shell's left navigation, one row per screen with the current one lit and the version in its foot.

The sidebar shows the app's mark and name, then one link per nav row that has an address in the page's nav_hrefs, each with its icon and label. The row whose id is here is lit and marked as the current page. Under 900 px it becomes the browser's popover, opened by the top bar's menu button and closed by its own close button, Esc or a click outside.

## Use it

Web:

```rust
use ocean_ui_core::Icon;
use ocean_ui_web::NavItem;
NavItem { id: "tickets", label: "Tickets", icon: Icon::Inbox, command_id: "go.tickets" }
```

Native:

```rust
use ocean_ui_core::Icon;
use ocean_ui_native::shell::{NavItem, Shell};
let row = NavItem { id: "shell", label: "Shell", icon: Icon::Dashboard, command_id: "page.shell" };
Shell { nav: vec![row], here: "shell", ..shell }.show(ui, &mut reg, |ui| ui.label("…"))
```

Cargo feature `shell`; since 2026-10-29.

## Props

| Name | Type | Default | What |
|---|---|---|---|
| `app_name` | `&'static str` | `—` | The app's name beside its mark, whose first letter fills the brand square, and again in the foot. |
| `nav` | `Vec<NavItem>` | `—` | The rows in order; a row without an address in the page's nav_hrefs is left out. |
| `nav[].id` | `&'static str` | `—` | The row's id, the one here and nav_hrefs name. |
| `nav[].label` | `&'static str` | `—` | The row's words. |
| `nav[].icon` | `Icon` | `—` | The icon before the label. |
| `nav[].command_id` | `&'static str` | `—` | The command the row stands for, written as its data-command. |
| `here` | `&'static str` | `—` | The id of the lit row, the current screen. |
| `version` | `String` | `—` | The build shown after the app's name in the foot. |

On the Mac: ![Sidebar, dark](/ui/native/shell-dark.png) ![Sidebar, light](/ui/native/shell-light.png)

## Examples

### The app's screens

One row per screen, the current one lit; the build in the foot.

```rust
let shell = Shell {
    app_name: "Service desk",
    version: "0.8.8".into(),
    nav: nav(),
    here: "queue",
    crumb: vec![
        Crumb { text: "Service desk".into(), href: Some("#queue".into()) },
        Crumb { text: "Queue".into(), href: None },
    ],
    title: "Queue".into(),
    sub: Some("Every ticket open now".into()),
    actions: vec![Button::new("Build an agent", Variant::Solid).href("#build")],
    status: None,
};
out.push_str(&page(&shell));
```

### Another screen lit

here names the lit row; the page marks it as current.

```rust
let shell = Shell {
    here: "agents",
    title: "Agents".into(),
    sub: None,
    actions: Vec::new(),
    ..desk()
};
out.push_str(&page(&shell));
```

### A longer name

The app's name sits beside its initial in the brand square.

```rust
let shell = Shell {
    app_name: "Compliance desk",
    here: "cost",
    title: "Cost control".into(),
    ..desk()
};
out.push_str(&page(&shell));
```

## Accessibility

- The rows are links in a nav labelled Ocean, and the lit row says aria-current="page".
- Icons are aria-hidden, so each row is named by its label.
- Under 900 px the panel's close button is labelled Close menu, and Esc or a click outside also closes it.
- A Skip to content link before the sidebar jumps to the main stage.

## Related

- [Top bar](/ui/components/topbar.md)
- [Command palette](/ui/components/command-palette.md)
- [Page head](/ui/components/page-head.md)
- [Icon](/ui/components/icon.md)
