# `hb-navbar`

**Category:** layout · **Tags:** layout, navigation · **Package:** `@htmlbricks/hb-navbar`

## Summary

`hb-navbar` is a top **navigation bar** built with Bulma layout (`level`, mobile helpers). It provides an optional **menu toggle** (hamburger) that flips an internal open flag and emits `navmenuswitch`, a **brand** area (default: logo + text, or fully replaced via slot), **three projection regions** (left, center, right slots), an optional **`nav-switcher`** slot to replace the default toggle label, and an optional **user avatar menu** backed by **`hb-dropdown-simple`** (declared dependency in `extra/docs.ts`).

## Behavior

- **Menu toggle:** A `<button>` is shown unless the `noburger` attribute is present with a **non-empty** string (use **`noburger="yes"`** to hide the control; avoid values like `"no"` if you want the button to remain visible, because any non-empty string hides it in the current `{#if !noburger}` logic). The button calls `switchMenu()` on click, toggling `isOpen` and dispatching **`navmenuswitch`** with `{ isOpen }`. Default content is the character `☰`; override with the **`nav-switcher`** slot.
- **`switchopen`:** String **`"yes"`** or **`"no"`**. On bind/update, the component syncs internal `isOpen` (`"yes"` → open). Omit or use **`"no"`** for a closed starting point (see implementation in `component.wc.svelte`).
- **Brand:** Default slot **`brand`** shows `companylogouri` as an `<img>` when non-empty, then `companybrandname`. Replace the whole block with **`slot="brand"`** content when you need custom markup.
- **User menu:** When `usermenu` is provided, `hb-dropdown-simple` is registered via `addComponent` and rendered with `list={JSON.stringify(usermenu.list)}` and the avatar from `imgUri`. Dropdown item selection is forwarded as **`navbarDropDownClick`** with `{ key }` (same shape as `hb-dropdown-simple` item keys).
- **`usermenu` parsing:** From HTML, pass **`usermenu` as a JSON string** (see Attributes). If the value is a string at runtime, the component attempts `JSON.parse`; parse errors are logged to the console.
- **`navbarSlotClick`:** Dispatched when the user **clicks** or presses **Enter** on the interactive wrappers around the **left** slot region and the **center / brand** region. The authoring types allow `side: "right"`; in the current markup, only **left** and **center** paths call `dispatch("navbarSlotClick", …)`.
- **Internationalization:** none (`extra/docs.ts` lists no `i18n` entries).

## Custom element tag

```html
<hb-navbar …></hb-navbar>
```

## Attributes (HTML / reflected props)

Attribute names are **snake_case**; values exposed from HTML are **strings** (booleans as **`yes`** / **`no`**, objects as **JSON**), per project conventions.

| Attribute | Required | Role |
|-----------|----------|------|
| `id` | No | Optional host id. |
| `style` | No | Optional inline style on the host (per typings). |
| `companybrandname` | Yes | Brand text shown in the default brand area. |
| `companylogouri` | Yes | Logo URL for the default brand `<img>`; use an empty string if you only want text or a custom `brand` slot. |
| `switchopen` | No | **`"yes"`** / **`"no"`** — aligns internal menu-open state with this value. |
| `usermenu` | No | JSON string: `{ "imgUri": string, "list"?: Array<{ "key": string, "label": string, "badge"?: number, "group"?: string }> }` for the avatar dropdown. |
| `noburger` | No | Set to **`yes`** to hide the hamburger / menu button entirely. |

## Events

Listen with `addEventListener` or framework bindings on the host element.

| Event | `detail` |
|-------|----------|
| `navmenuswitch` | `{ isOpen: boolean }` |
| `navbarDropDownClick` | `{ key: string }` — user menu item key from `hb-dropdown-simple`. |
| `navbarSlotClick` | `{ side: "left" \| "right" \| "center" }` — see Behavior for which regions emit this in the current implementation. |

## CSS custom properties (`::host`)

Documented in `extra/docs.ts` / `styleSetup` (Bulma tokens and one component override). Defaults below are the documented fallbacks; override from the light DOM on the host.

