@norconsult-digital-public/isypixel 2.0.2-canary.7 → 2.0.2-canary.9
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.
- package/dist/docs/web-components/ip-chip/llm.md +157 -0
- package/dist/docs/web-components/ip-chip-group/llm.md +165 -0
- package/dist/docs/web-components/ip-date-display/llm.md +161 -0
- package/dist/docs/web-components/services/locale/llm.md +62 -0
- package/dist/llm.md +21 -17
- package/dist/types/components/ip-chip/ip-chip.d.ts +67 -0
- package/dist/types/components/ip-chip-group/ip-chip-group.d.ts +80 -0
- package/dist/types/components/ip-date-display/i18n.d.ts +4 -0
- package/dist/types/components/ip-date-display/ip-date-display.d.ts +29 -0
- package/dist/types/components.d.ts +358 -0
- package/dist/types/home/runner/work/pixel/pixel/.stencil/utils/icons.d.ts +5 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/services/i18n/i18n.d.ts +3 -0
- package/dist/types/services/index.d.ts +2 -0
- package/dist/types/services/locale/locale.d.ts +23 -0
- package/dist/web-components/components/index.js +1 -1
- package/dist/web-components/components/ip-avatar-stack.js +1 -1
- package/dist/web-components/components/ip-avatar.js +1 -1
- package/dist/web-components/components/ip-button.js +1 -1
- package/dist/web-components/components/ip-chip-group.d.ts +11 -0
- package/dist/web-components/components/ip-chip-group.js +1 -0
- package/dist/web-components/components/ip-chip.d.ts +11 -0
- package/dist/web-components/components/ip-chip.js +1 -0
- package/dist/web-components/components/ip-date-display.d.ts +11 -0
- package/dist/web-components/components/ip-date-display.js +1 -0
- package/dist/web-components/components/ip-icon-button.js +1 -1
- package/dist/web-components/components/ip-icon-count.js +1 -1
- package/dist/web-components/components/ip-main-menu-group.js +1 -1
- package/dist/web-components/components/ip-main-menu-item.js +1 -1
- package/dist/web-components/components/ip-main-menu-section.js +1 -1
- package/dist/web-components/components/ip-main-menu-toggle.js +1 -1
- package/dist/web-components/components/ip-main-menu.js +1 -1
- package/dist/web-components/components/ip-tooltip.js +1 -1
- package/dist/web-components/components/p-6Y3JP5Mp.js +1 -0
- package/dist/web-components/components/{p-kvMV4IDK.js → p-8xxrpIeZ.js} +1 -1
- package/dist/web-components/components/{p-DHUR9EVo.js → p-B7OyzFE9.js} +1 -1
- package/dist/web-components/components/p-BG9BklGR.js +1 -0
- package/dist/web-components/components/{p-D7dv-vxU.js → p-BPNcFvV4.js} +1 -1
- package/dist/web-components/components/p-C7Xl2j2X.js +1 -0
- package/dist/web-components/components/p-CFwDQCcr.js +1 -0
- package/dist/web-components/components/p-CU3XMYRk.js +1 -0
- package/dist/web-components/components/{p-BB9-AZXH.js → p-D83crOsE.js} +1 -1
- package/dist/web-components/components/{p-BcC5iydm.js → p-DTh1Kvjd.js} +1 -1
- package/dist/web-components/components/{p-CYHyixFx.js → p-DVwQwKni.js} +1 -1
- package/dist/web-components/components/p-DefPpKsB.js +1 -0
- package/dist/web-components/components/p-DnTzptWz.js +1 -0
- package/dist/web-components/components/{p-DeYqZhmA.js → p-DvqClY_a.js} +1 -1
- package/dist/web-components/components/{p-Dfz1ldrQ.js → p-FtNC-zkT.js} +1 -1
- package/dist/web-components/components/{p-CV6-lWaN.js → p-U-7IBVRB.js} +1 -1
- package/dist/web-components/components/{p-DS538Bt0.js → p-VctHpAA_.js} +1 -1
- package/dist/web-components/components/p-iNLo7cGa.js +1 -0
- package/dist/web-components/components/p-npk6jupt.js +1 -0
- package/dist/web-components/components/{p-BzX4EQ1R.js → p-ntoTViAh.js} +1 -1
- package/dist/web-components/generated/angular/components.d.ts +115 -1
- package/dist/web-components/generated/angular/components.js +191 -0
- package/dist/web-components/generated/angular/components.ts +165 -0
- package/dist/web-components/generated/angular/index.d.ts +1 -1
- package/dist/web-components/generated/angular/index.js +3 -0
- package/dist/web-components/generated/angular/index.ts +3 -0
- package/dist/web-components/generated/react/components.d.ts +14 -1
- package/dist/web-components/generated/react/components.js +27 -0
- package/dist/web-components/generated/react/components.ts +37 -1
- package/dist/web-components/generated/svelte/components.d.ts +6 -0
- package/dist/web-components/generated/vue/components.d.ts +3 -0
- package/dist/web-components/generated/vue/components.js +34 -0
- package/dist/web-components/generated/vue/components.ts +40 -0
- package/llms.txt +4 -0
- package/package.json +1 -1
- package/dist/web-components/components/p-B_TLIx6P.js +0 -1
- package/dist/web-components/components/p-CAPVXUZ_.js +0 -1
- package/dist/web-components/components/p-D42v9_4Q.js +0 -1
- package/dist/web-components/components/p-DgTyjESP.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,161 @@
|
|
|
1
|
+
# ip-date-display
|
|
2
|
+
|
|
3
|
+
A presentational component that displays a date formatted for reading. It supports a selectable date detail level (`dateFormat`), optional time (`timeFormat`), and a `variant` that sets the text colour: three neutral emphasis levels or three semantic colours. An optional leading `icon` slot lets the consumer add an indicator. Use it for deadlines, completion dates, and other dates that should be emphasised by state.
|
|
4
|
+
|
|
5
|
+
The component is purely presentational: it is not interactive, emits no events, and does not participate in forms. The `variant` is set by the consumer, not computed internally.
|
|
6
|
+
|
|
7
|
+
The locale is read reactively from `PixelLocaleService`. There is no `locale` prop. Calling `PixelLocaleService.setLocale(...)` re-renders the date in the new locale automatically.
|
|
8
|
+
|
|
9
|
+
**Storybook:** https://pixel.isy.no/storybook/?path=/docs/core-ui-ip-date-display-usage--docs
|
|
10
|
+
|
|
11
|
+
> 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.
|
|
12
|
+
|
|
13
|
+
## Attributes
|
|
14
|
+
|
|
15
|
+
| Attribute | Type | Default | Values | Description |
|
|
16
|
+
| ------------ | ------ | ----------- | ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| `date` | string | `""` | ISO 8601 date or datetime | The date to display, e.g. `"2025-08-19"` or `"2025-08-19T14:30"`. Formatted internally. An empty value renders nothing; an unparseable value renders a localized "Invalid date" fallback. |
|
|
18
|
+
| `dateFormat` | string | `"short"` | `"short"`, `"medium"`, `"long"` | Date detail level. Maps to the `Intl.DateTimeFormat` `dateStyle` option. |
|
|
19
|
+
| `timeFormat` | string | `"none"` | `"none"`, `"short"`, `"medium"` | Whether and how detailed the time is shown. Maps to `Intl.DateTimeFormat` `timeStyle`; `"none"` shows no time. Only applies when `date` has a time component. |
|
|
20
|
+
| `variant` | string | `"primary"` | `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"error"` | Visual treatment. `primary`/`secondary`/`tertiary` are neutral emphasis levels; `success`/`warning`/`error` colour the date. The slotted icon inherits this colour. The semantic colour is generic: use `label` to convey its meaning. |
|
|
21
|
+
| `label` | string | `""` | Any string | Optional accessible label describing what a semantic variant means, e.g. `"Overdue"` or `"Do not start before"`. Rendered as visually hidden text. |
|
|
22
|
+
|
|
23
|
+
## Slots
|
|
24
|
+
|
|
25
|
+
| Slot | Description |
|
|
26
|
+
| ------ | ------------------------------------------------------------------------------------------------------------------------ |
|
|
27
|
+
| `icon` | Optional leading icon shown before the date. Decorative (`aria-hidden`); inherits the variant colour via `currentColor`. |
|
|
28
|
+
|
|
29
|
+
## Events
|
|
30
|
+
|
|
31
|
+
None. Purely presentational.
|
|
32
|
+
|
|
33
|
+
## Formatting
|
|
34
|
+
|
|
35
|
+
The date is formatted with `Intl.DateTimeFormat(PixelLocaleService.getLocale(), { dateStyle, timeStyle })`.
|
|
36
|
+
|
|
37
|
+
| `dateFormat` / `timeFormat` | `nb-NO` | `en-US` |
|
|
38
|
+
| --------------------------- | --------------------------- | ---------------------------- |
|
|
39
|
+
| `short` / `none` | `19.08.2025` | `8/19/25` |
|
|
40
|
+
| `short` / `short` | `19.08.2025, 14:30` | `8/19/25, 2:30 PM` |
|
|
41
|
+
| `long` / `short` | `19. august 2025 kl. 14:30` | `August 19, 2025 at 2:30 PM` |
|
|
42
|
+
|
|
43
|
+
- `timeFormat` only has an effect when `date` carries a time component (an ISO datetime such as `2025-08-19T14:30`). A date-only value ignores `timeFormat`.
|
|
44
|
+
- Date-only values are formatted in UTC so a timezone-shifted midnight cannot move the displayed calendar day.
|
|
45
|
+
- An empty `date` renders nothing. A non-empty but unparseable `date` renders a localized "Invalid date" fallback.
|
|
46
|
+
|
|
47
|
+
## Accessibility
|
|
48
|
+
|
|
49
|
+
- The date renders inside a `<time datetime="...">` element. The `datetime` attribute reflects the full ISO value passed in `date`, including the time when present.
|
|
50
|
+
- A semantic variant's colour is generic and not conveyed to assistive tech on its own. Set `label` to describe what it means (e.g. "Overdue"); it is announced as visually hidden text. Without a `label`, a semantic colour carries no meaning for screen readers.
|
|
51
|
+
- The slotted `icon` is decorative and marked `aria-hidden`. It reinforces the variant visually but carries no meaning for screen readers.
|
|
52
|
+
- When `date` is unparseable, the fallback renders only the localized "Invalid date" text: neither the slotted `icon` nor a `label` is shown, since neither applies to an error state.
|
|
53
|
+
|
|
54
|
+
## Localisation
|
|
55
|
+
|
|
56
|
+
The visible "Invalid date" fallback ships in English and Norwegian (`nb-NO`) and is resolved through `PixelI18nService`, the same mechanism as other Pixel components. Override it with `PixelI18nService.setCustomLanguage({ 'ip-date-display': { ... } })`. The `label` is not localised by the component: the consumer supplies it in the correct language.
|
|
57
|
+
|
|
58
|
+
| Key | `en` | `nb-NO` |
|
|
59
|
+
| ------------- | ------------ | ------------ |
|
|
60
|
+
| `invalidDate` | Invalid date | Ugyldig dato |
|
|
61
|
+
|
|
62
|
+
## Design tokens
|
|
63
|
+
|
|
64
|
+
> The `success`, `warning`, and `error` variants use temporary non-adaptive primitive stand-ins. No contrast-approved semantic tokens for these exist in Figma yet, so suitable `extended/*` shades are used and marked `//TODO` in the SCSS. The final tokens and WCAG contrast are resolved in the post-summer design cleanup.
|
|
65
|
+
|
|
66
|
+
| SCSS variable | Role |
|
|
67
|
+
| ----------------------------------------- | ----------------------------------------------- |
|
|
68
|
+
| `$ip_color_text_primary_black` | Text colour for `variant="primary"` |
|
|
69
|
+
| `$ip_color_text_secondary_default` | Text colour for `variant="secondary"` |
|
|
70
|
+
| `$ip_color_text_tertiary_default` | Text colour for `variant="tertiary"` |
|
|
71
|
+
| `$ip_color_extended_green-950` | Text colour for `variant="success"` (temporary) |
|
|
72
|
+
| `$ip_color_extended_yellow-950` | Text colour for `variant="warning"` (temporary) |
|
|
73
|
+
| `$ip_color_extended_red-600` | Text colour for `variant="error"` (temporary) |
|
|
74
|
+
| `$ip_typography_body_font_family_default` | Date font family |
|
|
75
|
+
| `$ip_typography_body_font_size_small` | Date font size |
|
|
76
|
+
| `$ip_typography_body_font_weight_default` | Date font weight |
|
|
77
|
+
| `$ip_spacing_space_100` | Gap between a slotted icon and the date |
|
|
78
|
+
|
|
79
|
+
## Usage
|
|
80
|
+
|
|
81
|
+
### HTML
|
|
82
|
+
|
|
83
|
+
```js
|
|
84
|
+
import '@norconsult-digital-public/isypixel/web-components/ip-date-display.js';
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
```html
|
|
88
|
+
<ip-date-display date="2025-08-19" date-format="long" variant="error" label="Overdue">
|
|
89
|
+
<i slot="icon" class="fas fa-triangle-exclamation"></i>
|
|
90
|
+
</ip-date-display>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### React
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
import { IpDateDisplay } from '@norconsult-digital-public/isypixel/web-components/react';
|
|
97
|
+
|
|
98
|
+
<IpDateDisplay date='2025-08-19' dateFormat='long' variant='error' label='Overdue'>
|
|
99
|
+
<i slot='icon' className='fas fa-triangle-exclamation' />
|
|
100
|
+
</IpDateDisplay>;
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Vue
|
|
104
|
+
|
|
105
|
+
```vue
|
|
106
|
+
<script setup lang="ts">
|
|
107
|
+
import { IpDateDisplay } from '@norconsult-digital-public/isypixel/web-components/vue';
|
|
108
|
+
</script>
|
|
109
|
+
|
|
110
|
+
<template>
|
|
111
|
+
<IpDateDisplay date="2025-08-19" date-format="long" variant="error" label="Overdue">
|
|
112
|
+
<i slot="icon" class="fas fa-triangle-exclamation" />
|
|
113
|
+
</IpDateDisplay>
|
|
114
|
+
</template>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Angular
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
import { IpDateDisplay } from '@norconsult-digital-public/isypixel/web-components/angular';
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
```html
|
|
124
|
+
<ip-date-display date="2025-08-19" date-format="long" variant="error" label="Overdue">
|
|
125
|
+
<i slot="icon" class="fas fa-triangle-exclamation"></i>
|
|
126
|
+
</ip-date-display>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Svelte
|
|
130
|
+
|
|
131
|
+
```svelte
|
|
132
|
+
<script lang="ts">
|
|
133
|
+
import '@norconsult-digital-public/isypixel/web-components/ip-date-display.js';
|
|
134
|
+
</script>
|
|
135
|
+
|
|
136
|
+
<ip-date-display date="2025-08-19" date-format="long" variant="error" label="Overdue">
|
|
137
|
+
<i slot="icon" class="fas fa-triangle-exclamation"></i>
|
|
138
|
+
</ip-date-display>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Blazor
|
|
142
|
+
|
|
143
|
+
> Attribute names must be **kebab-case** in Blazor HTML.
|
|
144
|
+
|
|
145
|
+
Copy `ip-date-display.js` to `wwwroot/lib/isypixel/components/` at build time. See `llm.md` in the package root for the MSBuild target.
|
|
146
|
+
|
|
147
|
+
```html
|
|
148
|
+
<script type="module" src="lib/isypixel/components/ip-date-display.js"></script>
|
|
149
|
+
|
|
150
|
+
<ip-date-display date="2025-08-19" date-format="long" variant="error" label="Overdue">
|
|
151
|
+
<i slot="icon" class="fas fa-triangle-exclamation"></i>
|
|
152
|
+
</ip-date-display>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Set the locale
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
import { PixelLocaleService } from '@norconsult-digital-public/isypixel/web-components/services';
|
|
159
|
+
|
|
160
|
+
PixelLocaleService.setLocale('nb-NO'); // all mounted ip-date-display elements re-render
|
|
161
|
+
```
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# PixelLocaleService
|
|
2
|
+
|
|
3
|
+
Static service holding the application's active formatting locale. Used by components that format values with `Intl` (dates now; numbers, currency, and relative time later). Independent of `PixelI18nService`: locale owns formatting (an open BCP 47 set), i18n owns translations (a closed language set).
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { PixelLocaleService } from '@norconsult-digital-public/isypixel/web-components/services';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## API
|
|
12
|
+
|
|
13
|
+
All methods operate on a reactive `@stencil/store`. Calling `setLocale` or `resetLocale` triggers an **automatic re-render** of every mounted Pixel component that reads the locale in `render()`. No page reload, no manual refresh.
|
|
14
|
+
|
|
15
|
+
| Method | Signature | Description |
|
|
16
|
+
| ------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
17
|
+
| `setLocale` | `(locale: string) => void` | Sets the active locale (BCP 47, e.g. `'nb-NO'`, `'en-US'`). Expects a valid locale string; the input is not validated at runtime. Re-renders all components using it. |
|
|
18
|
+
| `resetLocale` | `() => void` | Clears the active locale so formatting follows the runtime/browser locale again. Re-renders all components using it. |
|
|
19
|
+
| `getLocale` | `() => string \| undefined` | Returns the current locale. `undefined` means formatting follows the environment. |
|
|
20
|
+
|
|
21
|
+
## Behaviour
|
|
22
|
+
|
|
23
|
+
- **Default:** no locale set. Formatting follows the browser/runtime locale (`Intl` called with `undefined`). Call `resetLocale` to return to this state.
|
|
24
|
+
- **Type:** `string`. No closed enum. BCP 47 is an open set; the library does not maintain a list of allowed locales.
|
|
25
|
+
- **Reactivity:** internal `@stencil/store`, same principle as i18n. Components read the locale inside `render()` and re-render automatically on `setLocale` or `resetLocale`.
|
|
26
|
+
|
|
27
|
+
## Usage examples
|
|
28
|
+
|
|
29
|
+
### Set the locale
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { PixelLocaleService } from '@norconsult-digital-public/isypixel/web-components/services';
|
|
33
|
+
|
|
34
|
+
PixelLocaleService.setLocale('nb-NO');
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Follow the environment
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
PixelLocaleService.resetLocale();
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Read the current locale
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
const locale = PixelLocaleService.getLocale(); // 'nb-NO' | undefined
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Blazor
|
|
50
|
+
|
|
51
|
+
Locale is JavaScript-only. Call from a JS interop entry point or a `.js` file loaded in `index.html`:
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
import { PixelLocaleService } from '@norconsult-digital-public/isypixel/web-components/services';
|
|
55
|
+
PixelLocaleService.setLocale('nb-NO');
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Notes
|
|
59
|
+
|
|
60
|
+
- `PixelLocaleService` is intentionally decoupled from `PixelI18nService`. Setting the language does not change the locale, and vice versa. Set both if an app switches its whole UI language.
|
|
61
|
+
- `setLocale` expects a valid BCP 47 string; the input is not validated at runtime. To follow the environment again, call `resetLocale` rather than passing a sentinel value.
|
|
62
|
+
- Reactivity is powered by `@stencil/store`. Components that read `getLocale()` inside `render()` are automatically tracked and re-rendered when `setLocale` or `resetLocale` is called. No manual subscription is required.
|
package/dist/llm.md
CHANGED
|
@@ -169,26 +169,30 @@ In `index.html` `<body>`:
|
|
|
169
169
|
|
|
170
170
|
## Components
|
|
171
171
|
|
|
172
|
-
| Component | Description
|
|
173
|
-
| ---------------------- |
|
|
174
|
-
| `ip-button` | Clickable button with visual variants, loading state, and icon slot
|
|
175
|
-
| `ip-icon-button` | Circular icon-only button with CSS ripple, visual variants, and loading state
|
|
176
|
-
| `ip-tooltip` | Tooltip that wraps a trigger and shows non-interactive content on hover, focus, and Escape
|
|
177
|
-
| `ip-avatar` | Theme-aware avatar with image/fallback/initials/silhouette chain, label, ring, loader, corner slots, and tooltip
|
|
178
|
-
| `ip-avatar-stack` | Overlapping stack of `ip-avatar` elements with overflow collapse into a `+N` counter and a combined names label
|
|
179
|
-
| `ip-icon-count` | Compact inline indicator pairing a slotted icon with a value, e.g. an attachment count or a sensor reading
|
|
180
|
-
| `ip-
|
|
181
|
-
| `ip-
|
|
182
|
-
| `ip-
|
|
183
|
-
| `ip-main-menu
|
|
184
|
-
| `ip-main-menu-
|
|
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-date-display` | Presentational date display with selectable detail, optional time, a `variant` for neutral emphasis or a semantic colour, and an optional leading icon slot; locale read reactively from `PixelLocaleService` | `docs/web-components/ip-date-display/llm.md` |
|
|
183
|
+
| `ip-main-menu` | Sidebar navigation wrapper with expanded/auto-hide/collapsed desktop modes and mobile drawer | `docs/web-components/ip-main-menu/llm.md` |
|
|
184
|
+
| `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` |
|
|
185
|
+
| `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` |
|
|
186
|
+
| `ip-main-menu-group` | Collapsible group of navigation items with label, icon, and animated chevron | `docs/web-components/ip-main-menu-group/llm.md` |
|
|
187
|
+
| `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` |
|
|
185
188
|
|
|
186
189
|
## Services
|
|
187
190
|
|
|
188
|
-
| Service
|
|
189
|
-
|
|
|
190
|
-
| `PixelThemeService`
|
|
191
|
-
| `PixelI18nService`
|
|
191
|
+
| Service | Description | Docs |
|
|
192
|
+
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- |
|
|
193
|
+
| `PixelThemeService` | Static service for managing light/dark theme. Persists choice in localStorage | `docs/services/theme-service/llm.md` |
|
|
194
|
+
| `PixelI18nService` | Static i18n service for translating built-in component strings. Supports built-in languages and custom language injection | `docs/web-components/services/i18n/llm.md` |
|
|
195
|
+
| `PixelLocaleService` | Static service holding the active formatting locale for `Intl`-based components (dates now; numbers, currency later). Reactive, decoupled from i18n | `docs/web-components/services/locale/llm.md` |
|
|
192
196
|
|
|
193
197
|
## Migration guides
|
|
194
198
|
|