@htmlbricks/hb-sidenav-link
v0.76.5
Published
Sidebar nav item: Bootstrap Icons (bi-*), label, optional Bulma-style tag badge (outlined pill: transparent fill, border uses tag foreground color), and either a flat button that dispatches pageChange on click or an expandable group of subLinks with activ
Downloads
3,607
Readme
hb-sidenav-link (sidenav-link)
Category: layout
Tags: layout, navigation
Package: @htmlbricks/hb-sidenav-link
Overview
hb-sidenav-link is a single sidebar navigation row for hierarchical menus. It renders a Bootstrap Icons label row, an optional Bulma-style tag badge (outlined pill: transparent fill, border and text from the tag color), and either:
- a leaf link that dispatches
pageChangewhen the user activates it, or - a parent row with
subLinksthat expands to show nested links.
Active styling applies when the current page key (navpage) matches a link key, or when the selected flag is enabled. The component is intended for use inside hb-sidebar-desktop lists (and shares the INavLink shape with related layout components).
Bootstrap Icons are loaded from the component (bootstrap-icons CSS on jsDelivr). Icon names are the bi-* suffix only (for example house-door → bi-house-door).
Custom element
<hb-sidenav-link …></hb-sidenav-link>Props (TypeScript Component)
| Property | Type | Required | Notes |
|------------|-------------|----------|--------|
| navlink | INavLink | yes | From HTML, pass a JSON string (see below). |
| navpage | string | no | Current page key; drives active row and expanded groups. |
| selected | boolean | no | When true, forces the “current page” appearance. From HTML use string encodings (see Attributes). |
| id | string | no | Optional identifier (typed on the component API). |
| style | string | no | Optional inline style (typed on the component API). |
INavLink shape
Used for the root navlink and, recursively, for each entry in subLinks.
| Field | Type | Required | Description |
|------------|----------------|----------|-------------|
| key | string | yes | Stable id for the link; sent as page in pageChange for leaf clicks. |
| label | string | yes | Visible label. |
| icon | string | no | Bootstrap Icons name without the bi- prefix. |
| group | string | no | Present in the shared nav typings for interoperability. |
| badge | object | no | text (string), optional Bulma modifier classes class and classcolor (for example is-rounded, is-light). |
| subLinks | INavLink[] | no | If non-empty, the row becomes an expandable group instead of a single leaf. |
| active | boolean | no | Present on the shared type; not read by this component’s markup. |
| open | boolean | no | When navlink is provided as a JSON string, open: true initializes the group as expanded. |
Badges
badge supports:
text— badge label.class— optional Bulma tag class (defaults tois-roundedin the template).classcolor— optional color modifier (defaults tois-light).
Attributes (snake_case; string values in HTML)
Reflects the web component contract: attributes are strings.
| Attribute | Required | Description |
|------------|----------|-------------|
| navlink | yes | JSON string representing INavLink. |
| navpage | no | Current page key string. |
| selected | no | Boolean-as-string: yes / no per project conventions. The implementation also treats the literal strings true / yes as true, and treats an empty string as true; any other value becomes false unless already boolean true inside the app. Prefer explicit yes or no from HTML. |
| id | no | String. |
| style | no | String. |
If navlink arrives as a string, the component parses it as JSON and applies open from the parsed object when open === true.
Events
| Event | detail | When it fires |
|-------------|------------------------|----------------|
| pageChange | { page: string } | User activates a non-active leaf: either the root row (no subLinks) or a sub-link whose key does not match navpage and is not forced selected. Active rows (matching navpage or selected) are static for accessibility (aria-current="page") and do not dispatch pageChange on click. |
Listen in plain DOM:
document.querySelector('hb-sidenav-link').addEventListener('pageChange', (e) => {
console.log(e.detail.page);
});Behavior
Leaf row (no subLinks)
- If
navlink.key === navpageorselectedis true: one full-width “current” button (link styling), no click navigation event. - Otherwise: ghost button; click dispatches
pageChangewithdetail.page === navlink.key.
Parent row (non-empty subLinks)
- The parent row is a control that toggles expand/collapse and shows ▼ when open or when any child
keyequalsnavpage, otherwise ►. - The nested list is shown when the group is open or when some child has
key === navpage. - Each child follows the same active vs ghost rules as a leaf; inactive children dispatch
pageChangewithdetail.page ===that child’skey.
Layout
Labels use a flexible middle column; a fixed-width trail column (--hb-sidenav-trail-width) keeps titles aligned when some rows omit a badge or use the expand chevron. Long badge text is truncated with an ellipsis in the component styles.
Styling (Bulma and component variables)
Buttons and tags live in the shadow root. Theme with public --bulma-* variables on body, :root, or an ancestor; see Bulma CSS variables. Additional tokens are listed in extra/docs.ts.
| CSS custom property | Default (from docs) | Purpose |
|--------------------|---------------------|---------|
| --bulma-link | #485fc7 | Active row stripe, chevrons, and interactive accents. |
| --bulma-link-text | #ffffff | Text color on the active row background mix. |
| --bulma-text | #363636 | Default label color for inactive rows. |
| --bulma-scheme-main | #ffffff | Row surface behind ghost buttons. |
| --bulma-radius | 0.375rem | Row rounding for list items. |
| --hb-sidenav-trail-width | 3.5rem | Width of the right column (badges / expand chevron); keeps labels aligned when some rows omit a badge. |
CSS parts
| Part | Description |
|------|-------------|
| li | Bulma menu list row (li) wrapping the ghost or link button, label column, badge or chevron trail, and nested sub-links. |
Slots: none (htmlSlots is empty).
Examples
Simple leaf
<hb-sidenav-link
navpage="home"
navlink='{"label":"Home","key":"home","icon":"house-door"}'
></hb-sidenav-link>Leaf with badge
<hb-sidenav-link
navlink='{"label":"Home","key":"home","icon":"house-door","badge":{"text":"3","classcolor":"is-danger"}}'
></hb-sidenav-link>Expandable group with sub-links
<hb-sidenav-link
navpage="dash"
navlink='{"label":"Workspace","key":"workspace","icon":"folder2-open","subLinks":[{"label":"Dashboard","key":"dash","icon":"speedometer2"},{"label":"Projects","key":"projects","icon":"kanban"}]}'
></hb-sidenav-link>Force selected appearance
<hb-sidenav-link
selected="yes"
navlink='{"label":"Home","key":"home","icon":"house-door"}'
></hb-sidenav-link>Related types
INavLink matches the structure used by hb-offcanvas and hb-sidebar-desktop for navlinks arrays, so the same serialized objects can be reused across layout components.
License
Package metadata references Apache-2.0 (see LICENSE.md in the published package when consuming from npm).