| Variable | Default (documented) | Notes |
|----------|----------------------|--------|
| `--hb-layout-navbar-background` | _(empty)_ | From **`hb-layout`** / page: wins over per-host and Bulma tokens. |
| `--hb-navbar-background-color` | _(empty)_ | Set on **`hb-navbar`** only: between layout override and Bulma. |
| `--bulma-navbar-background-color` | `#f5f5f5` | Bulma navbar strip token ([docs](https://bulma.io/documentation/features/css-variables/)). |
| `--bulma-navbar-item-color` | `#363636` | Items and icon color on the bar. |
| `--bulma-navbar-height` | `3.25rem` | Minimum navbar block height. |
| `--bulma-navbar-item-img-max-height` | `1.75rem` | Max height for the brand logo image. |
| `--bulma-text` | `#363636` | Text fallback. |
| `--bulma-scheme-main-bis` | `#f5f5f5` | Background fallback after Bulma navbar token. |
| `--bulma-radius` | `0.375rem` | Menu toggle and control corner radius. |
| `--hb-navbar-menu-btn-radius` | _(empty)_ | Optional override for the hamburger / menu button radius. |

See [Bulma CSS variables](https://bulma.io/documentation/features/css-variables/) for the wider `--bulma-*` system.

## `::part` and slots

**Parts** (for `::part(...)` from outside the shadow root):

| Part | Purpose |
|------|---------|
| `left-slot` | Left cluster: toggle + left slot (see `extra/docs.ts`). |
| `center-slot` | Center column: brand + `center-slot` projection. |
| `right-slot` | Right cluster: `right-slot` + optional user dropdown. |

**Slots:**

| Slot | Purpose |
|------|---------|
| `left-slot` | Custom content to the left of the brand (inside the left region). |
| `center-slot` | Extra content centered on the bar (sibling to the brand control in the center column). |
| `right-slot` | Actions or widgets to the right of the brand (before the user menu, if any). |
| `nav-switcher` | Replaces the default `☰` label inside the menu button. |
| `brand` | Replaces the default logo + `companybrandname` block. |

## TypeScript typings (authoring)

From `types/webcomponent.type.d.ts`:

```ts
interface IUserMenuListItem {
  key: string;
  label: string;
  badge?: number;
  group?: string;
}
export interface IUserMenu {
  imgUri: string;
  list?: IUserMenuListItem[];
}
export type Component = {
  id?: string;
  style?: string;
  companybrandname: string;
  companylogouri: string;
  switchopen?: "yes" | "no";
  usermenu?: IUserMenu;
  noburger?: string;
};

export type Events = {
  navbarDropDownClick: { key: string };
  navmenuswitch: { isOpen: boolean };
  navbarSlotClick: { side: "left" | "right" | "center" };
};
```

## HTML examples

**Minimal bar (text-only brand):**

```html
<hb-navbar companybrandname="Acme" companylogouri=""></hb-navbar>
```

**Brand with logo and menu closed explicitly:**

```html
<hb-navbar
  companybrandname="Acme"
  companylogouri="https://example.com/logo.svg"
  switchopen="no"
></hb-navbar>
```

**No hamburger (e.g. desktop shell with another way to open the drawer):**

```html
<hb-navbar
  companybrandname="Studio"
  companylogouri=""
  noburger="yes"
></hb-navbar>
```

**User avatar dropdown** (`usermenu` must be a single JSON string in HTML):

```html
<hb-navbar
  companybrandname="Acme"
  companylogouri=""
  usermenu='{"imgUri":"https://example.com/avatar.png","list":[{"key":"profile","label":"Profile"},{"key":"signout","label":"Sign out"}]}'
></hb-navbar>
```

**Custom toggle glyph and right-slot actions:**

```html
<hb-navbar companybrandname="App" companylogouri="">
  <span slot="nav-switcher">Menu</span>
  <span slot="right-slot"><!-- host app controls --></span>
</hb-navbar>
```

```js
const el = document.querySelector("hb-navbar");
el.addEventListener("navmenuswitch", (e) => console.log("open:", e.detail.isOpen));
el.addEventListener("navbarDropDownClick", (e) => console.log("menu key:", e.detail.key));
el.addEventListener("navbarSlotClick", (e) => console.log("slot side:", e.detail.side));
```
