srcdev-nuxt-components 9.1.42 → 9.1.44

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 (31) hide show
  1. package/.claude/settings.json +3 -1
  2. package/.claude/skills/components/{data-grid.md → auto-grid.md} +36 -34
  3. package/.claude/skills/components/display-avatar.md +187 -0
  4. package/.claude/skills/components/display-chip.md +213 -0
  5. package/.claude/skills/css-animation-utilities.md +87 -0
  6. package/.claude/skills/index.md +4 -1
  7. package/app/assets/styles/setup/06.utility-classes/animations/_animation-scroller-x.css +21 -0
  8. package/app/assets/styles/setup/06.utility-classes/animations/_auto-rotate.css +5 -3
  9. package/app/assets/styles/setup/06.utility-classes/animations/_entry-exit-blur.css +5 -3
  10. package/app/assets/styles/setup/06.utility-classes/animations/_entry-zoom-reveal.css +5 -3
  11. package/app/assets/styles/setup/06.utility-classes/animations/index.css +5 -4
  12. package/app/components/01.atoms/display-avatar/DisplayAvatar.vue +130 -0
  13. package/app/components/{display-avatar → 01.atoms/display-avatar}/stories/DisplayAvatar.stories.ts +12 -0
  14. package/app/components/01.atoms/display-avatar/tests/DisplayAvatar.spec.ts +208 -0
  15. package/app/components/01.atoms/display-avatar/tests/__snapshots__/DisplayAvatar.spec.ts.snap +11 -0
  16. package/app/components/01.atoms/grids/data-grid/AutoGrid.vue +57 -0
  17. package/app/components/01.atoms/grids/data-grid/stories/{DataGrid.stories.ts → AutoGrid.stories.ts} +95 -39
  18. package/app/components/01.atoms/grids/data-grid/tests/{DataGrid.spec.ts → AutoGrid.spec.ts} +42 -22
  19. package/app/components/01.atoms/grids/data-grid/tests/__snapshots__/AutoGrid.spec.ts.snap +11 -0
  20. package/app/components/01.atoms/grids/data-grid/tests/__snapshots__/DataGrid.spec.ts.snap +3 -3
  21. package/app/components/02.molecules/display-chip/DisplayChip.vue +189 -0
  22. package/app/components/{display-chip → 02.molecules/display-chip}/stories/DisplayChip.stories.ts +37 -53
  23. package/app/components/02.molecules/display-chip/tests/DisplayChip.spec.ts +191 -0
  24. package/app/components/02.molecules/display-chip/tests/__snapshots__/DisplayChip.spec.ts.snap +12 -0
  25. package/app/pages/auto-grid.vue +311 -0
  26. package/app/pages/index.vue +5 -0
  27. package/app/pages/ui/display-chip.vue +201 -66
  28. package/package.json +1 -1
  29. package/app/components/01.atoms/grids/data-grid/DataGrid.vue +0 -39
  30. package/app/components/display-avatar/DisplayAvatar.vue +0 -148
  31. package/app/components/display-chip/DisplayChip.vue +0 -187
@@ -7,6 +7,11 @@
7
7
  <NuxtLink class="page-body-normal" to="/grid-stack">GridStack</NuxtLink>
8
8
  </LayoutRow>
9
9
 
10
+ <LayoutRow tag="div" variant="full-width" :style-class-passthrough="['mbe-20']">
11
+ <h2 class="page-heading-2">AutoGrid</h2>
12
+ <NuxtLink class="page-body-normal" to="/auto-grid">AutoGrid</NuxtLink>
13
+ </LayoutRow>
14
+
10
15
  <LayoutRow tag="div" variant="full-width" :style-class-passthrough="['mbe-20']">
11
16
  <h1 class="page-heading-1">Nuxt3 Components Layer</h1>
12
17
  <p>
@@ -5,26 +5,71 @@
5
5
  <LayoutRow tag="div" variant="popout">
6
6
  <h1 class="page-heading-2">Display Chip</h1>
7
7
 
