@htmlbricks/hb-sidebar-cards-navigator
v0.76.5
Published
Stacked sidebar navigator: picks an active panel from JSON panels (main or first without parent), shows hb-navbar with back when parentPanelId exists, then cards of rows rendered as hb-sidenav-button. Emits itemClick with panel, card and row context; rows
Readme
hb-sidebar-cards-navigator (sidebar-cards-navigator)
Category: layout
Tags: layout, navigation
Package: @htmlbricks/hb-sidebar-cards-navigator
Overview
hb-sidebar-cards-navigator is a stacked sidebar layout that drives navigation from a JSON panels tree. It resolves one active panel, renders a compact hb-navbar header for that panel, then lists each card’s rows as hb-sidenav-button entries. Row clicks emit a single itemClick custom event with full context (panel, card, row). Rows may optionally change the active panel via switchToPanelId.
Nested hb-navbar and hb-sidenav-button are registered at runtime (same package version as this component). Bootstrap Icons are loaded from jsDelivr in the component head for row icons.
Active panel resolution
The visible panel is chosen in this order:
- If an internal
switchToPanelIdstate is set (after a row withswitchToPanelIdwas clicked), the panel whoseidmatches that value is shown. - Otherwise the first panel with
main: trueis used. - If none is marked
main, the first panel withoutparentPanelIdis used.
If no panel matches, nothing is rendered inside the host.
UI behavior
hb-navbar:companybrandnameis bound to the active panel’stitle. Thenav-switcherslot shows a list icon for root-level panels and a back arrow whenparentPanelIdis set.navmenuswitchswitches the active panel toparentPanelIdwhen a parent exists (back navigation).- Cards: For each card on the active panel, if
rowsis non-empty, each row becomes onehb-sidenav-buttonwithnavlinkserialized from the row (text,key, optionalbootstrapIcon, optionalbadge). - Empty cards: Cards with no rows or an empty
rowsarray are skipped (no placeholder block).
Custom element
<hb-sidebar-cards-navigator …></hb-sidebar-cards-navigator>Attributes (snake_case; string values from HTML)
Web component attributes are strings. Pass structured data as a JSON string on panels.
| Attribute | Required | Description |
|-----------|----------|-------------|
| id | No | Host identifier; echoed on emitted itemClick detail when set. |
| style | No | Standard inline host styles (string). |
| panels | No | JSON string representing Panel[] (see data model below). If the runtime value is a string, the component parses it with JSON.parse; invalid JSON is logged and parsing is skipped. |
Boolean and numbers in JSON
Inside the panels JSON, use normal JSON booleans and numbers (e.g. "main": true). Those rules apply to the JSON payload, not to HTML boolean attributes on this tag.
Data model (panels JSON)
Types live in types/webcomponent.type.d.ts. Shapes below match authoring / TypeScript names; serialize the whole array as one string for the panels attribute.
Panel
| Field | Type | Notes |
|-------|------|--------|
| id | string | Panel identifier; used with switchToPanelId and hierarchy. |
| title | string (optional) | Shown in hb-navbar. |
| icon | string (optional) | Available on the type; not read directly by this host’s markup. |
| sort | number (optional) | Available on nested card types; not used for panel ordering in the current template. |
| parentPanelId | string (optional) | If set, navbar shows back and navmenuswitch returns to this parent panel id. |
| main | boolean (optional) | When true, this panel is preferred when no switchToPanelId override is active. |
| cards | array | List of CardNavigator objects. |
CardNavigator (card under a panel)
| Field | Type | Notes |
|-------|------|--------|
| id | string | Card id; used when resolving clicks. |
| title | string (optional) | Card-level metadata (not rendered as a separate heading in the current template). |
| icon | string (optional) | Metadata. |
| sort | number (optional) | Metadata. |
| rows | CardRow[] | Rows rendered as hb-sidenav-button instances. |
CardRow
| Field | Type | Notes |
|-------|------|--------|
| key | string | Stable row id; matched on click. |
| text | string | Primary label (passed to hb-sidenav-button navlink). |
| bootstrapIcon | string (optional) | Bootstrap Icons name without the bi- prefix (e.g. house-door). |
| badge | object (optional) | text, optional class, classcolor — forwarded to navlink. |
| subtext | string (optional) | On the type for richer payloads; not forwarded to navlink in the current implementation. |
| value | string, number, or boolean (optional) | Available in itemClick detail’s row; not sent to navlink. |
| selected | boolean (optional) | Available on row in itemClick; not sent to navlink. |
| type | "switch" | "range" | "radio" | "checkbox" | "button" (optional) | Available on row in itemClick; not sent to navlink. |
| switchToPanelId | string (optional) | After itemClick, the navigator switches the active panel to this id. |
Events
itemClick
Fired when the user activates a row (via hb-sidenav-button pageChange). event.detail matches CardRowSelected:
| Field | Meaning |
|-------|---------|
| id | Host id prop value (may be empty). |
| panel | Active panel fields without the cards array (plain object clone). |
| card | Selected card fields without the rows array. |
| row | The full CardRow that was clicked. |
If row.switchToPanelId is set, the internal active panel updates after the event is dispatched.
Styling (Bulma)
The component uses Bulma layout utilities and theme variables. Prefer --bulma-* on body, :root, or a parent that pierces into shadow DOM only if your bundler setup allows; otherwise set variables on elements that apply to this tree per your integration.
Documented variables (see extra/docs.ts / styleSetup):
| Variable | Role |
|----------|------|
| --bulma-block-spacing | Vertical gap between stacked groups of rows. |
| --bulma-text | Default text (rows, navbar). |
| --bulma-text-strong | Strong headings (titles). |
| --bulma-link | Interactive accents from nested navigation components. |
| --bulma-scheme-main | Surfaces behind stacks. |
Reference: Bulma CSS variables.
Slots and CSS parts
- Slots: none on this host.
::part: none declared for this host; nestedhb-*children may expose their own documented parts.
Dependencies
Declared in extra/docs.ts:
hb-navbar(which depends onhb-dropdown-simple)hb-sidenav-button
Ensure these custom elements are defined (for example via @htmlbricks/hb-bundle or the matching standalone packages) before using this navigator.
Examples
Minimal single panel
<hb-sidebar-cards-navigator
panels='[{"id":"home","title":"Home","cards":[{"id":"menu","rows":[{"key":"dash","text":"Dashboard","bootstrapIcon":"speedometer2"}]}]}]'
></hb-sidebar-cards-navigator>Main panel, child panel with back, and panel switch from a row
<hb-sidebar-cards-navigator
id="app-nav"
panels='[
{
"id": "root",
"main": true,
"title": "Overview",
"cards": [
{
"id": "account",
"title": "Account",
"rows": [
{ "key": "profile", "text": "Profile", "bootstrapIcon": "person" },
{
"key": "advanced",
"text": "Advanced",
"bootstrapIcon": "gear",
"switchToPanelId": "advanced-panel"
}
]
}
]
},
{
"id": "advanced-panel",
"parentPanelId": "root",
"title": "Advanced",
"cards": [
{
"id": "opts",
"rows": [
{ "key": "security", "text": "Security", "bootstrapIcon": "shield-lock" }
]
}
]
}
]'
></hb-sidebar-cards-navigator>Listening from JavaScript
const el = document.querySelector("hb-sidebar-cards-navigator");
el.addEventListener("itemClick", (e) => {
const { panel, card, row, id } = e.detail;
console.log(panel.id, card.id, row.key, id);
});TypeScript
Authoring types for this package: types/webcomponent.type.d.ts — Component, Panel, CardNavigator, CardRow, CardRowSelected, and Events (including itemClick detail typing for Svelte / wrappers).
License
Package metadata references Apache-2.0 (see LICENSE.md in the published package when consuming from npm).
