Atomic Angular — Doc interne

Sidebar

An app navigation panel — collapsible to an icon rail on desktop, a native-dialog drawer below the mobile breakpoint — with no rail and no nested submenus.

Sidebar is an app navigation panel: collapsible to icons on desktop, a native <dialog> drawer (Sheet) below the mobile breakpoint. It covers the common case — no rail, no nested submenus, no skeleton loading — with a real focusable trigger, a genuinely modal mobile drawer, and item labels that stay in the accessibility tree once the panel goes icon-only.

Minimal example

How it works

Sidebar renders as a native <aside> on desktop, and swaps to a Sheet anchored to side() below the 768px breakpoint (via BreakpointObserverService) — projecting the exact same sidebarHeader/sidebarContent/sidebarFooter content either way, nothing to branch on in application code.

isMobile provides injects click isMobile true isMobile false isMobile true isMobile false aria-current BreakpointObserverService SidebarComponent SIDEBAR_REF SidebarTriggerDirective toggle() Sheet.open()/close() collapsed model Sheet <aside> sidebarHeader / sidebarContent / sidebarFooter SidebarItemDirective routerLinkActive

The mobile drawer starts closed, and its entire content — including a trigger placed inside sidebarHeader — lives inside it. Below the breakpoint there is nothing on screen to open it from unless the app keeps a second trigger outside the <Sidebar> (its own top bar, typically), passed the panel explicitly since it cannot resolve SIDEBAR_REF through DI from outside:

The mobile drawer reuses Sheet unmodified — focus trap, Escape-to-close, focus restoration and the ::backdrop all come from the native <dialog> + showModal() — sized to the full viewport width (a fixed Sheet width can otherwise push the in-header trigger off-screen on a narrow phone) and painted with the same --sidebar/--sidebar-foreground tokens as the desktop panel, so a themed app gets a matching drawer with no extra work.

Recipes

Trailing badge and disabled item

A trailing Badge is pinned to the end of an item and dropped automatically once the sidebar is icon-only — there is no room next to a bare icon for a pill.

<a sidebarItem routerLink="/notifications">
  <BellIcon />
  <span sidebarItemLabel>Notifications</span>
  <badge size="xs">3</badge>
</a>

<a sidebarItem href="#" disabled>
  <CogIcon />
  <span sidebarItemLabel>Locked setting</span>
</a>

disabled reflects aria-disabled="true" and sets tabindex="-1" — the same contract as Link's own disabled.

inset and floating variants

variant="inset" draws no border or fill on Sidebar itself; the encased look comes from sidebarInset on the app's main content wrapper instead, which supplies the surface. variant="floating" needs no companion element — it detaches with a margin, border and shadow of its own, and reserves no layout space, ever, floating on top of whatever sibling content follows it.

floating/inset collapse differently from the default sidebar variant: instead of narrowing to an icon rail, the whole panel slides off-screen (and is marked inert while hidden, so its own header trigger cannot still be reached by keyboard). An app using either variant with collapse therefore needs a third trigger placed outside the <Sidebar>, shown only while collapsed() is true.

Reading the collapsed state from a projected component

A component projected inside sidebarHeader/sidebarContent/sidebarFooter reads the panel's own state by injecting SIDEBAR_REF — the same token SidebarTriggerDirective itself resolves through.

Options

Prop

Type

SidebarTriggerDirective

Prop

Type

SidebarTriggerDirective also reflects aria-expanded on its host, bound to the resolved sidebar's expanded() signal — a screen reader announces whether activating it opens or closes the panel, whichever viewport applies.

An InjectionToken<SidebarRef> a <Sidebar> provides for anything projected into it, exposing collapsed, isMobile, expanded (all Signal<boolean>) and toggle()/open()/close() — the last three branch on isMobile() automatically (desktop collapse vs. the mobile drawer).

Pitfalls

What's next

On this page