8
- <form>
9
- <div class="form-row">
10
- <div class="form-col">
11
- <label for="size">Size - {{ chipConfig.size }}</label>
12
- <input @input="changeSize" id="size" type="range" min="1" max="24" :value="12" />
13
- </div>
14
- <div class="form-col">
15
- <label for="maskWidth">Mask Width - {{ chipConfig.maskWidth }}</label>
16
- <input @input="changeMaskWidth" id="maskWidth" type="range" min="0" max="12" :value="4" />
17
- </div>
18
- <div class="form-col">
19
- <label for="offset">Offset - {{ chipConfig.offset }}</label>
20
- <input @input="changeOffset" id="offset" type="range" min="-12" max="12" :value="2" />
21
- </div>
22
- <div class="form-col">
23
- <label for="angle">Angle - {{ chipConfig.angle }}</label>
24
- <input @input="changeAngle" id="angle" type="range" min="0" max="360" :value="45" />
8
+ <!-- ── QA Panel (dev only) ───────────────────────────────── -->
9
+ <div v-if="isDev" class="qa-panel">
10
+ <details class="qa-panel__details">
11
+ <summary class="qa-panel__summary">
12
+ <span class="qa-panel__title">QA DisplayChip</span>
13
+ <code class="qa-panel__status">
14
+ size:{{ qaSize }}px · mask:{{ qaMaskWidth }}px · offset:{{ qaOffset }}px · angle:{{ qaAngle }}deg
15
+ </code>
16
+ </summary>
17
+ <div class="qa-panel__body">
18
+
19
+ <div class="qa-panel__group">
20
+ <span class="qa-panel__label">Size</span>
21
+ <div class="qa-panel__chips">
22
+ <button
23
+ v-for="preset in sizePresets"
24
+ :key="preset"
25
+ class="qa-panel__chip"
26
+ :class="{ 'is-active': qaSize === preset }"
27
+ @click="qaSize = preset"
28
+ >{{ preset }}px</button>
29
+ </div>
30
+ </div>
31
+
32
+ <div class="qa-panel__group">
33
+ <span class="qa-panel__label">Mask Width</span>
34
+ <div class="qa-panel__chips">
35
+ <button
36
+ v-for="preset in maskWidthPresets"
37
+ :key="preset"
38
+ class="qa-panel__chip"
39
+ :class="{ 'is-active': qaMaskWidth === preset }"
40
+ @click="qaMaskWidth = preset"
41
+ >{{ preset }}px</button>
42
+ </div>
43
+ </div>
44
+
45
+ <div class="qa-panel__group">
46
+ <span class="qa-panel__label">Offset</span>
47
+ <div class="qa-panel__chips">
48
+ <button
49
+ v-for="preset in offsetPresets"
50
+ :key="preset"
51
+ class="qa-panel__chip"
52
+ :class="{ 'is-active': qaOffset === preset }"
53
+ @click="qaOffset = preset"
54
+ >{{ preset }}px</button>
55
+ </div>
56
+ </div>
57
+
58
+ <div class="qa-panel__group">
59
+ <span class="qa-panel__label">Angle — {{ qaAngle }}deg</span>
60
+ <input
61
+ v-model.number="qaAngle"
62
+ type="range"
63
+ min="0"
64
+ max="360"
65
+ step="1"
66
+ class="qa-panel__range"
67
+ />
68
+ </div>
69
+
25
70
  </div>
26
- </div>
27
- </form>
71
+ </details>
72
+ </div>
28
73
 
29
74
  <section>
30
75
  <div class="dl">
@@ -106,6 +151,8 @@
106
151
  </template>
107
152
 
108
153
  <script setup lang="ts">
154
+ import type { DisplayChipConfig } from "~/types/components";
155
+
109
156
  definePageMeta({
110
157
  layout: false,
111
158
  });
@@ -118,59 +165,148 @@ useHead({
118
165
  },
119
166
  });
120
167
 
121
- const chipConfig = reactive({
122
- size: "12px",
123
- maskWidth: "4px",
124
- offset: "2px",
125
- angle: "45deg",
126
- });
168
+ // ── QA controls (dev only) ────────────────────────────────────────
169
+ const isDev = import.meta.dev;
170
+
171
+ const qaSize = ref(12);
172
+ const qaMaskWidth = ref(4);
173
+ const qaOffset = ref(2);
174
+ const qaAngle = ref(45);
127
175
 
