# `hb-dashboard-indicator` — Dashboard indicator

**Package folder:** `dashboard-indicator`  
**Category:** data  
**Tags:** data, dashboard  
**NPM scope (distribution):** `@htmlbricks/hb-dashboard-indicator`

---

## Summary

`hb-dashboard-indicator` is a compact KPI tile for dashboards: a colored **header** shows a large **metric** (`number`), an optional **caption** (`text`), and a **Bootstrap Icon**; an optional **footer** appears when `link_label` is set and acts as a single **click target** that emits a **`dashboardIndicatorClick`** custom event carrying the element’s `id`.

Accent color (“karma”) is either a **Bulma semantic palette** on `:host` (`success`, `danger`, `warning`, `primary`, `secondary`, `info`) or **`none`** to drive header background and footer text color from **`--hb--dashboard-indicator-background`** on the host.

---

## Behavior

### Rendering

- **`number`:** Shown as the main value (Bulma `title is-3`, with tightened line-height for a compact header). In markup, pass it as a **string** (web component attributes are always strings); the component coerces to a number internally (default **`0`** when omitted).
- **`text`:** Optional subtitle under the number (Bulma `subtitle is-7`). Empty string hides the subtitle line container content but the layout still reserves flow; empty caption is visually minimal.
- **`icon`:** Bootstrap Icons **glyph name only** (no `bi-` prefix). Rendered as `<i class="bi bi-{icon}">`. Implementation default if unset is **`hypnotize`**; the authoring type marks `icon` as optional to mirror HTML usage.
- **`link_label`:** If **non-empty**, a **footer** strip is rendered with the label and a right-pointing circle arrow icon. If empty or unset, **no footer** and **no** `dashboardIndicatorClick` from this control (there is nothing to click).
- **`id`:** Optional string forwarded in **`dashboardIndicatorClick`** detail as `{ id: string }`. If unset, detail is `{ id: "" }`.

### `karma` (accent)

Allowed values: `success`, `danger`, `warning`, `primary`, `secondary`, `info`, `none`.

- **`secondary`:** Not a separate Bulma palette in this component; it is **mapped to Bulma `dark`** HSL tokens (`--bulma-dark-h` / `-s` / `-l` with defaults), same as the SCSS comment in the repo.
- **Semantic values (`success` … `info` except `none`):** Header **background** and footer **text color** use `hsl(var(--bulma-<token>-h), …)` resolved from `:host` (Bulma 1.x CSS variables). **`--hb--dashboard-indicator-background` is ignored** for these values.
- **`none`:** Header background and footer link/icon color use **`var(--hb--dashboard-indicator-background, <fallback>)`** where fallback is Bulma **success** semantic HSL. Set the variable on **`hb-dashboard-indicator`** (inline `style`, stylesheet, or design token layer).

If `karma` is **not** one of the allowed literals (e.g. typo), the component **normalizes to `success`** (`karmaResolved`).

### Interaction

- **Click:** Only the **footer** (`link_label` visible) calls `dispatch("dashboardIndicatorClick", { id })`. The header is **not** clickable for this event.
- **Implementation note:** The footer uses a click handler without an equivalent keyboard handler in source; for strict accessibility, integrators may wrap the tile or add host-level keyboard handling if needed.

### Assets and shadow DOM

- **Bootstrap Icons** are loaded for the shadow tree (stylesheet link in the component head **and** a font import in `styles/webcomponent.scss` in the build). Integrators should use **valid icon names** compatible with the Bootstrap Icons version pinned by the bundle.
- **Bulma** card, title, and helper utilities are included via `styles/bulma.scss` with `:host` variable forwarding so **`--bulma-*`** tokens on the custom element affect the tile.

---

## Layout

- **Root:** Bulma **`card`** with class `hb-dashboard-indicator` and `data-karma={resolved}` for styling hooks.
- **Header (`card-header`):** Single **`card-header-title`** row (`hb-dashboard-indicator-header-inner`) as a flex row: **`nowrap`**, **space-between**, vertically centered.
  - **Left:** Icon wrapper (`hb-dashboard-indicator-icon`) — large icon (~`4rem`), white glyph on semantic header background.
  - **Right:** Flex column aligned **end** (`has-text-right`): **number** then **text**, white text, `min-width: 0` to avoid overflow blowout in tight grids.
- **Header padding:** Vertical `0.5rem`; horizontal **`var(--bulma-block-spacing, 1rem)`**. Inner title padding is reset to avoid double padding with Bulma’s defaults.
- **Footer (`card-footer`):** Only when `link_label` is set. Flex **space-between**, **clickable** (`is-clickable`), vertical padding `py-2`. Surface color from **`--bulma-background`** with scheme fallbacks; top border matches surface for a flush edge. First/last children get horizontal margins from **`--bulma-block-spacing`**.

---

## Logic (implementation reference)

| Concern | Rule |
| --- | --- |
| Valid `karma` set | `success`, `danger`, `warning`, `primary`, `secondary`, `info`, `none` |
| Invalid `karma` | Treated as **`success`** |
| Event emission | `new CustomEvent("dashboardIndicatorClick", { detail: { id } })` on `$host()` |
| Footer visibility | `{#if link_label}` — truthy string required |

