GitHub repository

Sidebar

App-shell navigation sidebar.

The application sidebar: grouped, icon-led navigation rendered as proper `<nav>` + `<ul>/<li>`. Items can link (`href`), carry a status dot and a square `badge`, and nest one level of children with the disclosure pattern. Collapses to an icon-only rail.

Demo

live · storybook Open in Storybook

Demo loads from https://dssoca-storybook.vercel.app/. Run pnpm storybook for it to render locally.

Usage

svelte
<script>
  import { Sidebar } from 'dssoca';
  let active = $state('hub');
  let collapsed = $state(false);
</script>

<Sidebar
  {active}
  {collapsed}
  onSelect={(id) => (active = id)}
  onToggleCollapsed={(c) => (collapsed = c)}
/>

Exports the `SideItem`, `SideGroup`, and `SideStatus` types from `dssoca`. `SideItem` gains `href`, `external` (off-site `href`: new tab, safe `rel`, external glyph, announced — the docs nav uses it for the Inspirations site), `badge`, optional `icon` (omit for a text-only item), and one level of nested `children`. The rail stretches to fill its host container’s height (`min-height: 100%`), so the border/background span the full screen or column; it still grows past the viewport when the nav is long.

HTML

CSS only — static markup The exact markup the component renders, generated at build time. Use it with dssoca/vanilla.css — see Plain HTML & CSS.

html
<nav class="ss-side" aria-label="Sidebar">
  <div class="section" id="ss-side-sec-0">Main</div>
  <ul class="list" aria-labelledby="ss-side-sec-0">
    <li class="row">
      <div class="item active" role="button" tabindex="0" aria-current="page">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="square" stroke-linejoin="miter" class="ss-icon" style="width:13px;height:13px" aria-hidden="true" focusable="false">
          <path d="M4 11l8-8 8 8"/>
          <path d="M6 9v12h12V9"/>
          <path d="M10 21v-6h4v6"/>
        </svg>
        <span class="label">Hub</span>
      </div>
    </li>
    <li class="row">
      <div class="item" role="button" tabindex="0">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="square" stroke-linejoin="miter" class="ss-icon" style="width:13px;height:13px" aria-hidden="true" focusable="false">
          <path d="M4 6h16M4 12h16M4 18h10"/>
        </svg>
        <span class="label">Logs</span>
        <span class="badge">3</span>
        <span class="dot" aria-hidden="true"></span>
      </div>
    </li>
  </ul>
</nav>

Static navigation; disclosures need your own JS.

Props

PropTypeDefaultDescription
activestring'hub'Active item id.
groupsSideGroup[]—Sections of items ({ id, label, icon?, status?, href?, external?, badge?, children? }); has a built-in default. `external` (with `href`) opens in a new tab with `rel="noopener noreferrer"`, a trailing external glyph and an "(opens in a new tab)" announcement.
onSelect(id: string) => void—Selection handler.
collapsedbooleanfalseCollapse to an icon-only rail; labels/section text are hidden.
onToggleCollapsed(collapsed: boolean) => void—Fired when the built-in collapse toggle is pressed.
size'sm' | 'md' | 'lg'—Per-instance size override; inherits the ancestor `data-size-variant` when unset.
↑↓ navigate · ↵ open · esc close

Keyboard shortcuts

No shortcuts registered

Shortcuts added through the dssoca registry will show up here.

Single-key shortcuts