128
- const changeSize = (e: Event) => {
129
- const target = e.target as HTMLInputElement;
130
- chipConfig.size = `${target.value}px`;
131
- };
132
-
133
- const changeMaskWidth = (e: Event) => {
134
- const target = e.target as HTMLInputElement;
135
- chipConfig.maskWidth = `${target.value}px`;
136
- };
137
-
138
- const changeOffset = (e: Event) => {
139
- const target = e.target as HTMLInputElement;
140
- chipConfig.offset = `${target.value}px`;
141
- };
142
-
143
- const changeAngle = (e: Event) => {
144
- const target = e.target as HTMLInputElement;
145
- chipConfig.angle = `${target.value}deg`;
146
- };
176
+ const sizePresets = [8, 10, 12, 16, 20, 24];
177
+ const maskWidthPresets = [0, 2, 4, 6, 8];
178
+ const offsetPresets = [-4, 0, 2, 4, 8];
179
+
180
+ const chipConfig = computed((): DisplayChipConfig => ({
181
+ size: `${qaSize.value}px`,
182
+ maskWidth: `${qaMaskWidth.value}px`,
183
+ offset: `${qaOffset.value}px`,
184
+ angle: `${qaAngle.value}deg`,
185
+ }));
147
186
  </script>
148
187
 
149
188
  <style lang="css">
