@norconsult-digital-public/isypixel 2.0.2-canary.5 → 2.0.2-canary.7
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-avatar/llm.md +27 -21
- package/dist/docs/web-components/ip-avatar-stack/llm.md +169 -0
- package/dist/docs/web-components/ip-icon-count/llm.md +126 -0
- package/dist/llm.md +2 -0
- package/dist/types/components/ip-avatar-stack/ip-avatar-stack.d.ts +96 -0
- package/dist/types/components/ip-icon-count/ip-icon-count.d.ts +14 -0
- package/dist/types/components.d.ts +215 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/web-components/components/index.js +1 -1
- package/dist/web-components/components/ip-avatar-stack.d.ts +11 -0
- package/dist/web-components/components/ip-avatar-stack.js +1 -0
- 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-icon-button.js +1 -1
- package/dist/web-components/components/ip-icon-count.d.ts +11 -0
- package/dist/web-components/components/ip-icon-count.js +1 -0
- 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-CWbwcDHB.js → p-B_TLIx6P.js} +1 -1
- package/dist/web-components/components/{p-C7Kf2aED.js → p-BcC5iydm.js} +1 -1
- package/dist/web-components/components/{p-DpQ72I9n.js → p-BzX4EQ1R.js} +1 -1
- package/dist/web-components/components/p-CV6-lWaN.js +1 -0
- package/dist/web-components/components/{p-DrSqAb5O.js → p-CYHyixFx.js} +1 -1
- package/dist/web-components/components/p-D7dv-vxU.js +1 -0
- package/dist/web-components/components/{p-B1x6AHw9.js → p-DS538Bt0.js} +1 -1
- package/dist/web-components/components/{p-CSHQqNXM.js → p-DeYqZhmA.js} +1 -1
- package/dist/web-components/components/{p-uroVS1GL.js → p-Dfz1ldrQ.js} +1 -1
- package/dist/web-components/components/{p-B7DtfC4M.js → p-DgTyjESP.js} +1 -1
- package/dist/web-components/components/{p-CPd0stBB.js → p-kvMV4IDK.js} +1 -1
- package/dist/web-components/generated/angular/components.d.ts +79 -0
- package/dist/web-components/generated/angular/components.js +132 -0
- package/dist/web-components/generated/angular/components.ts +111 -0
- package/dist/web-components/generated/angular/index.d.ts +1 -1
- package/dist/web-components/generated/angular/index.js +2 -0
- package/dist/web-components/generated/angular/index.ts +2 -0
- package/dist/web-components/generated/react/components.d.ts +9 -1
- package/dist/web-components/generated/react/components.js +18 -0
- package/dist/web-components/generated/react/components.ts +25 -1
- package/dist/web-components/generated/svelte/components.d.ts +4 -0
- package/dist/web-components/generated/vue/components.d.ts +2 -0
- package/dist/web-components/generated/vue/components.js +23 -0
- package/dist/web-components/generated/vue/components.ts +27 -0
- package/llms.txt +2 -0
- package/package.json +1 -1
|
@@ -72,27 +72,33 @@ A theme-aware user avatar. It shows a profile image with a fallback chain (prima
|
|
|
72
72
|
|
|
73
73
|
> The avatar reuses generic semantic tokens as theme-aware stand-ins; a dedicated avatar token family (background, foreground, ring, container hover/selected) does not exist yet. Avatar sizes are literal pixel values for the same reason. These are marked `//TODO` in the SCSS and will be replaced once design adds the avatar tokens.
|
|
74
74
|
|
|
75
|
-
| SCSS variable | Role
|
|
76
|
-
| ------------------------------------------------------------ |
|
|
77
|
-
| `$ip_color_surface_primary_default` | Ring layer background behind the ring gap
|
|
78
|
-
| `$ip_color_text_primary_blue` | Foreground colour: initials, silhouette, loader, and default ring
|
|
79
|
-
| `$ip_color_border_opaque_15` | No-image background behind initials / silhouette
|
|
80
|
-
| `$ip_color_border_opaque_10` | Clickable container hover background and the stripe overlay
|
|
81
|
-
| `$ip_color_border_opaque_20` | Selected container background
|
|
82
|
-
| `$ip_color_button_focus_default` | Focus ring when `clickable`
|
|
83
|
-
| `$ip_color_brand_accent_primary_default` | Ring colour for `ring-variant="brand"`
|
|
84
|
-
| `$ip_color_extended_green-500` | Ring colour for `ring-variant="success"`
|
|
85
|
-
| `$ip_color_extended_yellow-500` | Ring colour for `ring-variant="warning"`
|
|
86
|
-
| `$ip_color_extended_red-500` | Ring colour for `ring-variant="error"`
|
|
87
|
-
| `$ip_color_text_primary_black` |
|
|
88
|
-
| `$ip_radius_size_small` | Framed container and focus-ring radius
|
|
89
|
-
| `$ip_spacing_space_050` / `$ip_spacing_space_200` | Framed container padding
|
|
90
|
-
| `$ip_spacing_space_100` / `_200` / `_300` | Avatar↔label gap defaults for small / medium / large
|
|
91
|
-
| `$ip_typography_body_font_size_small` / `_medium` / `_large` | Initials and label font size per size
|
|
92
|
-
| `$ip_typography_body_line_height_compact` | Line height for the name and caption lines
|
|
93
|
-
| `$ip_typography_font_family_primary` | Font family for initials and label
|
|
94
|
-
| `$ip_typography_font_weight_bold_700` | Initials font weight
|
|
95
|
-
| `$ip_typography_font_weight_light_300` | Caption and placeholder font weight (italic)
|
|
75
|
+
| SCSS variable | Role |
|
|
76
|
+
| ------------------------------------------------------------ | ------------------------------------------------------------------------ |
|
|
77
|
+
| `$ip_color_surface_primary_default` | Ring layer background behind the ring gap |
|
|
78
|
+
| `$ip_color_text_primary_blue` | Foreground colour: initials, silhouette, loader, and default ring |
|
|
79
|
+
| `$ip_color_border_opaque_15` | No-image background behind initials / silhouette |
|
|
80
|
+
| `$ip_color_border_opaque_10` | Clickable container hover background and the stripe overlay |
|
|
81
|
+
| `$ip_color_border_opaque_20` | Selected container background |
|
|
82
|
+
| `$ip_color_button_focus_default` | Focus ring when `clickable` |
|
|
83
|
+
| `$ip_color_brand_accent_primary_default` | Ring colour for `ring-variant="brand"` |
|
|
84
|
+
| `$ip_color_extended_green-500` | Ring colour for `ring-variant="success"` |
|
|
85
|
+
| `$ip_color_extended_yellow-500` | Ring colour for `ring-variant="warning"` |
|
|
86
|
+
| `$ip_color_extended_red-500` | Ring colour for `ring-variant="error"` |
|
|
87
|
+
| `$ip_color_text_primary_black` | Default label (name) text colour; override with `--ip-avatar-text-color` |
|
|
88
|
+
| `$ip_radius_size_small` | Framed container and focus-ring radius |
|
|
89
|
+
| `$ip_spacing_space_050` / `$ip_spacing_space_200` | Framed container padding |
|
|
90
|
+
| `$ip_spacing_space_100` / `_200` / `_300` | Avatar↔label gap defaults for small / medium / large |
|
|
91
|
+
| `$ip_typography_body_font_size_small` / `_medium` / `_large` | Initials and label font size per size |
|
|
92
|
+
| `$ip_typography_body_line_height_compact` | Line height for the name and caption lines |
|
|
93
|
+
| `$ip_typography_font_family_primary` | Font family for initials and label |
|
|
94
|
+
| `$ip_typography_font_weight_bold_700` | Initials font weight |
|
|
95
|
+
| `$ip_typography_font_weight_light_300` | Caption and placeholder font weight (italic) |
|
|
96
|
+
|
|
97
|
+
## CSS custom properties
|
|
98
|
+
|
|
99
|
+
| Property | Default | Role |
|
|
100
|
+
| ------------------------ | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
101
|
+
| `--ip-avatar-text-color` | `$ip_color_text_primary_black` | Label (name and caption) text colour. Set to `currentColor` so the label inherits its surroundings — e.g. on a dark surface such as inside a tooltip. |
|
|
96
102
|
|
|
97
103
|
## Usage
|
|
98
104
|
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# ip-avatar-stack
|
|
2
|
+
|
|
3
|
+
A stacked-avatar component that overlaps multiple `ip-avatar` instances and shows a combined names label (the first person's name plus a `+N` count for the rest). Consumers place `ip-avatar` elements in the default slot; the stack manages the overlap, the overflow collapse into a `+N` counter, and the label. It reuses each avatar's own ring to keep the overlapping circles visually distinct.
|
|
4
|
+
|
|
5
|
+
**Storybook:** https://pixel.isy.no/storybook/?path=/docs/core-ui-ip-avatar-stack-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
|
+
> Place `ip-avatar` elements in the default slot. The stack forces each slotted avatar to `image-only`, so you do not need to set `mode` yourself. In `label-mode="name"` the stack reads the first avatar's `name` for the text label, so set `name` on at least the first avatar. Match each avatar's `size` to the stack's `size` so the circles align.
|
|
10
|
+
|
|
11
|
+
## Attributes
|
|
12
|
+
|
|
13
|
+
| Attribute | Type | Default | Values | Description |
|
|
14
|
+
| ----------------- | ------- | ----------- | -------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
15
|
+
| `max` | number | `3` | Any integer ≥ 1 | Maximum number of avatars rendered (the hard cap). Surplus avatars are hidden; in `label-mode="counter"` they collapse into a `+N` counter circle (N = total − visible). |
|
|
16
|
+
| `auto-fit` | boolean | `true` | `true`, `false` | Reduces the visible avatars to fit the container width, collapsing the rest like `max` does (`max` stays the cap). Set `false` for a fixed stack that always shows up to `max`. |
|
|
17
|
+
| `size` | string | `"medium"` | `"small"`, `"medium"`, `"large"`, `"custom"` | Stack size: drives the overflow counter size (small 40px, medium 50px, large 64px) and the default overlap. |
|
|
18
|
+
| `custom-size` | string | `undefined` | Any CSS length | Diameter of the overflow counter when `size="custom"`, applied to both width and height. |
|
|
19
|
+
| `overlap` | string | `undefined` | Any CSS length | Overrides the overlap offset between circles. Defaults scale with `size` (small 20px, medium 24px, large 30px). |
|
|
20
|
+
| `label-mode` | string | `"name"` | `"name"`, `"counter"`, `"none"` | How the group is summarised. `name`: first name + `+N` rest text label. `counter`: a `+N` counter circle in the stack. `none`: nothing. The counter circle and the text label are mutually exclusive. |
|
|
21
|
+
| `gap` | string | `undefined` | Any CSS length | Overrides the gap between the stack and the label. Defaults scale with `size`. |
|
|
22
|
+
| `preview-avatars` | boolean | `true` | `true`, `false` | Whether the tooltip previews (the counter preview and the names-label tooltip) show a small avatar beside each person. Set `false` for a compact, name-only list. |
|
|
23
|
+
| `clickable` | boolean | `false` | `true`, `false` | Makes the `+N` overflow counter (in `label-mode="counter"`) focusable, keyboard-activatable, and emits `ipOverflowClick`. |
|
|
24
|
+
| `disabled` | boolean | `false` | `true`, `false` | Greys out the stack and, when `clickable`, prevents activation of the overflow counter. |
|
|
25
|
+
|
|
26
|
+
**Counter mode** — In `label-mode="counter"`, when more avatars are slotted than are shown, the visible avatars are shown (up to `max`, or fewer with `auto-fit`) and the remainder collapse into a single `+N` counter circle appended to the stack, where N = total − visible. No text label is shown. The collapsed avatars are hidden from the layout and the accessibility tree. Hovering or focusing the counter opens a tooltip previewing the collapsed people. The preview reads `name`, `src`, and `caption` from the collapsed `ip-avatar` elements; by default each row shows a small `ip-avatar` with its name and caption, or just the name and caption when `preview-avatars="false"`.
|
|
27
|
+
|
|
28
|
+
**Auto-fit** — On by default. The stack measures its container width and shows as many avatars as fit, collapsing the rest into the `+N` counter (counter mode) or reflecting them in the `+N` text (name mode). `max` remains the upper cap, so the visible count is never more than `max` and adapts down as the container narrows. It needs a width-constrained ancestor to measure against; place the stack in its own container for best results. Set `auto-fit="false"` for a fixed stack that always shows up to `max`.
|
|
29
|
+
|
|
30
|
+
**Names label** — In `label-mode="name"` the text label reads the first slotted avatar's `name` and appends `+N`, where N is the number of remaining avatars (total − 1), e.g. `Markus Halvorsen +2` for three avatars. This mode shows no counter circle. When more than one avatar is slotted, hovering the label opens a tooltip listing every slotted person (not just the overflow), using the same preview rows as counter mode and honouring `preview-avatars`.
|
|
31
|
+
|
|
32
|
+
## Slots
|
|
33
|
+
|
|
34
|
+
| Slot | Description |
|
|
35
|
+
| ---------- | ---------------------------------------------------------------------------------- |
|
|
36
|
+
| `default` | The `ip-avatar` elements to stack. Non-`ip-avatar` nodes are ignored. |
|
|
37
|
+
| `label` | Overrides the auto-generated text label. Shown in `label-mode="name"`. |
|
|
38
|
+
| `overflow` | Overrides the content of the `+N` counter circle. Shown in `label-mode="counter"`. |
|
|
39
|
+
|
|
40
|
+
## Events
|
|
41
|
+
|
|
42
|
+
| Event | Payload | When |
|
|
43
|
+
| ----------------- | ------- | ---------------------------------------------------------------------------------------------- |
|
|
44
|
+
| `ipOverflowClick` | `void` | A `clickable` overflow counter is activated by mouse or keyboard. Not emitted when `disabled`. |
|
|
45
|
+
|
|
46
|
+
## Accessibility
|
|
47
|
+
|
|
48
|
+
- The overlap and paint order are presentational only; each slotted `ip-avatar` keeps its own accessible name and tooltip.
|
|
49
|
+
- Avatars collapsed into the `+N` counter are hidden from the accessibility tree; their names are surfaced through the counter's tooltip preview instead.
|
|
50
|
+
- When `clickable`, the overflow counter exposes `role="button"`, is focusable (`tabindex="0"`), shows a `:focus-visible` ring, is activated with Enter or Space, and carries an `aria-label` describing how many more there are.
|
|
51
|
+
- When `disabled`, a clickable counter sets `aria-disabled="true"` and blocks `ipOverflowClick`.
|
|
52
|
+
|
|
53
|
+
## Design tokens
|
|
54
|
+
|
|
55
|
+
> The stack reuses generic semantic tokens as theme-aware stand-ins; a dedicated avatar token family (background, foreground, ring, sizes, overlap) does not exist yet. Counter sizes and overlap offsets are literal pixel values for the same reason. These are marked `//TODO` in the SCSS and will be replaced once design adds the avatar tokens.
|
|
56
|
+
|
|
57
|
+
| SCSS variable | Role |
|
|
58
|
+
| ------------------------------------------------------------ | ---------------------------------------------------------- |
|
|
59
|
+
| `$ip_color_surface_primary_default` | Overflow counter ring layer background behind the ring gap |
|
|
60
|
+
| `$ip_color_text_primary_blue` | Overflow counter ring colour and `+N` text colour |
|
|
61
|
+
| `$ip_color_border_opaque_15` | Overflow counter inner background behind the `+N` text |
|
|
62
|
+
| `$ip_color_button_focus_default` | Focus ring of the overflow counter when `clickable` |
|
|
63
|
+
| `$ip_color_text_tertiary_default` | Names label text colour |
|
|
64
|
+
| `$ip_spacing_space_100` / `_200` / `_300` | Stack↔label gap defaults for small / medium / large |
|
|
65
|
+
| `$ip_typography_body_font_size_small` / `_medium` / `_large` | Counter and label font size per size |
|
|
66
|
+
| `$ip_typography_body_line_height_compact` | Label line height |
|
|
67
|
+
| `$ip_typography_font_family_primary` | Font family for the counter and label |
|
|
68
|
+
| `$ip_typography_font_weight_bold_700` | `+N` counter font weight |
|
|
69
|
+
|
|
70
|
+
## Usage
|
|
71
|
+
|
|
72
|
+
### HTML
|
|
73
|
+
|
|
74
|
+
> Attribute names must be **kebab-case** in HTML: use `label-mode`, not `labelMode`.
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
import '@norconsult-digital-public/isypixel/web-components/ip-avatar-stack.js';
|
|
78
|
+
import '@norconsult-digital-public/isypixel/web-components/ip-avatar.js';
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```html
|
|
82
|
+
<ip-avatar-stack max="3" size="medium" label-mode="name">
|
|
83
|
+
<ip-avatar name="Markus Halvorsen" src="/users/markus.jpg"></ip-avatar>
|
|
84
|
+
<ip-avatar name="Mia Berg" src="/users/mia.jpg"></ip-avatar>
|
|
85
|
+
<ip-avatar name="Jonas Lie" src="/users/jonas.jpg"></ip-avatar>
|
|
86
|
+
<ip-avatar name="Sara Nilsen"></ip-avatar>
|
|
87
|
+
</ip-avatar-stack>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### React
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
import { IpAvatarStack, IpAvatar } from '@norconsult-digital-public/isypixel/web-components/react';
|
|
94
|
+
|
|
95
|
+
<IpAvatarStack max={3} size='medium' labelMode='name' clickable onIpOverflowClick={() => {}}>
|
|
96
|
+
<IpAvatar name='Markus Halvorsen' src='/users/markus.jpg' />
|
|
97
|
+
<IpAvatar name='Mia Berg' src='/users/mia.jpg' />
|
|
98
|
+
<IpAvatar name='Jonas Lie' src='/users/jonas.jpg' />
|
|
99
|
+
<IpAvatar name='Sara Nilsen' />
|
|
100
|
+
</IpAvatarStack>;
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Vue
|
|
104
|
+
|
|
105
|
+
```vue
|
|
106
|
+
<script setup lang="ts">
|
|
107
|
+
import { IpAvatarStack, IpAvatar } from '@norconsult-digital-public/isypixel/web-components/vue';
|
|
108
|
+
</script>
|
|
109
|
+
|
|
110
|
+
<template>
|
|
111
|
+
<IpAvatarStack :max="3" size="medium" label-mode="name">
|
|
112
|
+
<IpAvatar name="Markus Halvorsen" src="/users/markus.jpg" />
|
|
113
|
+
<IpAvatar name="Mia Berg" src="/users/mia.jpg" />
|
|
114
|
+
<IpAvatar name="Jonas Lie" src="/users/jonas.jpg" />
|
|
115
|
+
<IpAvatar name="Sara Nilsen" />
|
|
116
|
+
</IpAvatarStack>
|
|
117
|
+
</template>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Angular
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
import { IpAvatarStack, IpAvatar } from '@norconsult-digital-public/isypixel/web-components/angular';
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
```html
|
|
127
|
+
<ip-avatar-stack [max]="3" size="medium" label-mode="name" clickable (ipOverflowClick)="onShowAll()">
|
|
128
|
+
<ip-avatar name="Markus Halvorsen" [src]="markusUrl"></ip-avatar>
|
|
129
|
+
<ip-avatar name="Mia Berg" [src]="miaUrl"></ip-avatar>
|
|
130
|
+
<ip-avatar name="Jonas Lie" [src]="jonasUrl"></ip-avatar>
|
|
131
|
+
<ip-avatar name="Sara Nilsen"></ip-avatar>
|
|
132
|
+
</ip-avatar-stack>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Svelte
|
|
136
|
+
|
|
137
|
+
```svelte
|
|
138
|
+
<script lang="ts">
|
|
139
|
+
import '@norconsult-digital-public/isypixel/web-components/ip-avatar-stack.js';
|
|
140
|
+
import '@norconsult-digital-public/isypixel/web-components/ip-avatar.js';
|
|
141
|
+
</script>
|
|
142
|
+
|
|
143
|
+
<ip-avatar-stack max="3" size="medium" label-mode="name">
|
|
144
|
+
<ip-avatar name="Markus Halvorsen" src="/users/markus.jpg"></ip-avatar>
|
|
145
|
+
<ip-avatar name="Mia Berg" src="/users/mia.jpg"></ip-avatar>
|
|
146
|
+
<ip-avatar name="Jonas Lie" src="/users/jonas.jpg"></ip-avatar>
|
|
147
|
+
<ip-avatar name="Sara Nilsen"></ip-avatar>
|
|
148
|
+
</ip-avatar-stack>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Blazor
|
|
152
|
+
|
|
153
|
+
> Attribute names must be **kebab-case** in Blazor HTML.
|
|
154
|
+
|
|
155
|
+
Copy `ip-avatar-stack.js` and `ip-avatar.js` to `wwwroot/lib/isypixel/components/` at build time. See `llm.md` in the package root for the MSBuild target.
|
|
156
|
+
|
|
157
|
+
```html
|
|
158
|
+
<script type="module" src="lib/isypixel/components/ip-avatar-stack.js"></script>
|
|
159
|
+
<script type="module" src="lib/isypixel/components/ip-avatar.js"></script>
|
|
160
|
+
|
|
161
|
+
<ip-avatar-stack max="3" size="medium" label-mode="name">
|
|
162
|
+
<ip-avatar name="Markus Halvorsen" src="/users/markus.jpg"></ip-avatar>
|
|
163
|
+
<ip-avatar name="Mia Berg" src="/users/mia.jpg"></ip-avatar>
|
|
164
|
+
<ip-avatar name="Jonas Lie" src="/users/jonas.jpg"></ip-avatar>
|
|
165
|
+
<ip-avatar name="Sara Nilsen"></ip-avatar>
|
|
166
|
+
</ip-avatar-stack>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
- Boolean attributes such as `clickable` and `disabled` must be set as `clickable="true"` (string value) — Blazor does not reliably render bare boolean attributes on custom elements.
|
|
@@ -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
|
@@ -175,6 +175,8 @@ In `index.html` `<body>`:
|
|
|
175
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
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
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` |
|
|
178
180
|
| `ip-main-menu` | Sidebar navigation wrapper with expanded/auto-hide/collapsed desktop modes and mobile drawer | `docs/web-components/ip-main-menu/llm.md` |
|
|
179
181
|
| `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` |
|
|
180
182
|
| `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` |
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { EventEmitter, JSX } from '../../stencil-public-runtime';
|
|
2
|
+
export declare class IpAvatarStack {
|
|
3
|
+
/** Host element, used to keep the stacking layout in sync when layout props change. */
|
|
4
|
+
private host;
|
|
5
|
+
/** Maximum number of avatars shown before the rest collapse into a `+N` counter. Acts as the hard cap; with `auto-fit` on, fewer may show. */
|
|
6
|
+
max: number;
|
|
7
|
+
/** Reduces the visible avatars to fit the container width, collapsing the rest like `max` does (`max` stays the cap). Set `auto-fit="false"` for a fixed stack that always shows up to `max`. */
|
|
8
|
+
autoFit: boolean;
|
|
9
|
+
/** Stack size. Drives the overflow counter size and the default overlap; slotted avatars should match. */
|
|
10
|
+
size: 'small' | 'medium' | 'large' | 'custom';
|
|
11
|
+
/** Diameter of the overflow counter when `size="custom"`. Any CSS length, applied to both width and height. */
|
|
12
|
+
customSize: string | undefined;
|
|
13
|
+
/** Overrides the overlap offset between circles. Any CSS length; defaults scale with `size`. */
|
|
14
|
+
overlap: string | undefined;
|
|
15
|
+
/** How the group is summarised: the first name with a `+N` rest count, a `+N` overflow counter circle in the stack, or nothing. The counter circle and the text label are mutually exclusive. */
|
|
16
|
+
labelMode: 'name' | 'counter' | 'none';
|
|
17
|
+
/** Overrides the gap between the stack and the label. Any CSS length; defaults scale with `size`. */
|
|
18
|
+
gap: string | undefined;
|
|
19
|
+
/** Whether the tooltip previews (the counter and the names label) show a small avatar beside each person, or just the name and caption. */
|
|
20
|
+
previewAvatars: boolean;
|
|
21
|
+
/** Makes the `+N` overflow counter focusable, keyboard-activatable, and emits `ipOverflowClick`. */
|
|
22
|
+
clickable: boolean;
|
|
23
|
+
/** Greys out the stack and, when `clickable`, prevents activation of the overflow counter. */
|
|
24
|
+
disabled: boolean;
|
|
25
|
+
/** Identity of every slotted avatar, in order. Drives the count, the names label, the counter, and both tooltip previews. */
|
|
26
|
+
private people;
|
|
27
|
+
/** Width-fitted cap computed by the width observer when `autoFit` is on; `null` until first measured (then `effectiveMax` falls back to `max`). */
|
|
28
|
+
private fittedMax;
|
|
29
|
+
/** Emitted when a clickable, non-disabled overflow counter is activated by mouse or keyboard. */
|
|
30
|
+
overflowClick: EventEmitter<void>;
|
|
31
|
+
/** Active width observer driving auto-fit; null when auto-fit is off or the element is detached. */
|
|
32
|
+
private resizeObserver;
|
|
33
|
+
/** True once the first render has measured; gates restart-on-reconnect so the very first connect defers to `componentDidLoad`. */
|
|
34
|
+
private hasLoaded;
|
|
35
|
+
/** Re-reads the slot and re-applies the layout when the collapse threshold changes. */
|
|
36
|
+
relayout(): void;
|
|
37
|
+
/** Re-fits when a dimension-affecting prop changes — the count that fits depends on avatar size and overlap. */
|
|
38
|
+
onDimensionChange(): void;
|
|
39
|
+
/** Starts or stops width observation when auto-fit is toggled, resetting the fitted cap. */
|
|
40
|
+
onAutoFitChange(): void;
|
|
41
|
+
/** Restarts width observation when the element is re-attached after a move; the first connect defers to `componentDidLoad`. */
|
|
42
|
+
connectedCallback(): void;
|
|
43
|
+
/** Begins observing the container width once the element and its slotted avatars exist. */
|
|
44
|
+
componentDidLoad(): void;
|
|
45
|
+
/** Tears down the width observer when the element leaves the DOM. */
|
|
46
|
+
disconnectedCallback(): void;
|
|
47
|
+
/** The `ip-avatar` elements currently assigned to the default slot. */
|
|
48
|
+
private assignedAvatars;
|
|
49
|
+
/** Reads the first avatar's name from the `name` property, falling back to the attribute for plain-HTML consumers. */
|
|
50
|
+
private nameOf;
|
|
51
|
+
/** Reads an avatar's image source from the `src` property, falling back to the attribute for plain-HTML consumers. */
|
|
52
|
+
private srcOf;
|
|
53
|
+
/** Reads an avatar's caption from the `caption` property, falling back to the attribute for plain-HTML consumers. */
|
|
54
|
+
private captionOf;
|
|
55
|
+
/** Records every slotted avatar's identity, then applies the stacking layout. */
|
|
56
|
+
private syncFromSlot;
|
|
57
|
+
/** Re-reads the slotted avatars whenever the assigned set changes. */
|
|
58
|
+
private handleSlotChange;
|
|
59
|
+
/** Forces each avatar to image-only, paints each above the one before it (last on top), and collapses avatars beyond `effectiveMax` into the overflow counter. */
|
|
60
|
+
private applyStacking;
|
|
61
|
+
/** Avatars to show before collapsing: the width-fitted cap (never above `max`) in auto-fit mode, otherwise `max`. */
|
|
62
|
+
private get effectiveMax();
|
|
63
|
+
/** Observes the parent's width (container resize) and the window (ambient resize) so the fitted cap stays in sync. */
|
|
64
|
+
private startObserving;
|
|
65
|
+
/** Disconnects the width observer and the window listener. */
|
|
66
|
+
private stopObserving;
|
|
67
|
+
/** Measures the container and updates the fitted cap, re-applying the stacking layout when it changes. */
|
|
68
|
+
private recomputeFit;
|
|
69
|
+
/** Content-box width available to the stack, measured from its parent. */
|
|
70
|
+
private availableWidth;
|
|
71
|
+
/** Current overlap offset in px, read from the computed custom property (set per size or via the `overlap` prop). */
|
|
72
|
+
private measuredOverlap;
|
|
73
|
+
/** Current stack↔label gap in px, read from the computed custom property (set per size or via the `gap` prop). */
|
|
74
|
+
private measuredGap;
|
|
75
|
+
/** Natural width of the rendered names label, reserved so it is not clipped before avatars collapse in name mode. */
|
|
76
|
+
private measuredLabelWidth;
|
|
77
|
+
/** Pixel width the `+N` counter occupies, matching the per-size circle in the SCSS. */
|
|
78
|
+
private counterWidth;
|
|
79
|
+
/** Largest avatar count that fits the available width, reserving room for the counter when one will show. At least 1. */
|
|
80
|
+
private computeFittedMax;
|
|
81
|
+
/** Emits ipOverflowClick when the counter is clickable and not disabled. */
|
|
82
|
+
private handleOverflowActivate;
|
|
83
|
+
/** Activates the overflow counter on Enter or Space, mirroring native button keyboard behaviour. */
|
|
84
|
+
private handleOverflowKeyDown;
|
|
85
|
+
/** Auto-generated names label: the first name plus a `+N` count of the remaining avatars. */
|
|
86
|
+
private get labelText();
|
|
87
|
+
/** Renders the people preview: ip-avatar's built-in label per row, or a compact name-only list when `previewAvatars` is off. Shared by the counter preview and the names-label tooltip. */
|
|
88
|
+
private renderPeopleList;
|
|
89
|
+
/** A preview row using ip-avatar's own circle, name, and caption. The class makes its label inherit the tooltip bubble's colour. */
|
|
90
|
+
private renderPersonRow;
|
|
91
|
+
/** A compact, avatar-less preview row — the name with an optional caption beneath. Used when `previewAvatars` is off, where ip-avatar's circle-bound label cannot apply. */
|
|
92
|
+
private renderPersonName;
|
|
93
|
+
/** Inline custom properties for the overlap and label gap, set only when the consumer overrides the defaults. */
|
|
94
|
+
private get hostStyle();
|
|
95
|
+
render(): JSX.Element;
|
|
96
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { JSX } from '../../stencil-public-runtime';
|
|
2
|
+
/** Compact inline indicator pairing a slotted icon with a value, e.g. an attachment count or a sensor reading. Display only — not interactive. */
|
|
3
|
+
export declare class IpIconCount {
|
|
4
|
+
/** Value shown next to the icon. A string so "12", "+14", and "37°C" are all valid. Empty renders a "-" placeholder so the layout stays consistent. */
|
|
5
|
+
value: string;
|
|
6
|
+
/** Colour variant for the icon and value. Mirrors the `variant` naming on ip-button / ip-icon-button. */
|
|
7
|
+
variant: 'default' | 'brand' | 'warning' | 'error';
|
|
8
|
+
/** Size of the icon and value text. */
|
|
9
|
+
size: 'small' | 'medium' | 'large';
|
|
10
|
+
/** Optional accessible label describing the value, e.g. "12 attachments". Sets aria-label on the host; an icon + value alone is not descriptive to screen readers. */
|
|
11
|
+
label: string;
|
|
12
|
+
/** Renders the icon and value, exposing a single labelled image to assistive tech when `label` is set. */
|
|
13
|
+
render(): JSX.Element;
|
|
14
|
+
}
|