C&C Docs
Log in

cnc-nav-vertical

The sidebar tree: a vertical list of collapsible groups with icons and counts, nested to any depth. Like the rest of the family it is a projection of one root tree.

Quick start

Give it a root tree and handle itemclick. Groups start collapsed except along the path to active-id, so pointing that at a nested item opens its ancestors.

<cnc-nav-vertical
  active-id="drafts"
  @itemclick="router.go($event.detail.item.href)"
  $root='{
    "id": "root",
    "children": [
      { "id": "dash", "label": "Dashboard", "icon": "heroicons/home", "href": "/" },
      { "id": "content", "label": "Content", "children": [
        { "id": "drafts", "label": "Drafts", "href": "/drafts", "count": 3 }
      ]}
    ]
  }'
></cnc-nav-vertical>

Node fields

Every item in the tree, at any depth, takes the same fields.

Field Purpose
id The node's identity. Used by active-id and carried in the events, so it must be unique across the whole tree rather than among its siblings.
label The text shown for the item.
children An array of the same shape, nested to any depth. A node WITH children is a group; a node without is a destination.
href The destination. Note that the widget calls preventDefault() on it and emits its event instead, so this is data for your handler rather than a working link.
icon An icon name shown before the label.
count A number shown at the end of the row — unread items, results, whatever the row counts. Rendered only when TRUTHY, so a zero is omitted rather than shown.

Usage guidance

Navigation is the HOST's job. Every one of these widgets swallows the click on an href and emits an event carrying it instead of letting the browser follow the link, so a nav with no handler renders correctly and goes nowhere. Route from the event.

A group row both toggles and emits, so the handler sees clicks that are not destinations. Branch on item.href rather than assuming every itemclick is a navigation, or opening a section will route you somewhere.

Bind expanded when the sidebar is long. It is seeded once from active-id and then owned by the widget, so without a binding every collapse the user makes is lost on the next page — which in a sidebar they see on every screen is the difference between a tree they have arranged and one that keeps resetting.

Counts render only when truthy, so a zero disappears rather than showing "0". Where the distinction matters — an empty inbox against one you have not counted — put the value in the label instead.

← Back to Widgets