150
189
  .ui-display-chip-page {
151
- form {
152
- margin-bottom: 2rem;
153
-
154
- .form-row {
155
- .form-col {
156
- display: grid;
157
- grid-template-columns: 200px 200px;
158
- gap: 1rem;
159
- padding: 0.5rem 0;
160
-
161
- label {
162
- font-weight: bold;
163
- }
190
+ /* ── QA Panel ──────────────────────────────────────────────────── */
164
191
 
165
- input {
166
- padding: 0.5rem;
167
- border: 1px solid var(--slate-07);
168
- border-radius: 4px;
169
- font-size: 1rem;
170
- }
171
- }
192
+ .qa-panel {
193
+ background: oklch(15% 0 0);
194
+ color: white;
195
+ font-size: 1.3rem;
196
+ }
197
+
198
+ .qa-panel__details {
199
+ padding: 1rem 2rem;
200
+ }
201
+
202
+ .qa-panel__summary {
203
+ cursor: pointer;
204
+ display: flex;
205
+ align-items: center;
206
+ gap: 1.6rem;
207
+ list-style: none;
208
+ user-select: none;
209
+
210
+ &::-webkit-details-marker { display: none; }
211
+ }
212
+
213
+ .qa-panel__title {
214
+ font-weight: 600;
215
+ font-size: 1.1rem;
216
+ text-transform: uppercase;
217
+ letter-spacing: 0.08em;
218
+ }
219
+
220
+ .qa-panel__status {
221
+ font-family: monospace;
222
+ font-size: 1.2rem;
223
+ background: oklch(0% 0 0 / 0.3);
224
+ padding: 0.2rem 0.8rem;
225
+ border-radius: 0.4rem;
226
+ user-select: text;
227
+ cursor: text;
228
+ }
229
+
230
+ .qa-panel__body {
231
+ display: flex;
232
+ flex-wrap: wrap;
233
+ gap: 2.4rem;
234
+ padding-block: 1.2rem 0.4rem;
235
+ }
236
+
237
+ .qa-panel__group {
238
+ display: flex;
239
+ flex-direction: column;
240
+ gap: 0.6rem;
241
+ }
242
+
243
+ .qa-panel__label {
244
+ font-size: 1.1rem;
245
+ text-transform: uppercase;
246
+ letter-spacing: 0.08em;
247
+ opacity: 0.55;
248
+ }
249
+
250
+ .qa-panel__chips {
251
+ display: flex;
252
+ flex-wrap: wrap;
253
+ gap: 0.4rem;
254
+ }
255
+
256
+ .qa-panel__chip {
257
+ font-family: monospace;
258
+ font-size: 1.2rem;
259
+ color: white;
260
+ background: oklch(0% 0 0 / 0.25);
261
+ border: 1px solid oklch(100% 0 0 / 0.18);
262
+ padding: 0.3rem 1rem;
263
+ border-radius: 0.4rem;
264
+ cursor: pointer;
265
+ transition: background 0.15s;
266
+
267
+ &:hover { background: oklch(0% 0 0 / 0.4); }
268
+
269
+ &.is-active {
270
+ background: oklch(55% 0.18 240);
271
+ border-color: oklch(55% 0.18 240);
272
+ }
273
+ }
274
+
275
+ .qa-panel__range {
276
+ appearance: none;
277
+ width: 18rem;
278
+ height: 0.4rem;
279
+ background: oklch(100% 0 0 / 0.18);
280
+ border-radius: 0.4rem;
281
+ outline: none;
282
+ cursor: pointer;
283
+
284
+ &::-webkit-slider-thumb {
285
+ appearance: none;
286
+ width: 1.4rem;
287
+ height: 1.4rem;
288
+ border-radius: 50%;
289
+ background: oklch(55% 0.18 240);
290
+ cursor: pointer;
291
+ transition: background 0.15s;
292
+ }
293
+
294
+ &::-moz-range-thumb {
295
+ width: 1.4rem;
296
+ height: 1.4rem;
297
+ border: none;
298
+ border-radius: 50%;
299
+ background: oklch(55% 0.18 240);
300
+ cursor: pointer;
301
+ transition: background 0.15s;
172
302
  }
303
+
304
+ &:hover::-webkit-slider-thumb { background: oklch(62% 0.18 240); }
305
+ &:hover::-moz-range-thumb { background: oklch(62% 0.18 240); }
173
306
  }
307
+
308
+ /* ── Demo grid ─────────────────────────────────────────────────── */
309
+
174
310
  section {
175
311
  margin-top: 2rem;
176
312
 
@@ -181,11 +317,10 @@ const changeAngle = (e: Event) => {
181
317
  align-items: center;
182
318
  justify-content: start;
183
319
 
184
- /* background-color: var(--slate-05); */
185
-
186
320
  .dt {
187
321
  font-weight: bold;
188
322
  }
323
+
189
324
  .dd {
190
325
  margin: 0;
191
326
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "srcdev-nuxt-components",
3
3
  "type": "module",
4
- "version": "9.1.42",
4
+ "version": "9.1.44",
5
5
  "main": "nuxt.config.ts",
6
6
  "types": "types.d.ts",
7
7
  "license": "MIT",
@@ -1,39 +0,0 @@
1
- <template>
2
- <component :is="tag" class="data-grid" :class="[elementClasses]" :aria-labelledby="ariaLabelledby">
3
- <slot v-for="(_, name) in $slots" :key="name" :name="name"></slot>
4
- </component>
5
- </template>
6
-
7
- <script setup lang="ts">
8
- interface Props {
9
- tag?: "div" | "section" | "article" | "main";
10
- styleClassPassthrough?: string | string[];
11
- }
12
-
13
- const props = withDefaults(defineProps<Props>(), {
14
- tag: "div",
15
- styleClassPassthrough: () => [],
16
- });
17
-
18
- const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
19
- const { ariaLabelledby } = useAriaLabelledById(props.tag);
20
-
21
- watch(
22
- () => props.styleClassPassthrough,
23
- () => resetElementClasses(props.styleClassPassthrough),
24
- );
25
- </script>
26
-
27
- <style lang="css">
28
- @layer components {
29
- .data-grid {
30
- /* CSS Tockens for @container grid-template-columns */
31
- --data-grid-columns: repeat(auto-fit, minmax(250px, 1fr));
32
- --data-grid-gap: 1rem;
33
-
34
- display: grid;
35
- grid-template-columns: var(--data-grid-columns);
36
- gap: var(--data-grid-gap);
37
- }
38
- }
39
- </style>
@@ -1,148 +0,0 @@
1
- <template>
2
- <component
3
- :is="props.chip ? DisplayChip : as"
4
- v-bind="props.chip ? (typeof props.chip === 'object' ? { config: props.chip } : { config: chipDefaultConfig }) : {}"
5
- class="display-avatar"
6
- :class="[size, elementClasses]"
7
- :style-class-passthrough="elementClasses"
8
- >
9
- <slot name="default">
10
- <NuxtImg v-if="src" :src :alt="alt || 'Avatar'" width="100%" height="100%" class="avatar-image" />
11
- <span v-else>{{ fallback }}</span>
12
- </slot>
13
- <slot name="icon"></slot>
14
- </component>
15
- </template>
16
-
17
- <script setup lang="ts">
18
- import DisplayChip from "../display-chip/DisplayChip.vue";
19
- import type { DisplayChipProps } from "../../types/components";
20
-
21
- export interface AvatarSlots {
22
- default(props?: {}): any;
23
- icon(props?: {}): any;
24
- }
25
-
26
- const props = defineProps({
27
- as: {
28
- type: [String, Object] as PropType<any>,
29
- default: "span",
30
- },
31
- src: {
32
- type: String,
33
- default: undefined,
34
- },
35
- alt: {
36
- type: String,
37
- default: undefined,
38
- },
39
- text: {
40
- type: String,
41
- default: undefined,
42
- },
43
- size: {
44
- type: String as PropType<"xs" | "s" | "md" | "lg" | "xl" | string>,
45
- default: "md",
46
- },
47
- chip: {
48
- type: [Boolean, Object] as PropType<boolean | DisplayChipProps>,
49
- default: undefined,
50
- },
51
- class: {
52
- type: [String, Array, Object] as PropType<any>,
53
- default: undefined,
54
- },
55
- style: {
56
- type: [String, Array, Object] as PropType<any>,
57
- default: undefined,
58
- },
59
- styleClassPassthrough: {
60
- type: [String, Array] as PropType<string | string[]>,
61
- default: () => [],
62
- },
63
- });
64
-
65
- defineSlots<AvatarSlots>();
66
-
67
- const { elementClasses, resetElementClasses, updateElementClasses } = useStyleClassPassthrough(
68
- props.styleClassPassthrough
69
- );
70
-
71
- if (props.chip && typeof props.chip === "object" && !("styleClassPassthrough" in props.chip)) {
72
- updateElementClasses(["display-avatar", props.size]);
73
- }
74
-
75
- const fallback = computed(
76
- () =>
77
- props.text ||
78
- (props.alt || "")
79
- .split(" ")
80
- .map((word) => word.charAt(0))
81
- .join("")
82
- .substring(0, 2)
83
- );
84
-
85
- const chipDefaultConfig = {
86
- size: "12px",
87
- maskWidth: "4px",
88
- offset: "0px",
89
- angle: "90deg",
90
- };
91
-
92
- watch(
93
- () => props.styleClassPassthrough,
94
- () => {
95
- resetElementClasses(props.styleClassPassthrough);
96
- }
97
- );
98
- </script>
99
-
100
- <style lang="css">
101
- @layer components {
102
- .display-avatar {
103
- display: flex;
104
- align-items: center;
105
- justify-content: center;
106
- border-radius: 50%;
107
- color: var(--slate-03);
108
-
109
- isolation: isolate;
110
-
111
- &.xs {
112
- width: 24px;
113
- height: 24px;
114
- font-size: 0.75rem;
115
- }
116
- &.s {
117
- width: 32px;
118
- height: 32px;
119
- font-size: 0.875rem;
120
- }
121
- &.md {
122
- width: 40px;
123
- height: 40px;
124
- font-size: 1rem;
125
- }
126
- &.lg {
127
- width: 48px;
128
- height: 48px;
129
- font-size: 1.125rem;
130
- }
131
- &.xl {
132
- width: 56px;
133
- height: 56px;
134
- font-size: 1.25rem;
135
- }
136
-
137
- .avatar-image {
138
- width: 100%;
139
- border-radius: 50%;
140
- object-fit: cover;
141
- }
142
-
143
- .avatar-icon {
144
- font-size: 24px;
145
- }
146
- }
147
- }
148
- </style>
@@ -1,187 +0,0 @@
1
- <template>
2
- <component :is="tag" class="display-chip-core" :class="[shape, elementClasses]" :style="chipStyles">
3
- <slot name="default"></slot>
4
- <Icon v-if="config?.icon" :name="config.icon" class="chip-icon" />
5
- <span v-if="config?.label" class="chip-label" :class="`length-${config.label.length}`">{{ validatedLabel }}</span>
6
- </component>
7
- </template>
8
-
9
- <script setup lang="ts">
10
- import type { DisplayChipConfig } from "../../types/components"
11
-
12
- const props = defineProps({
13
- tag: {
14
- type: String as PropType<"div" | "span">,
15
- default: "div",
16
- },
17
- shape: {
18
- type: String as PropType<"circle" | "square">,
19
- default: "circle",
20
- },
21
- config: {
22
- type: Object as PropType<DisplayChipConfig>,
23
- default: () => ({
24
- size: "12px",
25
- maskWidth: "4px",
26
- offset: "0px",
27
- angle: "90deg",
28
- icon: undefined,
29
- label: undefined,
30
- }),
31
- },
32
- styleClassPassthrough: {
33
- type: [String, Array] as PropType<string | string[]>,
34
- default: () => [],
35
- },
36
- })
37
-
38
- const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
39
-
40
- const validatedLabel = computed(() => {
41
- if (!props.config?.label) return props.config?.label
42
- if (props.config.label.length > 3) {
43
- console.warn(
44
- `DisplayChip: label "${
45
- props.config.label
46
- }" exceeds maximum length of 3 characters. Truncating to "${props.config.label.slice(0, 3)}"`
47
- )
48
- return props.config.label.slice(0, 3)
49
- }
50
- return props.config.label
51
- })
52
-
53
- const chipStyles = computed(() => ({
54
- "--chip-size": props.config?.size,
55
- "--chip-mask-width": props.config?.maskWidth,
56
- "--chip-offset": props.config?.offset,
57
- "--chip-angle": props.config?.angle,
58
- }))
59
- </script>
60
-
61
- <style lang="css">
62
- @layer components {
63
- .display-chip-core {
64
- --computed-mask-diameter: calc(var(--chip-size) + (var(--chip-mask-width) * 2));
65
-
66
- &.circle {
67
- --computed-chip-offset: calc((100% / 2) + var(--chip-offset));
68
- --computed-position-x: calc(var(--computed-chip-offset) * cos(var(--chip-angle) - 90deg) + (100% / 2));
69
- --computed-position-y: calc(var(--computed-chip-offset) * sin(var(--chip-angle) - 90deg) + (100% / 2));
70
- }
71
-
72
- &.square {
73
- --circle-x: calc(50% + (50% + var(--chip-offset) + (var(--chip-size) / 2)) * cos(var(--chip-angle) - 90deg));
74
- --circle-y: calc(50% + (50% + var(--chip-offset) + (var(--chip-size) / 2)) * sin(var(--chip-angle) - 90deg));
75
- --computed-position-x: clamp(calc(var(--chip-offset) * -1), var(--circle-x), calc(100% + var(--chip-offset)));
76
- --computed-position-y: clamp(calc(var(--chip-offset) * -1), var(--circle-y), calc(100% + var(--chip-offset)));
77
- }
78
-
79
- /* colors */
80
-
81
- --color-offline: slategrey;
82
- --color-online: rgb(0, 255, 135);
83
- --color-idle: rgb(255, 185, 51);
84
- --color-dnd: rgb(255, 40, 80);
85
-
86
- position: relative;
87
- display: inline-block;
88
-
89
- &::after {
90
- content: "";
91
- aspect-ratio: 1;
92
- background: var(--color-offline);
93
- position: absolute;
94
- width: var(--chip-size);
95
- border-radius: 100%;
96
- z-index: 1;
97
- }
98
- .chip-icon {
99
- position: absolute;
100
- width: var(--chip-size);
101
- height: var(--chip-size);
102
- border-radius: 100%;
103
- display: flex;
104
- align-items: center;
105
- justify-content: center;
106
- color: black;
107
- z-index: 2;
108
- }
109
-
110
- .chip-label {
111
- --_font-size-adjust: 0.7;
112
- position: absolute;
113
- width: var(--chip-size);
114
- height: var(--chip-size);
115
- border-radius: 100%;
116
- display: flex;
117
- align-items: center;
118
- justify-content: center;
119
- color: black;
120
- z-index: 2;
121
- font-size: calc(var(--chip-size) * var(--_font-size-adjust));
122
- line-height: 1;
123
- letter-spacing: -0.05rem;
124
- user-select: none;
125
-
126
- &.length-2 {
127
- --_font-size-adjust: 0.6;
128
- }
129
-
130
- &.length-3 {
131
- --_font-size-adjust: 0.5;
132
- }
133
- }
134
-
135
- & > * {
136
- /*
137
- create the cutout mask around the image,
138
- it's just a radial gradient positioned at the same place as the
139
- psuedo-element ::after
140
- */
141
-
142
- &:not(.chip-icon, .chip-label) {
143
- mask-image: radial-gradient(
144
- var(--computed-mask-diameter) var(--computed-mask-diameter) at var(--computed-position-x)
145
- var(--computed-position-y),
146
- transparent calc(50% - 0.5px),
147
- black calc(50% + 0.5px)
148
- );
149
- }
150
- }
151
-
152
- &.circle {
153
- &::after,
154
- .chip-icon,
155
- .chip-label {
156
- top: calc(var(--computed-position-y) - (var(--chip-size) / 2));
157
- left: calc(var(--computed-position-x) - (var(--chip-size) / 2));
158
- }
159
- }
160
-
161
- &.square {
162
- &::after,
163
- .chip-icon,
164
- .chip-label {
165
- top: calc(var(--computed-position-y) - (var(--chip-size) / 2));
166
- left: calc(var(--computed-position-x) - (var(--chip-size) / 2));
167
- }
168
- }
169
-
170
- &.online {
171
- &::after {
172
- background-color: var(--color-online);
173
- }
174
- }
175
- &.idle {
176
- &::after {
177
- background-color: var(--color-idle);
178
- }
179
- }
180
- &.dnd {
181
- &::after {
182
- background-color: var(--color-dnd);
183
- }
184
- }
185
- }
186
- }
187
- </style>