@norconsult-digital-public/isypixel 2.0.2-canary.6 → 2.0.2-canary.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/docs/web-components/ip-chip/llm.md +157 -0
  2. package/dist/docs/web-components/ip-chip-group/llm.md +165 -0
  3. package/dist/docs/web-components/ip-icon-count/llm.md +126 -0
  4. package/dist/llm.md +15 -12
  5. package/dist/types/components/ip-chip/ip-chip.d.ts +67 -0
  6. package/dist/types/components/ip-chip-group/ip-chip-group.d.ts +80 -0
  7. package/dist/types/components/ip-icon-count/ip-icon-count.d.ts +14 -0
  8. package/dist/types/components.d.ts +347 -0
  9. package/dist/types/home/runner/work/pixel/pixel/.stencil/utils/icons.d.ts +5 -0
  10. package/dist/types/index.d.ts +3 -0
  11. package/dist/web-components/components/index.js +1 -1
  12. package/dist/web-components/components/ip-avatar-stack.js +1 -1
  13. package/dist/web-components/components/ip-avatar.js +1 -1
  14. package/dist/web-components/components/ip-button.js +1 -1
  15. package/dist/web-components/components/ip-chip-group.d.ts +11 -0
  16. package/dist/web-components/components/ip-chip-group.js +1 -0
  17. package/dist/web-components/components/ip-chip.d.ts +11 -0
  18. package/dist/web-components/components/ip-chip.js +1 -0
  19. package/dist/web-components/components/ip-icon-button.js +1 -1
  20. package/dist/web-components/components/ip-icon-count.d.ts +11 -0
  21. package/dist/web-components/components/ip-icon-count.js +1 -0
  22. package/dist/web-components/components/ip-main-menu-group.js +1 -1
  23. package/dist/web-components/components/ip-main-menu-item.js +1 -1
  24. package/dist/web-components/components/ip-main-menu-section.js +1 -1
  25. package/dist/web-components/components/ip-main-menu-toggle.js +1 -1
  26. package/dist/web-components/components/ip-main-menu.js +1 -1
  27. package/dist/web-components/components/ip-tooltip.js +1 -1
  28. package/dist/web-components/components/p-BG9BklGR.js +1 -0
  29. package/dist/web-components/components/{p-D7rK08OB.js → p-BPNcFvV4.js} +1 -1
  30. package/dist/web-components/components/{p-DWpUb5rd.js → p-Ba5PDZcO.js} +1 -1
  31. package/dist/web-components/components/{p-BYKtWIr5.js → p-BcS76vWO.js} +1 -1
  32. package/dist/web-components/components/{p-D42v9_4Q.js → p-BrE_t6WH.js} +1 -1
  33. package/dist/web-components/components/p-C7Xl2j2X.js +1 -0
  34. package/dist/web-components/components/p-C8zDW_sy.js +1 -0
  35. package/dist/web-components/components/{p-BkayA00u.js → p-CDL6v2R_.js} +1 -1
  36. package/dist/web-components/components/p-CU3XMYRk.js +1 -0
  37. package/dist/web-components/components/{p-VLgeZTve.js → p-ClvSUrIV.js} +1 -1
  38. package/dist/web-components/components/{p-BB9-AZXH.js → p-D83crOsE.js} +1 -1
  39. package/dist/web-components/components/{p-MvV7276a.js → p-DTh1Kvjd.js} +1 -1
  40. package/dist/web-components/components/{p-6Z45CK1I.js → p-DVwQwKni.js} +1 -1
  41. package/dist/web-components/components/p-U-7IBVRB.js +1 -0
  42. package/dist/web-components/components/{p-msgdnxTK.js → p-VctHpAA_.js} +1 -1
  43. package/dist/web-components/components/{p-DHUR9EVo.js → p-Z_KsG5lc.js} +1 -1
  44. package/dist/web-components/components/{p-CXMRqnYG.js → p-ntoTViAh.js} +1 -1
  45. package/dist/web-components/generated/angular/components.d.ts +111 -1
  46. package/dist/web-components/generated/angular/components.js +186 -0
  47. package/dist/web-components/generated/angular/components.ts +161 -0
  48. package/dist/web-components/generated/angular/index.d.ts +1 -1
  49. package/dist/web-components/generated/angular/index.js +3 -0
  50. package/dist/web-components/generated/angular/index.ts +3 -0
  51. package/dist/web-components/generated/react/components.d.ts +14 -1
  52. package/dist/web-components/generated/react/components.js +27 -0
  53. package/dist/web-components/generated/react/components.ts +37 -1
  54. package/dist/web-components/generated/svelte/components.d.ts +6 -0
  55. package/dist/web-components/generated/vue/components.d.ts +3 -0
  56. package/dist/web-components/generated/vue/components.js +33 -0
  57. package/dist/web-components/generated/vue/components.ts +39 -0
  58. package/llms.txt +3 -0
  59. package/package.json +1 -1
  60. package/dist/web-components/components/p-C1tFWpS0.js +0 -1
  61. package/dist/web-components/components/p-CAPVXUZ_.js +0 -1