The `style` field exists on the **TypeScript `Component`** type for authoring, but the Svelte props block does **not** destructure `style`; host styling still works by setting the standard **`style`** attribute on `<hb-dashboard-indicator>` (especially for CSS variables).

---

## Custom element tag

```html
<hb-dashboard-indicator …></hb-dashboard-indicator>
```

---

## Attributes / properties (snake_case, string values in HTML)

Web components reflect **string** attributes. Use JSON only where a future API requires it (not used here). Numbers and enums are plain strings.

| Attribute | Required | Default (behavior) | Description |
| --- | --- | --- | --- |
| `id` | No | `""` | Passed through in `dashboardIndicatorClick` detail. |
| `number` | No | `0` | Main KPI; pass as string, e.g. `"42"`. |
| `text` | No | `""` | Caption under the number. |
| `icon` | No | `"hypnotize"` in implementation | Bootstrap Icons name without `bi-` prefix. |
| `link_label` | No | `""` | If set, shows footer and enables click + event. |
| `karma` | No | `"success"` | Accent mode; see Behavior. |
| `style` | No | — | Standard HTML: useful to set `--hb--dashboard-indicator-background` and other variables on the host. |

---

## Events

Listen with `addEventListener` or framework equivalents.

| Event name | `event.detail` | When it fires |
| --- | --- | --- |
| **`dashboardIndicatorClick`** | `{ id: string }` | User **clicks** the **footer** while `link_label` is set. `id` matches the element’s `id` attribute / property (empty string if unset). |

TypeScript (consumer-side):

```ts
el.addEventListener("dashboardIndicatorClick", (e: CustomEvent<{ id: string }>) => {
  console.log(e.detail.id);
});
```

---

## CSS custom properties

Documented in `extra/docs.ts` / `styleSetup.vars`. Set on **`hb-dashboard-indicator`** (`:host`) unless your bundler wraps the element.

| Variable | Role |
| --- | --- |
| **`--hb--dashboard-indicator-background`** | When **`karma="none"`**: header **background** and footer **foreground** (label + arrow). If unset, falls back to Bulma **success** semantic color. **Ignored** when `karma` is any Bulma semantic value. |
| **`--bulma-block-spacing`** | Horizontal padding in header and footer row (default `1rem` in CSS). |
| **`--bulma-background`** | Footer strip **surface** color; when unset, SCSS uses scheme HSL fallbacks (`--bulma-scheme-h`, `--bulma-scheme-s`, `--bulma-background-l`, etc.). |

Additional **`--bulma-*-h` / `-s` / `-l`** (and defaults `--bulma-hb-def-*`) on `:host` control semantic karma colors per [Bulma CSS variables](https://bulma.io/documentation/features/css-variables/).

### `::part` names

**None** — `cssParts` is empty.

### Slots

**None** — `htmlSlots` is empty; all content is props-driven.

---

## Typings (`types/webcomponent.type.d.ts`)

### `Karma`

```ts
export type Karma =
  | "success"
  | "danger"
  | "warning"
  | "primary"
  | "secondary"
  | "info"
  /** Use `--hb--dashboard-indicator-background` on the host instead of Bulma `karma` tokens. */
  | "none";
```

### `Component`

```ts
export type Component = {
  id?: string;
  style?: string;
  number?: number;
  text?: string;
  icon?: string;
  link_label?: string;
  karma?: Karma;
};
```

### `Events`

```ts
export type Events = {
  dashboardIndicatorClick: { id: string };
};
```

Generated builds also emit **`types/html-elements.d.ts`** and **`types/svelte-elements.d.ts`** under the package output for DOM and Svelte typings.

---

## Examples

### Minimal tile with footer and Bulma success accent

```html
<hb-dashboard-indicator
  id="kpi-sales"
  number="128"
  text="Orders today"
  icon="cart-check"
  link_label="View details"
  karma="success"
></hb-dashboard-indicator>
```

### Danger accent (queue / errors)

```html
<hb-dashboard-indicator
  id="kpi-failures"
  number="3"
  text="Failed jobs"
  icon="exclamation-triangle"
  link_label="Open queue"
  karma="danger"
></hb-dashboard-indicator>
```

### Custom brand color (`karma="none"`)

```html
<hb-dashboard-indicator
  id="kpi-custom"
  karma="none"
  style="--hb--dashboard-indicator-background: #6366f1"
  number="12"
  text="Custom metric"
  icon="stars"
  link_label="Details"
></hb-dashboard-indicator>
```

### No footer (display-only KPI)

```html
<hb-dashboard-indicator
  number="11"
  text="Active sessions"
  icon="window"
  karma="primary"
></hb-dashboard-indicator>
```

### Vanilla JS: handle navigation by `id`

```html
<hb-dashboard-indicator
  id="orders"
  number="54"
  text="Open orders"
  icon="inbox"
  link_label="Go to inbox"
  karma="warning"
></hb-dashboard-indicator>
<script>
  document.querySelector("hb-dashboard-indicator").addEventListener("dashboardIndicatorClick", (e) => {
    if (e.detail.id === "orders") {
      location.assign("/inbox");
    }
  });
</script>
```

---

## i18n

None configured in `extra/docs.ts` (`i18nLanguages` is empty). All visible strings are supplied by the host via attributes.