@@ -0,0 +1,157 @@
1
+ # ip-chip
2
+
3
+ A compact, presentational chip: a label/tag with a semantic status colour, orthogonal fill and border axes, an optional leading icon, a collapsed icon-only state, and an optional remove button. It has no click or selection behaviour of its own — interactivity and selection are owned by `ip-chip-group`. Standalone, it is a status tag or a removable input tag.
4
+
5
+ **Storybook:** https://pixel.isy.no/storybook/?path=/docs/core-ui-ip-chip-usage--docs
6
+
7
+ > This component requires ISY Pixel global styles to render correctly. Always remind the user to verify that styles are imported in their global stylesheet. See `llm.md` in the package root for style import options.
8
+
9
+ ## Attributes
10
+
11
+ | Attribute | Type | Default | Values | Description |
12
+ | -------------- | ------- | ---------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
13
+ | `variant` | string | `"info"` | `"neutral"`, `"info"`, `"success"`, `"warning"`, `"error"`, `"brand"` | Drives the chip colour (fill and icon). `info` is the default; `neutral` is a status-less greyscale chip. |
14
+ | `border-style` | string | `"solid"` | `"none"`, `"solid"`, `"dashed"` | Border style. |
15
+ | `size` | string | `"medium"` | `"small"`, `"medium"`, `"large"` | Chip size. |
16
+ | `value` | string | `""` | Any string | Passive identity read by `ip-chip-group`. No effect standalone. |
17
+ | `interactive` | boolean | `false` | `true`, `false` | Makes the chip body a toggle button with `aria-pressed`. Set by `ip-chip-group` in single/multiple mode; no effect standalone. |
18
+ | `selected` | boolean | `false` | `true`, `false` | Visual selected state. Set primarily by `ip-chip-group`; styling only. |
19
+ | `collapsed` | boolean | `false` | `true`, `false` | Hides the text visually and shows only the icon. The text is kept for screen readers. Requires the `icon` slot. |
20
+ | `removable` | boolean | `false` | `true`, `false` | Shows a built-in remove button (X). |
21
+ | `remove-label` | string | `"Remove"` | Any string | Accessible label for the remove button. The chip text is appended where available, e.g. "Remove High". |
22
+ | `disabled` | boolean | `false` | `true`, `false` | Disables the chip and its remove button. |
23
+
24
+ **Colour vs border** — `variant` sets the fill tint and icon colour; `border-style` independently controls the border line (`none`, `solid`, or `dashed`). The border is a neutral grey on every variant — the status colour lives in the fill and the icon.
25
+
26
+ ## Slots
27
+
28
+ | Slot | Description |
29
+ | ------------- | -------------------------------------------------------------------------------------------------- |
30
+ | `default` | The text content of the chip. |
31
+ | `icon` | Leading icon or status dot, shown before the text. Required when `collapsed`. |
32
+ | `remove-icon` | Overrides the icon inside the remove button. Defaults to a built-in X (Font Awesome Free `xmark`). |
33
+
34
+ ## Events
35
+
36
+ | Event | Payload | When |
37
+ | ---------- | ------- | --------------------------------------------------------------------- |
38
+ | `ipRemove` | `void` | The built-in remove button is activated. Not emitted when `disabled`. |
39
+
40
+ ## Methods
41
+
42
+ | Method | Signature | Description |
43
+ | ---------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
44
+ | `setFocus` | `setFocus(segment?: 'primary' \| 'remove') => Promise<void>` | Moves focus to a chip segment (default `'primary'`). Falls back to the other segment when the requested one is not focusable. Used by `ip-chip-group` to restore focus after a keyboard removal. |
45
+
46
+ ## Accessibility
47
+
48
+ - The chip is presentational by default. Inside `ip-chip-group` it becomes a **split button**: the primary (body) and the remove button are separate, sibling `<button>`s — never nested. In selection modes the group makes the primary a toggle button with `aria-pressed`; every primary and remove button is a natural tab stop.
49
+ - When a chip is removed via keyboard inside `ip-chip-group`, the group moves focus to a neighbouring chip (see the ip-chip-group docs). Standalone, the consumer is responsible for moving focus after removing the chip from the DOM.
50
+ - When `collapsed`, the text is visually hidden but kept for assistive technology, so the chip retains an accessible name.
51
+ - The remove button is an always-focusable `<button>` with an accessible name combining `remove-label` and the chip text, e.g. "Remove High". It shows a `:focus-visible` ring.
52
+ - When `disabled`, the remove button sets both `disabled` and `aria-disabled="true"`, and the chip is greyed out.
53
+ - Long text is truncated with an ellipsis at a `max-width` (set `--ip-chip-max-width`); the full text is then shown in an `ip-tooltip` on hover/focus. A `collapsed` chip always offers its full text in the tooltip.
54
+
55
+ ## Design tokens
56
+
57
+ > The chip reuses generic semantic tokens and non-adaptive primitive extended/core colours as theme stand-ins; a dedicated chip token family (fill, border, text, focus, remove-hover, target size) does not exist yet. These are marked `//TODO` in the SCSS and will be replaced once design adds the chip tokens.
58
+
59
+ | SCSS variable | Role |
60
+ | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
61
+ | `$ip_color_core_steel_blue-900` | Text colour on every variant — a non-adaptive near-black (= primary-black's light value) so it stays legible on the light fills in both themes; the label is shown at 60% opacity. A 20%-opacity mix of it is the non-adaptive border on filled chips (visible on the light fill in both themes). |
62
+ | `$ip_color_border_opaque_20` | Adaptive border for the group-unselected (ghost) chip, which sits on the page rather than a fill: near-black at 20% in light mode, flipping to translucent white in dark mode so the outline stays visible. Also the remove-button hover background. |
63
+ | `$ip_color_text_primary_black` | Text colour for a fill-less ghost chip (group-unselected) — adaptive, so it follows the page in dark mode |
64
+ | `$ip_color_extended_indigo-100` / `-700` | `info` (default) fill / icon |
65
+ | `$ip_color_brand_accent_primary_default` | `brand` fill (a pale `color-mix` wash) and icon — the teal brand accent |
66
+ | `$ip_color_extended_green-100` / `-700` | `success` fill / icon |
67
+ | `$ip_color_extended_orange-100` / `-950` | `warning` fill / icon |
68
+ | `$ip_color_extended_red-100` / `-600` | `error` fill / icon |
69
+ | `$ip_color_core_light_gray-200` / `-900` | `neutral` fill / icon (status-less greyscale) |
70
+ | `$ip_color_border_opaque_10` | Resting background of the remove button |
71
+ | `$ip_color_button_focus_default` | Focus ring for the chip and the remove button (borrowed from ip-button) |
72
+ | `$ip_radius_size_medium` | Border radius — fixed across sizes, matching ip-button |
73
+ | `$ip_spacing_space_025` – `$ip_spacing_space_150` | Padding and gaps per size |
74
+ | `$ip_typography_body_font_size_small` / `_medium` / `_large` | Text font size per size |
75
+ | `$ip_typography_font_family_primary` | Font family |
76
+ | `$ip_typography_font_weight_medium_500` | Text font weight |
77
+
78
+ ## CSS custom properties
79
+
80
+ | Property | Default | Role |
81
+ | --------------------- | ------- | -------------------------------------------------------------- |
82
+ | `--ip-chip-max-width` | `none` | Maximum chip width before the text truncates with an ellipsis. |
83
+
84
+ ## Usage
85
+
86
+ ### HTML
87
+
88
+ > Attribute names must be **kebab-case** in HTML: use `border-style`, not `borderStyle`.
89
+
90
+ ```js
91
+ import '@norconsult-digital-public/isypixel/web-components/ip-chip.js';
92
+ ```
93
+
94
+ ```html
95
+ <ip-chip variant="warning" border-style="dashed">
96
+ <span slot="icon">●</span>
97
+ High
98
+ </ip-chip>
99
+
100
+ <ip-chip variant="info" removable remove-label="Remove">Periodic 2 months</ip-chip>
101
+ ```
102
+
103
+ ### React
104
+
105
+ ```tsx
106
+ import { IpChip } from '@norconsult-digital-public/isypixel/web-components/react';
107
+
108
+ <IpChip variant='warning' borderStyle='dashed' onIpRemove={() => {}}>
109
+ High
110
+ </IpChip>;
111
+ ```
112
+
113
+ ### Vue
114
+
115
+ ```vue
116
+ <script setup lang="ts">
117
+ import { IpChip } from '@norconsult-digital-public/isypixel/web-components/vue';
118
+ </script>
119
+
120
+ <template>
121
+ <IpChip variant="info" removable @ipRemove="onRemove">Periodic 2 months</IpChip>
122
+ </template>
123
+ ```
124
+
125
+ ### Angular
126
+
127
+ ```ts
128
+ import { IpChip } from '@norconsult-digital-public/isypixel/web-components/angular';
129
+ ```
130
+
131
+ ```html
132
+ <ip-chip variant="success" border-style="none" (ipRemove)="onRemove()">Scheduled</ip-chip>
133
+ ```
134
+
135
+ ### Svelte
136
+
137
+ ```svelte
138
+ <script lang="ts">
139
+ import '@norconsult-digital-public/isypixel/web-components/ip-chip.js';
140
+ </script>
141
+
142
+ <ip-chip variant="error" border-style="dashed">Failure</ip-chip>
143
+ ```
144
+
145
+ ### Blazor
146
+
147
+ > Attribute names must be **kebab-case** in Blazor HTML.
148
+
149
+ Copy `ip-chip.js` to `wwwroot/lib/isypixel/components/` at build time. See `llm.md` in the package root for the MSBuild target.
150
+
151
+ ```html
152
+ <script type="module" src="lib/isypixel/components/ip-chip.js"></script>
153
+
154
+ <ip-chip variant="warning" border-style="dashed">High</ip-chip>
155
+ ```
156
+
157
+ - Boolean attributes such as `removable`, `collapsed`, `selected`, and `disabled` must be set as `removable="true"` (string value) — Blazor does not reliably render bare boolean attributes on custom elements.
@@ -0,0 +1,165 @@
1
+ # ip-chip-group
2
+
3
+ Groups `ip-chip` children under one shared interaction model. `selection-mode` decides what activating a chip does — nothing (display/grouping), select one, or select many — while `removable` on individual chips is orthogonal and adds a trailing remove button. Each chip is rendered as a **split button** (a primary action and an optional remove action as separate buttons); every button is a natural tab stop, and the group restores focus to a neighbouring chip after a keyboard-initiated removal.
4
+
5
+ **Storybook:** https://pixel.isy.no/storybook/?path=/docs/core-ui-ip-chip-group-usage--docs
6
+
7
+ > This component requires ISY Pixel global styles to render correctly. Always remind the user to verify that styles are imported in their global stylesheet. See `llm.md` in the package root for style import options.
8
+
9
+ ## The two axes
10
+
11
+ The group composes two independent things — combine them freely:
12
+
13
+ 1. **Selection** — the group's `selection-mode`: `none`, `single`, or `multiple`. A change emits `ipChange`.
14
+ 2. **Removal** — a chip's own `removable` attribute adds a remove button that emits `ipRemove` (on the chip). Independent of `selection-mode`.
15
+
16
+ | Goal | Recipe |
17
+ | ------------------------------- | -------------------------------------------------------------------------- |
18
+ | Read-only status group | `selection-mode="none"` |
19
+ | Removable tags (not selectable) | `selection-mode="none"` + chips `removable` |
20
+ | Choose one / several | `selection-mode="single"` / `"multiple"` |
21
+ | Choose several **and** remove | `selection-mode="multiple"` + `removable` + listen `ipChange` / `ipRemove` |
22
+
23
+ ## Attributes
24
+
25
+ | Attribute | Type | Default | Values | Description |
26
+ | ---------------- | ------------------- | -------------- | ---------------------------------- | ----------------------------------------------------------------------------------------------------- |
27
+ | `selection-mode` | string | `"none"` | `"none"`, `"single"`, `"multiple"` | What activating a chip does: nothing (display), select one, or select many. |
28
+ | `value` | string \| string\[] | `undefined` | Any value(s) | Selected value(s). Binding it makes the group controlled. `string` in single, `string[]` in multiple. |
29
+ | `orientation` | string | `"horizontal"` | `"horizontal"`, `"vertical"` | Visual layout direction of the chips. |
30
+ | `disabled` | boolean | `false` | `true`, `false` | Disables the whole group and all of its chips. |
31
+
32
+ **Control model** — uncontrolled by default: the group owns the selection state (and `value`, if set initially, seeds it). It becomes controlled when the consumer binds `value` and writes the new value back in the `ipChange` handler — like a native `<input>`.
33
+
34
+ **`value` typing** — a `string` in single mode (settable via the attribute), a `string[]` in multiple mode (must be set via the **property**, since an HTML attribute can only carry a string).
35
+
36
+ **Chip identity** — a chip is identified by its `value`; a chip without one falls back to its trimmed text content. Chips that share the same fallback text share one identity — selecting one selects all of them — so always set `value` on selectable chips.
37
+
38
+ ## Slots
39
+
40
+ | Slot | Description |
41
+ | --------- | ------------------------------- |
42
+ | `default` | One or more `ip-chip` elements. |
43
+
44
+ ## Events
45
+
46
+ | Event | Payload | When |
47
+ | ---------- | ------------------------------- | ---------------------------------------------------------------------------------------------- |
48
+ | `ipChange` | `{ value: string \| string[] }` | Selection changes (single/multiple only). `value` is a string in single, an array in multiple. |
49
+
50
+ > Removal is emitted as `ipRemove` on the individual `ip-chip`, not on the group.
51
+
52
+ ## Accessibility
53
+
54
+ - The group is `role="group"`. Provide an accessible name via `aria-label` or `aria-labelledby`. Orientation is visual only (a reflected `orientation` attribute drives the layout); `aria-orientation` is intentionally not set, since it is not a valid property on `role="group"`.
55
+ - **Split button** — each chip exposes a primary button and, when `removable`, a separate remove button; they are never nested, so clicking remove never also toggles selection.
56
+ - **Keyboard** — every primary and remove button is a natural tab stop; Enter/Space and click activate the focused button natively.
57
+ - **Focus restoration on removal** — when a chip is removed while its remove button holds visible keyboard focus (`:focus-visible`), the group moves focus to the next chip's remove button (or the closest previous one when the last chip was removed), so serial keyboard removal never drops focus. Pointer-initiated removals never move focus. Focus moves only after the consumer actually removes the chip from the DOM in its `ipRemove` handler.
58
+ - **Selection** — in single/multiple the primary is a toggle button with `aria-pressed`. Selection is explicit (it does not follow focus).
59
+ - In `none` mode the primary is not interactive or focusable (display only); a `removable` chip's remove button stays focusable.
60
+ - When `disabled`, the group and every chip are disabled; chips re-enable to their own prior state when the group is re-enabled.
61
+
62
+ ## Design tokens
63
+
64
+ | SCSS variable | Role |
65
+ | ----------------------- | ----------------- |
66
+ | `$ip_spacing_space_100` | Gap between chips |
67
+
68
+ ## Usage
69
+
70
+ ### HTML
71
+
72
+ ```js
73
+ import '@norconsult-digital-public/isypixel/web-components/ip-chip-group.js';
74
+ import '@norconsult-digital-public/isypixel/web-components/ip-chip.js';
75
+ ```
76
+
77
+ ```html
78
+ <!-- Filter: choose several, each removable -->
79
+ <ip-chip-group selection-mode="multiple" aria-label="Filter by status">
80
+ <ip-chip value="high" removable>High</ip-chip>
81
+ <ip-chip value="medium" removable>Medium</ip-chip>
82
+ <ip-chip value="low" removable>Low</ip-chip>
83
+ </ip-chip-group>
84
+
85
+ <!-- Removable tags, no selection -->
86
+ <ip-chip-group aria-label="Applied tags">
87
+ <ip-chip value="design" removable>Design</ip-chip>
88
+ <ip-chip value="frontend" removable>Frontend</ip-chip>
89
+ </ip-chip-group>
90
+ ```
91
+
92
+ ### React
93
+
94
+ ```tsx
95
+ import { IpChipGroup, IpChip } from '@norconsult-digital-public/isypixel/web-components/react';
96
+
97
+ <IpChipGroup selectionMode='multiple' aria-label='Tags' onIpChange={(e) => setValue(e.detail.value)}>
98
+ <IpChip value='a' removable onIpRemove={() => remove('a')}>
99
+ Design
100
+ </IpChip>
101
+ <IpChip value='b' removable onIpRemove={() => remove('b')}>
102
+ Frontend
103
+ </IpChip>
104
+ </IpChipGroup>;
105
+ ```
106
+
107
+ ### Vue
108
+
109
+ ```vue
110
+ <script setup lang="ts">
111
+ import { IpChipGroup, IpChip } from '@norconsult-digital-public/isypixel/web-components/vue';
112
+ </script>
113
+
114
+ <template>
115
+ <IpChipGroup selection-mode="single" aria-label="Priority" @ipChange="onChange">
116
+ <IpChip value="high">High</IpChip>
117
+ <IpChip value="low">Low</IpChip>
118
+ </IpChipGroup>
119
+ </template>
120
+ ```
121
+
122
+ ### Angular
123
+
124
+ ```ts
125
+ import { IpChipGroup, IpChip } from '@norconsult-digital-public/isypixel/web-components/angular';
126
+ ```
127
+
128
+ ```html
129
+ <ip-chip-group selection-mode="multiple" aria-label="Filters" (ipChange)="onChange($event)">
130
+ <ip-chip value="a" [removable]="true" (ipRemove)="remove('a')">Design</ip-chip>
131
+ <ip-chip value="b" [removable]="true" (ipRemove)="remove('b')">Frontend</ip-chip>
132
+ </ip-chip-group>
133
+ ```
134
+
135
+ ### Svelte
136
+
137
+ ```svelte
138
+ <script lang="ts">
139
+ import '@norconsult-digital-public/isypixel/web-components/ip-chip-group.js';
140
+ import '@norconsult-digital-public/isypixel/web-components/ip-chip.js';
141
+ </script>
142
+
143
+ <ip-chip-group selection-mode="multiple" aria-label="Filter">
144
+ <ip-chip value="a">A</ip-chip>
145
+ <ip-chip value="b">B</ip-chip>
146
+ </ip-chip-group>
147
+ ```
148
+
149
+ ### Blazor
150
+
151
+ > Attribute names must be **kebab-case** in Blazor HTML.
152
+
153
+ Copy `ip-chip-group.js` and `ip-chip.js` to `wwwroot/lib/isypixel/components/` at build time. See `llm.md` in the package root for the MSBuild target.
154
+
155
+ ```html
156
+ <script type="module" src="lib/isypixel/components/ip-chip-group.js"></script>
157
+ <script type="module" src="lib/isypixel/components/ip-chip.js"></script>
158
+
159
+ <ip-chip-group selection-mode="single" aria-label="Priority">
160
+ <ip-chip value="high">High</ip-chip>
161
+ <ip-chip value="low">Low</ip-chip>
162
+ </ip-chip-group>
163
+ ```
164
+
165
+ - For multiple selection, set `value` as a property (`string[]`) from your view model — an HTML attribute can only carry a single string.
@@ -0,0 +1,126 @@
1
+ # ip-icon-count
2
+
3
+ A compact inline indicator that pairs a slotted icon with a value. Use it to show a count or measurement next to a contextual icon — e.g. a paperclip with `+14` for attachments, a checklist icon with `16` for tasks, or a temperature icon with `37°C` for a sensor reading.
4
+
5
+ The component is display only: it is not interactive, emits no events, and does not participate in forms. Consumers needing click behaviour wrap it in a `<button>` or `<a>`.
6
+
7
+ **Storybook:** https://pixel.isy.no/storybook/?path=/docs/core-ui-ip-icon-count-usage--docs
8
+
9
+ > This component requires ISY Pixel global styles to render correctly. Always remind the user to verify that styles are imported in their global stylesheet. See `llm.md` in the package root for style import options.
10
+
11
+ ## Attributes
12
+
13
+ | Attribute | Type | Default | Values | Description |
14
+ | --------- | ------ | ----------- | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
15
+ | `value` | string | `""` | Any string | The value shown next to the icon. A string so `"12"`, `"+14"`, and `"37°C"` are all valid. When empty, a `-` placeholder is shown. |
16
+ | `variant` | string | `"default"` | `"default"`, `"brand"`, `"warning"`, `"error"` | Colour variant for the icon and value. |
17
+ | `size` | string | `"medium"` | `"small"`, `"medium"`, `"large"` | Size of the icon and value text. |
18
+ | `label` | string | `""` | Any string | Optional accessible label describing the value, e.g. `"12 attachments"`. Sets `aria-label` on the host. See Accessibility. |
19
+
20
+ ## Slots
21
+
22
+ | Slot | Description |
23
+ | ------ | ----------------------------------------------------------- |
24
+ | `icon` | The icon element to display. Typically an `<i>` or `<svg>`. |
25
+
26
+ ## Accessibility
27
+
28
+ - The slotted icon is decorative and marked `aria-hidden`. On its own, an icon plus a value is not descriptive to assistive technology.
29
+ - When `label` is set, the host is exposed as `role="img"` with the label as its accessible name, so screen readers announce the meaning (e.g. "12 attachments") rather than the bare value.
30
+ - When `label` is empty, the component is exposed as-is and the value text is read on its own. Provide a `label` whenever the icon carries meaning that the value alone does not convey.
31
+
32
+ ## Design tokens
33
+
34
+ > The `brand`, `warning`, and `error` variants use colours that fall below WCAG AA contrast on light surfaces (`brand`) or are non-adaptive primitive stand-ins (`warning`, `error`) because no sufficiently contrasting semantic tokens exist yet. These are marked `//TODO` in the SCSS and will be replaced with semantic, theme-aware tokens once design adds them. The same gap applies to the ip-avatar ring variants.
35
+
36
+ | SCSS variable | Role |
37
+ | --------------------------------------------------------------------------- | --------------------------------------------------------- |
38
+ | `$ip_color_text_secondary_default` | Value colour for `variant="default"` |
39
+ | `$ip_color_icon_primary_default` | Icon colour for `variant="default"` |
40
+ | `$ip_color_brand_accent_primary_default` | Icon and value colour for `variant="brand"` |
41
+ | `$ip_color_extended_orange-700` | Icon and value colour for `variant="warning"` (temporary) |
42
+ | `$ip_color_extended_red-700` | Icon and value colour for `variant="error"` (temporary) |
43
+ | `$ip_iconography_size_tiny` / `_small` / `_medium` | Icon size for `size` small / medium / large |
44
+ | `$ip_typography_mono_spaced_numbers_font_size_tiny` / `_small` / `_default` | Value font size for `size` small / medium / large |
45
+ | `$ip_typography_mono_spaced_numbers_font_family_default` | Value font family (monospace) |
46
+ | `$ip_typography_mono_spaced_numbers_font_weight_default` | Value font weight |
47
+ | `$ip_typography_mono_spaced_numbers_letter_spacing_default` | Value letter spacing |
48
+ | `$ip_radius_size_medium` | Container border radius |
49
+ | `$ip_spacing_space_075` | Gap between the icon and the value |
50
+ | `$ip_spacing_space_025` / `$ip_spacing_space_050` | Container padding (vertical / horizontal) |
51
+
52
+ ## Usage
53
+
54
+ ### HTML
55
+
56
+ ```js
57
+ import '@norconsult-digital-public/isypixel/web-components/ip-icon-count.js';
58
+ ```
59
+
60
+ ```html
61
+ <ip-icon-count value="+14" variant="default" size="medium" label="14 attachments">
62
+ <i slot="icon" class="fa-solid fa-paperclip"></i>
63
+ </ip-icon-count>
64
+ ```
65
+
66
+ ### React
67
+
68
+ ```tsx
69
+ import { IpIconCount } from '@norconsult-digital-public/isypixel/web-components/react';
70
+
71
+ <IpIconCount value='+14' variant='default' size='medium' label='14 attachments'>
72
+ <i slot='icon' className='fa-solid fa-paperclip' />
73
+ </IpIconCount>;
74
+ ```
75
+
76
+ ### Vue
77
+
78
+ ```vue
79
+ <script setup lang="ts">
80
+ import { IpIconCount } from '@norconsult-digital-public/isypixel/web-components/vue';
81
+ </script>
82
+
83
+ <template>
84
+ <IpIconCount value="+14" variant="default" size="medium" label="14 attachments">
85
+ <i slot="icon" class="fa-solid fa-paperclip" />
86
+ </IpIconCount>
87
+ </template>
88
+ ```
89
+
90
+ ### Angular
91
+
92
+ ```ts
93
+ import { IpIconCount } from '@norconsult-digital-public/isypixel/web-components/angular';
94
+ ```
95
+
96
+ ```html
97
+ <ip-icon-count value="+14" variant="default" size="medium" label="14 attachments">
98
+ <i slot="icon" class="fa-solid fa-paperclip"></i>
99
+ </ip-icon-count>
100
+ ```
101
+
102
+ ### Svelte
103
+
104
+ ```svelte
105
+ <script lang="ts">
106
+ import '@norconsult-digital-public/isypixel/web-components/ip-icon-count.js';
107
+ </script>
108
+
109
+ <ip-icon-count value="+14" variant="default" size="medium" label="14 attachments">
110
+ <i slot="icon" class="fa-solid fa-paperclip"></i>
111
+ </ip-icon-count>
112
+ ```
113
+
114
+ ### Blazor
115
+
116
+ > Attribute names must be **kebab-case** in Blazor HTML.
117
+
118
+ Copy `ip-icon-count.js` to `wwwroot/lib/isypixel/components/` at build time. See `llm.md` in the package root for the MSBuild target.
119
+
120
+ ```html
121
+ <script type="module" src="lib/isypixel/components/ip-icon-count.js"></script>
122
+
123
+ <ip-icon-count value="+14" variant="default" size="medium" label="14 attachments">
124
+ <i slot="icon" class="fa-solid fa-paperclip"></i>
125
+ </ip-icon-count>
126
+ ```
package/dist/llm.md CHANGED
@@ -169,18 +169,21 @@ In `index.html` `<body>`:
169
169
 
170
170
  ## Components
171
171
 
172
- | Component | Description | Docs |
173
- | ---------------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
174
- | `ip-button` | Clickable button with visual variants, loading state, and icon slot | `docs/web-components/ip-button/llm.md` |
175
- | `ip-icon-button` | Circular icon-only button with CSS ripple, visual variants, and loading state | `docs/web-components/ip-icon-button/llm.md` |
176
- | `ip-tooltip` | Tooltip that wraps a trigger and shows non-interactive content on hover, focus, and Escape | `docs/web-components/ip-tooltip/llm.md` |
177
- | `ip-avatar` | Theme-aware avatar with image/fallback/initials/silhouette chain, label, ring, loader, corner slots, and tooltip | `docs/web-components/ip-avatar/llm.md` |
178
- | `ip-avatar-stack` | Overlapping stack of `ip-avatar` elements with overflow collapse into a `+N` counter and a combined names label | `docs/web-components/ip-avatar-stack/llm.md` |
179
- | `ip-main-menu` | Sidebar navigation wrapper with expanded/auto-hide/collapsed desktop modes and mobile drawer | `docs/web-components/ip-main-menu/llm.md` |
180
- | `ip-main-menu-toggle` | Hamburger button for the top bar that opens the `ip-main-menu` mobile drawer via a shared store | `docs/web-components/ip-main-menu-toggle/llm.md` |
181
- | `ip-main-menu-section` | Semantic section wrapper that groups navigation items with an optional visible label | `docs/web-components/ip-main-menu-section/llm.md` |
182
- | `ip-main-menu-group` | Collapsible group of navigation items with label, icon, and animated chevron | `docs/web-components/ip-main-menu-group/llm.md` |
183
- | `ip-main-menu-item` | Individual navigation item; renders as `<a>` when `href` is provided, otherwise as `<button>` | `docs/web-components/ip-main-menu-item/llm.md` |
172
+ | Component | Description | Docs |
173
+ | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- |
174
+ | `ip-button` | Clickable button with visual variants, loading state, and icon slot | `docs/web-components/ip-button/llm.md` |
175
+ | `ip-icon-button` | Circular icon-only button with CSS ripple, visual variants, and loading state | `docs/web-components/ip-icon-button/llm.md` |
176
+ | `ip-tooltip` | Tooltip that wraps a trigger and shows non-interactive content on hover, focus, and Escape | `docs/web-components/ip-tooltip/llm.md` |
177
+ | `ip-avatar` | Theme-aware avatar with image/fallback/initials/silhouette chain, label, ring, loader, corner slots, and tooltip | `docs/web-components/ip-avatar/llm.md` |
178
+ | `ip-avatar-stack` | Overlapping stack of `ip-avatar` elements with overflow collapse into a `+N` counter and a combined names label | `docs/web-components/ip-avatar-stack/llm.md` |
179
+ | `ip-icon-count` | Compact inline indicator pairing a slotted icon with a value, e.g. an attachment count or a sensor reading | `docs/web-components/ip-icon-count/llm.md` |
180
+ | `ip-chip` | Presentational status/tag chip with orthogonal fill and border, a leading icon, a collapsed state, and a remove button | `docs/web-components/ip-chip/llm.md` |
181
+ | `ip-chip-group` | Groups `ip-chip` children as split buttons with one model: display, single, or multiple selection, plus per-chip removable, with focus restoration on keyboard removal | `docs/web-components/ip-chip-group/llm.md` |
182
+ | `ip-main-menu` | Sidebar navigation wrapper with expanded/auto-hide/collapsed desktop modes and mobile drawer | `docs/web-components/ip-main-menu/llm.md` |
183
+ | `ip-main-menu-toggle` | Hamburger button for the top bar that opens the `ip-main-menu` mobile drawer via a shared store | `docs/web-components/ip-main-menu-toggle/llm.md` |
184
+ | `ip-main-menu-section` | Semantic section wrapper that groups navigation items with an optional visible label | `docs/web-components/ip-main-menu-section/llm.md` |
185
+ | `ip-main-menu-group` | Collapsible group of navigation items with label, icon, and animated chevron | `docs/web-components/ip-main-menu-group/llm.md` |
186
+ | `ip-main-menu-item` | Individual navigation item; renders as `<a>` when `href` is provided, otherwise as `<button>` | `docs/web-components/ip-main-menu-item/llm.md` |
184
187
 
185
188
  ## Services
186
189
 
@@ -0,0 +1,67 @@
1
+ import { EventEmitter, JSX } from '../../stencil-public-runtime';
2
+ /**
3
+ * Presentational chip: a compact status/tag label with a semantic colour, orthogonal fill and border, an optional
4
+ * leading icon, a collapsed icon-only state, and an optional remove button. It owns no selection logic — when
5
+ * `ip-chip-group` makes it `interactive`, its body renders as a toggle button whose pressed state the group drives.
6
+ * The chip only emits `ipRemove`.
7
+ */
8
+ export declare class IpChip {
9
+ /** Host element, used to measure the label for truncation. */
10
+ private host;
11
+ /** Drives the chip colour (fill and icon). `neutral` is a status-less greyscale chip. */
12
+ variant: 'neutral' | 'info' | 'success' | 'warning' | 'error' | 'brand';
13
+ /** Border style. */
14
+ borderStyle: 'none' | 'solid' | 'dashed';
15
+ /** Chip size. */
16
+ size: 'small' | 'medium' | 'large';
17
+ /** Passive identity read by `ip-chip-group`. Has no effect when the chip is used standalone. */
18
+ value: string;
19
+ /** Makes the chip body a toggle button. Set by `ip-chip-group` in single/multiple mode; no effect standalone. */
20
+ interactive: boolean;
21
+ /** Visual selected state. Set by `ip-chip-group`; drives `aria-pressed` on the interactive body. */
22
+ selected: boolean;
23
+ /** Hides the text visually and shows only the icon. The text is kept for screen readers. Requires the `icon` slot. */
24
+ collapsed: boolean;
25
+ /** Shows a built-in remove button (X) as the chip's trailing action. */
26
+ removable: boolean;
27
+ /** Accessible label for the remove button. The chip text is appended where available, e.g. "Remove High". */
28
+ removeLabel: string;
29
+ /** Disables the chip and its remove button. */
30
+ disabled: boolean;
31
+ /** Tracks whether the `icon` slot has assigned content, to render the icon wrapper only when needed. */
32
+ private hasIcon;
33
+ /** Plain-text content of the chip, used for the remove button's accessible name and the tooltip. */
34
+ private labelText;
35
+ /** Whether the label is visually truncated, so the full text is offered in a tooltip. */
36
+ private isTruncated;
37
+ /** Emitted when the built-in remove button is activated. */
38
+ removeEvent: EventEmitter<void>;
39
+ /** Observes the label so truncation is re-evaluated when the chip is resized. */
40
+ private resizeObserver;
41
+ /** The label element currently observed, so the observer can follow it when a render recreates the label. */
42
+ private observedLabel;
43
+ connectedCallback(): void;
44
+ componentDidRender(): void;
45
+ disconnectedCallback(): void;
46
+ /** Moves focus to a chip segment, falling back to the other one when the requested segment is not focusable. */
47
+ setFocus(segment?: 'primary' | 'remove'): Promise<void>;
48
+ /** Records whether the icon slot has content so the icon wrapper is only rendered when an icon is present. */
49
+ private handleIconSlotChange;
50
+ /** Captures the chip's text so the remove button can be named and the full text shown in the tooltip. */
51
+ private handleLabelSlotChange;
52
+ /** Emits ipRemove and stops the click from reaching the group, so removing never also toggles selection. */
53
+ private handleRemove;
54
+ /** Keeps the observer on the current label element — a render can recreate it (the body swaps span/button). */
55
+ private observeTruncation;
56
+ /** Flags the label as truncated when its content overflows the available width. */
57
+ private measureTruncation;
58
+ /** Accessible name for the remove button: the label with the chip text appended, e.g. "Remove High". */
59
+ private get removeAccessibleName();
60
+ /** The leading icon, wrapped only when it has content so an empty wrapper is never rendered. */
61
+ private renderIcon;
62
+ /** The chip body: a toggle button when the group made it interactive, otherwise a presentational span. */
63
+ private renderBody;
64
+ /** The trailing remove button — an always-focusable action independent of the chip body. */
65
+ private renderRemove;
66
+ render(): JSX.Element;
67
+ }