srcdev-nuxt-components 9.6.0 → 9.6.2
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/.claude/skills/component-compliance-checklist.md +22 -3
- package/.claude/skills/component-dynamic-slots.md +3 -3
- package/.claude/skills/component-export-types.md +10 -16
- package/.claude/skills/component-naming.md +1 -1
- package/.claude/skills/components/alert-content.md +9 -1
- package/.claude/skills/components/container-glow.md +21 -8
- package/.claude/skills/components/display-avatar.md +27 -10
- package/.claude/skills/components/display-chip.md +38 -24
- package/.claude/skills/components/display-pill.md +58 -10
- package/.claude/skills/components/display-prompt.md +8 -5
- package/.claude/skills/components/display-toast.md +21 -4
- package/.claude/skills/components/glowing-border.md +20 -2
- package/.claude/skills/components/google-reviews.md +2 -2
- package/.claude/skills/components/profile-section.md +59 -21
- package/.claude/skills/components/responsive-header.md +11 -1
- package/.claude/skills/components/select-menu.md +54 -5
- package/.claude/skills/components/site-header.md +2 -2
- package/.claude/skills/components/social-icons-list.md +2 -0
- package/.claude/skills/components/tabbed-content.md +300 -0
- package/.claude/skills/composable-anchor-scroll.md +16 -15
- package/.claude/skills/index.md +8 -7
- package/.claude/skills/storybook-add-story.md +55 -0
- package/.claude/skills/theming-component-token-pattern.md +48 -0
- package/.claude/skills/theming-status-tokens.md +60 -0
- package/.vscode/srcdev-component-display-avatar.code-snippets +9 -1
- package/.vscode/srcdev-component-display-chip.code-snippets +3 -2
- package/.vscode/srcdev-component-display-pill.code-snippets +10 -0
- package/.vscode/srcdev-component-profile-section.code-snippets +27 -4
- package/.vscode/srcdev-component-responsive-header.code-snippets +6 -0
- package/.vscode/srcdev-component-select-menu.code-snippets +28 -0
- package/.vscode/{srcdev-component-tabs-core.code-snippets → srcdev-component-tabbed-content.code-snippets} +35 -16
- package/app/assets/styles/setup/03.theming/_status.css +24 -0
- package/app/assets/styles/setup/03.theming/index.css +1 -0
- package/app/components/01.atoms/animations/container-glow/CONSUMER-STYLING.md +39 -35
- package/app/components/01.atoms/animations/container-glow/ContainerGlow.vue +25 -15
- package/app/components/01.atoms/animations/container-glow/stories/ContainerGlow.stories.ts +130 -24
- package/app/components/01.atoms/animations/container-glow/tests/ContainerGlow.spec.ts +45 -0
- package/app/components/01.atoms/animations/container-glow/tests/__snapshots__/ContainerGlow.spec.ts.snap +2 -2
- package/app/components/01.atoms/animations/glowing-border/CONSUMER-STYLING.md +76 -19
- package/app/components/01.atoms/animations/glowing-border/GlowingBorder.vue +12 -10
- package/app/components/01.atoms/animations/glowing-border/stories/GlowingBorder.stories.ts +201 -42
- package/app/components/01.atoms/animations/glowing-border/tests/GlowingBorder.spec.ts +15 -4
- package/app/components/01.atoms/animations/glowing-border/tests/__snapshots__/GlowingBorder.spec.ts.snap +1 -1
- package/app/components/01.atoms/display-pill/CONSUMER-STYLING.md +75 -9
- package/app/components/01.atoms/display-pill/DisplayPill.vue +57 -24
- package/app/components/01.atoms/display-pill/stories/DisplayPill.stories.ts +240 -16
- package/app/components/01.atoms/display-pill/tests/DisplayPill.spec.ts +43 -14
- package/app/components/01.atoms/display-pill/tests/__snapshots__/DisplayPill.spec.ts.snap +3 -3
- package/app/components/01.atoms/tabbed-content/CONSUMER-STYLING.md +201 -0
- package/app/components/01.atoms/tabbed-content/TabbedContent.vue +750 -0
- package/app/components/01.atoms/tabbed-content/stories/TabbedContent.stories.ts +279 -0
- package/app/components/01.atoms/tabbed-content/tests/TabbedContent.spec.ts +816 -0
- package/app/components/02.molecules/alert-content/AlertContent.vue +11 -2
- package/app/components/02.molecules/alert-content/AlertContentInner.vue +19 -0
- package/app/components/02.molecules/alert-content/CONSUMER-STYLING.md +17 -4
- package/app/components/02.molecules/alert-content/stories/AlertContent.stories.ts +200 -17
- package/app/components/02.molecules/alert-content/tests/AlertContent.spec.ts +33 -0
- package/app/components/02.molecules/display-avatar/CONSUMER-STYLING.md +33 -15
- package/app/components/02.molecules/display-avatar/DisplayAvatar.vue +81 -36
- package/app/components/02.molecules/display-avatar/stories/DisplayAvatar.stories.ts +108 -6
- package/app/components/02.molecules/display-avatar/tests/DisplayAvatar.spec.ts +104 -13
- package/app/components/02.molecules/display-avatar/tests/__snapshots__/DisplayAvatar.spec.ts.snap +4 -3
- package/app/components/02.molecules/display-chip/CONSUMER-STYLING.md +57 -19
- package/app/components/02.molecules/display-chip/DisplayChip.vue +72 -54
- package/app/components/02.molecules/display-chip/stories/DisplayChip.stories.ts +103 -6
- package/app/components/02.molecules/display-chip/tests/DisplayChip.spec.ts +98 -29
- package/app/components/02.molecules/display-chip/tests/__snapshots__/DisplayChip.spec.ts.snap +8 -4
- package/app/components/02.molecules/profile-section/CONSUMER-STYLING.md +103 -13
- package/app/components/02.molecules/profile-section/ProfileSection.vue +123 -23
- package/app/components/02.molecules/profile-section/stories/ProfileSection.stories.ts +353 -115
- package/app/components/02.molecules/profile-section/tests/ProfileSection.spec.ts +144 -11
- package/app/components/02.molecules/profile-section/tests/__snapshots__/ProfileSection.spec.ts.snap +6 -11
- package/app/components/02.molecules/prompt/CONSUMER-STYLING.md +9 -1
- package/app/components/02.molecules/prompt/DisplayPrompt.vue +2 -2
- package/app/components/02.molecules/prompt/stories/DisplayPrompt.stories.ts +208 -71
- package/app/components/02.molecules/prompt/tests/DisplayPrompt.spec.ts +19 -6
- package/app/components/02.molecules/select-menu/CONSUMER-STYLING.md +66 -8
- package/app/components/02.molecules/select-menu/SelectMenu.vue +141 -18
- package/app/components/02.molecules/select-menu/stories/SelectMenu.stories.ts +232 -2
- package/app/components/02.molecules/select-menu/tests/SelectMenu.spec.ts +151 -0
- package/app/components/02.molecules/select-menu/tests/__snapshots__/SelectMenu.spec.ts.snap +6 -2
- package/app/components/02.molecules/social-icons-list/CONSUMER-STYLING.md +6 -2
- package/app/components/02.molecules/social-icons-list/SocialIconsList.vue +1 -0
- package/app/components/02.molecules/toast/CONSUMER-STYLING.md +91 -27
- package/app/components/02.molecules/toast/DisplayToast.vue +109 -50
- package/app/components/02.molecules/toast/DisplayToastProvider.vue +109 -45
- package/app/components/02.molecules/toast/stories/DisplayToast.stories.ts +23 -0
- package/app/components/02.molecules/toast/stories/DisplayToastProvider.stories.ts +73 -0
- package/app/components/02.molecules/toast/tests/DisplayToast.spec.ts +132 -18
- package/app/components/02.molecules/toast/tests/DisplayToastProvider.spec.ts +105 -39
- package/app/components/03.organisms/google-reviews/tests/__snapshots__/GoogleReviewCard.spec.ts.snap +1 -1
- package/app/components/03.organisms/google-reviews/tests/__snapshots__/GoogleReviews.spec.ts.snap +6 -6
- package/app/components/03.organisms/responsive-header/CONSUMER-STYLING.md +38 -11
- package/app/components/03.organisms/responsive-header/NavigationItems.vue +27 -12
- package/app/components/03.organisms/responsive-header/ResponsiveHeader.vue +35 -20
- package/app/components/03.organisms/responsive-header/stories/ResponsiveHeader.stories.ts +1 -1
- package/app/components/03.organisms/services/service-detail/tests/__snapshots__/ServiceDetail.spec.ts.snap +1 -1
- package/app/components/03.organisms/services/service-summary/tests/__snapshots__/ServiceSummary.spec.ts.snap +1 -1
- package/app/components/03.organisms/services/services-grids/tests/__snapshots__/ServiceSummaryGrid.spec.ts.snap +3 -3
- package/app/composables/useTabs.ts +148 -206
- package/app/types/components/display-chip.d.ts +8 -4
- package/app/types/components/display-toast.d.ts +2 -0
- package/app/types/components/index.ts +0 -1
- package/app/types/components/select-menu.d.ts +2 -0
- package/app/utils/pausableTimeout.ts +41 -0
- package/nuxt.config.ts +1 -1
- package/package.json +1 -1
- package/.claude/skills/components/tab-navigation.md +0 -288
- package/.claude/skills/components/tabs-core.md +0 -187
- package/.vscode/srcdev-component-tab-navigation.code-snippets +0 -30
- package/app/components/01.atoms/navigation/tabs/CONSUMER-STYLING.md +0 -120
- package/app/components/01.atoms/navigation/tabs/TabsCore.vue +0 -272
- package/app/components/01.atoms/navigation/tabs/stories/TabsCore.stories.ts +0 -199
- package/app/components/01.atoms/navigation/tabs/tests/TabsCore.spec.ts +0 -274
- package/app/components/02.molecules/navigation/tab-navigation/CONSUMER-STYLING.md +0 -191
- package/app/components/02.molecules/navigation/tab-navigation/TabNavigation.vue +0 -550
- package/app/components/02.molecules/navigation/tab-navigation/stories/TabNavigation.stories.ts +0 -259
- package/app/components/02.molecules/navigation/tab-navigation/tests/TabNavigation.spec.ts +0 -379
- package/app/components/02.molecules/navigation/tab-navigation/tests/__snapshots__/TabNavigation.spec.ts.snap +0 -33
- package/app/composables/useNavCollapse.ts +0 -86
- package/app/types/components/nav-item.d.ts +0 -11
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<component
|
|
2
|
+
<component
|
|
3
|
+
:is="tag"
|
|
4
|
+
class="display-chip"
|
|
5
|
+
:class="elementClasses"
|
|
6
|
+
:data-shape="shape"
|
|
7
|
+
:data-status="status"
|
|
8
|
+
:style="chipStyles"
|
|
9
|
+
>
|
|
3
10
|
<slot name="default"></slot>
|
|
4
|
-
<Icon v-if="config?.icon" :name="config.icon" class="chip-icon" />
|
|
5
|
-
<span v-if="
|
|
11
|
+
<Icon v-if="config?.icon" :name="config.icon" class="display-chip-icon" aria-hidden="true" />
|
|
12
|
+
<span v-if="labelGraphemes.length" class="display-chip-label" :data-length="displayLength">{{ displayLabel }}</span>
|
|
13
|
+
<span v-if="statusLabel" class="sr-only">{{ statusLabel }}</span>
|
|
6
14
|
</component>
|
|
7
15
|
</template>
|
|
8
16
|
|
|
9
17
|
<script setup lang="ts">
|
|
10
|
-
import type { DisplayChipConfig } from "~/types/components";
|
|
18
|
+
import type { DisplayChipConfig, DisplayChipStatus } from "~/types/components";
|
|
11
19
|
|
|
12
20
|
interface Props {
|
|
13
21
|
tag?: "div" | "span";
|
|
14
22
|
shape?: "circle" | "square";
|
|
23
|
+
status?: DisplayChipStatus;
|
|
24
|
+
statusLabel?: string;
|
|
15
25
|
config?: DisplayChipConfig;
|
|
16
26
|
styleClassPassthrough?: string | string[];
|
|
17
27
|
}
|
|
@@ -19,17 +29,14 @@ interface Props {
|
|
|
19
29
|
const props = withDefaults(defineProps<Props>(), {
|
|
20
30
|
tag: "span",
|
|
21
31
|
shape: "circle",
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
offset: "0px",
|
|
26
|
-
angle: "90deg",
|
|
27
|
-
icon: undefined,
|
|
28
|
-
label: undefined,
|
|
29
|
-
}),
|
|
32
|
+
status: "offline",
|
|
33
|
+
statusLabel: "",
|
|
34
|
+
config: () => ({}),
|
|
30
35
|
styleClassPassthrough: () => [],
|
|
31
36
|
});
|
|
32
37
|
|
|
38
|
+
const MAX_LABEL_LENGTH = 3;
|
|
39
|
+
|
|
33
40
|
const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
|
|
34
41
|
|
|
35
42
|
watch(
|
|
@@ -39,112 +46,123 @@ watch(
|
|
|
39
46
|
}
|
|
40
47
|
);
|
|
41
48
|
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
`DisplayChip: label "${
|
|
47
|
-
props.config.label
|
|
48
|
-
}" exceeds maximum length of 3 characters. Truncating to "${props.config.label.slice(0, 3)}"`
|
|
49
|
-
);
|
|
50
|
-
return props.config.label.slice(0, 3);
|
|
51
|
-
}
|
|
52
|
-
return props.config.label;
|
|
49
|
+
const labelGraphemes = computed(() => {
|
|
50
|
+
const label = props.config?.label?.trim();
|
|
51
|
+
if (!label) return [];
|
|
52
|
+
return Array.from(new Intl.Segmenter(undefined, { granularity: "grapheme" }).segment(label), ({ segment }) => segment);
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
+
const displayLabel = computed(() => labelGraphemes.value.slice(0, MAX_LABEL_LENGTH).join(""));
|
|
56
|
+
const displayLength = computed(() => Math.min(labelGraphemes.value.length, MAX_LABEL_LENGTH));
|
|
57
|
+
|
|
58
|
+
watch(
|
|
59
|
+
labelGraphemes,
|
|
60
|
+
(graphemes) => {
|
|
61
|
+
if (graphemes.length > MAX_LABEL_LENGTH) {
|
|
62
|
+
console.warn(
|
|
63
|
+
`DisplayChip: label "${props.config?.label}" exceeds maximum length of ${MAX_LABEL_LENGTH} characters. Truncating to "${displayLabel.value}"`
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
{ immediate: true }
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
// Always written inline so a nested chip never inherits its parent's geometry.
|
|
55
71
|
const chipStyles = computed(() => ({
|
|
56
|
-
"--_chip-size": props.config?.size,
|
|
57
|
-
"--_chip-mask-width": props.config?.maskWidth,
|
|
58
|
-
"--_chip-offset": props.config?.offset,
|
|
59
|
-
"--_chip-angle": props.config?.angle,
|
|
72
|
+
"--_chip-size": props.config?.size || "var(--display-chip-size, 1.2rem)",
|
|
73
|
+
"--_chip-mask-width": props.config?.maskWidth || "var(--display-chip-mask-width, 0.4rem)",
|
|
74
|
+
"--_chip-offset": props.config?.offset || "var(--display-chip-offset, 0rem)",
|
|
75
|
+
"--_chip-angle": props.config?.angle || "var(--display-chip-angle, 90deg)",
|
|
60
76
|
}));
|
|
61
77
|
</script>
|
|
62
78
|
|
|
63
79
|
<style lang="css">
|
|
64
80
|
@layer components {
|
|
65
81
|
.display-chip {
|
|
66
|
-
--
|
|
67
|
-
--
|
|
82
|
+
--_size: max(0px, var(--_chip-size));
|
|
83
|
+
--_mask-diameter: calc(var(--_size) + (max(0px, var(--_chip-mask-width)) * 2));
|
|
84
|
+
--_dot-colour: var(--display-chip-colour-offline, var(--status-neutral));
|
|
68
85
|
|
|
69
86
|
position: relative;
|
|
70
87
|
display: inline-block;
|
|
71
88
|
|
|
72
|
-
|
|
89
|
+
&[data-shape="circle"] {
|
|
73
90
|
--_offset: calc((100% / 2) + var(--_chip-offset));
|
|
74
91
|
--_position-x: calc(var(--_offset) * cos(var(--_chip-angle) - 90deg) + (100% / 2));
|
|
75
92
|
--_position-y: calc(var(--_offset) * sin(var(--_chip-angle) - 90deg) + (100% / 2));
|
|
76
93
|
}
|
|
77
94
|
|
|
78
|
-
|
|
79
|
-
--_circle-x: calc(50% + (50% + var(--_chip-offset) + (var(--
|
|
80
|
-
--_circle-y: calc(50% + (50% + var(--_chip-offset) + (var(--
|
|
95
|
+
&[data-shape="square"] {
|
|
96
|
+
--_circle-x: calc(50% + (50% + var(--_chip-offset) + (var(--_size) / 2)) * cos(var(--_chip-angle) - 90deg));
|
|
97
|
+
--_circle-y: calc(50% + (50% + var(--_chip-offset) + (var(--_size) / 2)) * sin(var(--_chip-angle) - 90deg));
|
|
81
98
|
--_position-x: clamp(calc(var(--_chip-offset) * -1), var(--_circle-x), calc(100% + var(--_chip-offset)));
|
|
82
99
|
--_position-y: clamp(calc(var(--_chip-offset) * -1), var(--_circle-y), calc(100% + var(--_chip-offset)));
|
|
83
100
|
}
|
|
84
101
|
|
|
85
|
-
|
|
86
|
-
--_dot-colour: var(--display-chip-colour-online,
|
|
102
|
+
&[data-status="online"] {
|
|
103
|
+
--_dot-colour: var(--display-chip-colour-online, var(--status-success));
|
|
87
104
|
}
|
|
88
105
|
|
|
89
|
-
|
|
90
|
-
--_dot-colour: var(--display-chip-colour-idle,
|
|
106
|
+
&[data-status="idle"] {
|
|
107
|
+
--_dot-colour: var(--display-chip-colour-idle, var(--status-warning));
|
|
91
108
|
}
|
|
92
109
|
|
|
93
|
-
|
|
94
|
-
--_dot-colour: var(--display-chip-colour-dnd,
|
|
110
|
+
&[data-status="dnd"] {
|
|
111
|
+
--_dot-colour: var(--display-chip-colour-dnd, var(--status-danger));
|
|
95
112
|
}
|
|
96
113
|
|
|
97
114
|
&::after {
|
|
98
115
|
content: "";
|
|
99
|
-
aspect-ratio: 1;
|
|
100
116
|
background: var(--_dot-colour);
|
|
101
117
|
position: absolute;
|
|
102
|
-
width: var(--
|
|
118
|
+
width: var(--_size);
|
|
119
|
+
height: var(--_size);
|
|
103
120
|
border-radius: 100%;
|
|
104
121
|
z-index: 1;
|
|
105
122
|
}
|
|
106
123
|
|
|
107
124
|
&::after,
|
|
108
|
-
.chip-icon,
|
|
109
|
-
.chip-label {
|
|
110
|
-
top: calc(var(--_position-y) - (var(--
|
|
111
|
-
left: calc(var(--_position-x) - (var(--
|
|
125
|
+
.display-chip-icon,
|
|
126
|
+
.display-chip-label {
|
|
127
|
+
top: calc(var(--_position-y) - (var(--_size) / 2));
|
|
128
|
+
left: calc(var(--_position-x) - (var(--_size) / 2));
|
|
112
129
|
}
|
|
113
130
|
|
|
114
|
-
.chip-icon {
|
|
131
|
+
.display-chip-icon {
|
|
115
132
|
position: absolute;
|
|
116
|
-
font-size: var(--
|
|
133
|
+
font-size: var(--_size);
|
|
117
134
|
color: var(--display-chip-text-colour, black);
|
|
118
135
|
z-index: 2;
|
|
119
136
|
}
|
|
120
137
|
|
|
121
|
-
.chip-label {
|
|
138
|
+
.display-chip-label {
|
|
122
139
|
--_font-size-adjust: 0.7;
|
|
123
140
|
|
|
124
141
|
position: absolute;
|
|
125
|
-
width: var(--
|
|
126
|
-
height: var(--
|
|
142
|
+
width: var(--_size);
|
|
143
|
+
height: var(--_size);
|
|
127
144
|
border-radius: 100%;
|
|
128
145
|
display: flex;
|
|
129
146
|
align-items: center;
|
|
130
147
|
justify-content: center;
|
|
131
148
|
color: var(--display-chip-text-colour, black);
|
|
132
149
|
z-index: 2;
|
|
133
|
-
font-size: calc(var(--
|
|
150
|
+
font-size: calc(var(--_size) * var(--_font-size-adjust));
|
|
134
151
|
line-height: 1;
|
|
135
152
|
letter-spacing: -0.05rem;
|
|
153
|
+
white-space: nowrap;
|
|
136
154
|
user-select: none;
|
|
137
155
|
|
|
138
|
-
|
|
156
|
+
&[data-length="2"] {
|
|
139
157
|
--_font-size-adjust: 0.6;
|
|
140
158
|
}
|
|
141
159
|
|
|
142
|
-
|
|
160
|
+
&[data-length="3"] {
|
|
143
161
|
--_font-size-adjust: 0.5;
|
|
144
162
|
}
|
|
145
163
|
}
|
|
146
164
|
|
|
147
|
-
& > *:not(.chip-icon, .chip-label) {
|
|
165
|
+
& > *:not(.display-chip-icon, .display-chip-label, .sr-only) {
|
|
148
166
|
mask-image: radial-gradient(
|
|
149
167
|
var(--_mask-diameter) var(--_mask-diameter) at var(--_position-x) var(--_position-y),
|
|
150
168
|
transparent calc(50% - 0.5px),
|
|
@@ -14,6 +14,7 @@ interface ChipStoryArgs {
|
|
|
14
14
|
icon: string;
|
|
15
15
|
label: string;
|
|
16
16
|
status: "offline" | "online" | "idle" | "dnd";
|
|
17
|
+
statusLabel: string;
|
|
17
18
|
useSlot: boolean;
|
|
18
19
|
slotContent: string;
|
|
19
20
|
styleClassPassthrough: string[];
|
|
@@ -87,11 +88,18 @@ export default {
|
|
|
87
88
|
status: {
|
|
88
89
|
control: { type: "select" },
|
|
89
90
|
options: ["offline", "online", "idle", "dnd"],
|
|
90
|
-
description: "Status
|
|
91
|
+
description: "Status colour for the chip dot",
|
|
91
92
|
table: {
|
|
92
93
|
category: "Appearance",
|
|
93
94
|
},
|
|
94
95
|
},
|
|
96
|
+
statusLabel: {
|
|
97
|
+
control: { type: "text" },
|
|
98
|
+
description: "Screen-reader text for the status (e.g. 'Online'), so it isn't conveyed by colour alone",
|
|
99
|
+
table: {
|
|
100
|
+
category: "Accessibility",
|
|
101
|
+
},
|
|
102
|
+
},
|
|
95
103
|
// Slot Configuration
|
|
96
104
|
useSlot: {
|
|
97
105
|
control: { type: "boolean" },
|
|
@@ -129,6 +137,7 @@ export default {
|
|
|
129
137
|
icon: "",
|
|
130
138
|
label: "",
|
|
131
139
|
status: "offline",
|
|
140
|
+
statusLabel: "",
|
|
132
141
|
useSlot: true,
|
|
133
142
|
slotContent: "SRC",
|
|
134
143
|
styleClassPassthrough: [],
|
|
@@ -149,7 +158,7 @@ const Template: StoryFn<ChipStoryArgs> = (args) => ({
|
|
|
149
158
|
})
|
|
150
159
|
);
|
|
151
160
|
|
|
152
|
-
const classes = computed(() =>
|
|
161
|
+
const classes = computed(() => args.styleClassPassthrough || []);
|
|
153
162
|
|
|
154
163
|
return { args, chipConfig, classes };
|
|
155
164
|
},
|
|
@@ -159,6 +168,8 @@ const Template: StoryFn<ChipStoryArgs> = (args) => ({
|
|
|
159
168
|
:tag="args.tag"
|
|
160
169
|
:shape="args.shape"
|
|
161
170
|
:config="chipConfig"
|
|
171
|
+
:status="args.status"
|
|
172
|
+
:status-label="args.statusLabel"
|
|
162
173
|
:style-class-passthrough="classes"
|
|
163
174
|
>
|
|
164
175
|
<template v-if="args.useSlot" #default>
|
|
@@ -290,14 +301,14 @@ const MultipleChipsTemplate: StoryFn<ChipStoryArgs> = (args) => ({
|
|
|
290
301
|
<div style="display: flex; gap: 40px; align-items: center; justify-content: center; height: 100vh; flex-wrap: wrap;">
|
|
291
302
|
<StorybookComponent
|
|
292
303
|
:config="{ size: '12px', maskWidth: '4px', offset: '0px', angle: '45deg', label: '5' }"
|
|
293
|
-
|
|
304
|
+
status="online"
|
|
294
305
|
>
|
|
295
306
|
<div style="width: 50px; height: 50px; background: #64748b; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #f8fafc; font-weight: 600; font-size: 1.3rem; font-family: sans-serif;">SRC</div>
|
|
296
307
|
</StorybookComponent>
|
|
297
308
|
|
|
298
309
|
<StorybookComponent
|
|
299
310
|
:config="{ size: '10px', maskWidth: '3px', offset: '2px', angle: '315deg', icon: 'mdi:pause' }"
|
|
300
|
-
|
|
311
|
+
status="idle"
|
|
301
312
|
>
|
|
302
313
|
<div style="width: 50px; height: 50px; background: #64748b; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #f8fafc; font-weight: 600; font-size: 1.3rem; font-family: sans-serif;">SRC</div>
|
|
303
314
|
</StorybookComponent>
|
|
@@ -305,14 +316,14 @@ const MultipleChipsTemplate: StoryFn<ChipStoryArgs> = (args) => ({
|
|
|
305
316
|
<StorybookComponent
|
|
306
317
|
shape="square"
|
|
307
318
|
:config="{ size: '14px', maskWidth: '2px', offset: '-5px', angle: '135deg', label: 'DND' }"
|
|
308
|
-
|
|
319
|
+
status="dnd"
|
|
309
320
|
>
|
|
310
321
|
<div style="width: 50px; height: 50px; background: #64748b; border-radius: 4px; display: flex; align-items: center; justify-content: center; color: #f8fafc; font-weight: 600; font-size: 1.3rem; font-family: sans-serif;">SRC</div>
|
|
311
322
|
</StorybookComponent>
|
|
312
323
|
|
|
313
324
|
<StorybookComponent
|
|
314
325
|
:config="{ size: '16px', maskWidth: '6px', offset: '8px', angle: '90deg' }"
|
|
315
|
-
|
|
326
|
+
status="offline"
|
|
316
327
|
>
|
|
317
328
|
<div style="width: 50px; height: 50px; background: #64748b; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #f8fafc; font-weight: 600; font-size: 1.3rem; font-family: sans-serif;">SRC</div>
|
|
318
329
|
</StorybookComponent>
|
|
@@ -328,3 +339,89 @@ MultipleChips.parameters = {
|
|
|
328
339
|
},
|
|
329
340
|
},
|
|
330
341
|
};
|
|
342
|
+
|
|
343
|
+
const hostStyle = (shape: "circle" | "square", size = 50) =>
|
|
344
|
+
`width: ${size}px; height: ${size}px; background: #64748b; border-radius: ${shape === "circle" ? "50%" : "4px"}; display: flex; align-items: center; justify-content: center; color: #f8fafc; font: 600 1.3rem sans-serif;`;
|
|
345
|
+
|
|
346
|
+
const stressChips: Array<{
|
|
347
|
+
key: string;
|
|
348
|
+
caption: string;
|
|
349
|
+
shape?: "circle" | "square";
|
|
350
|
+
status?: ChipStoryArgs["status"];
|
|
351
|
+
config?: DisplayChipConfig;
|
|
352
|
+
hostSize?: number;
|
|
353
|
+
hostText?: string;
|
|
354
|
+
brokenImage?: boolean;
|
|
355
|
+
noSlot?: boolean;
|
|
356
|
+
dir?: "rtl";
|
|
357
|
+
}> = [
|
|
358
|
+
{ key: "family", caption: "ZWJ family emoji (one grapheme)", status: "online", config: { size: "18px", angle: "45deg", label: "👨👩👧👦" } },
|
|
359
|
+
{ key: "flags", caption: "4 flags, truncated to 3", status: "idle", config: { size: "20px", angle: "45deg", label: "🇬🇧🇺🇸🇫🇷🇩🇪" } },
|
|
360
|
+
{ key: "count", caption: '"999+", truncated to "999"', status: "dnd", config: { size: "18px", angle: "45deg", label: "999+" } },
|
|
361
|
+
{ key: "wide", caption: '"WWW" (widest glyphs)', status: "online", config: { size: "16px", angle: "45deg", label: "WWW" } },
|
|
362
|
+
{ key: "html", caption: "HTML-like label", status: "dnd", config: { size: "18px", angle: "45deg", label: "<b>" } },
|
|
363
|
+
{ key: "rtl", caption: "Arabic label in an RTL wrapper", status: "online", dir: "rtl", config: { size: "18px", angle: "45deg", label: "مرحبا" } },
|
|
364
|
+
{ key: "whitespace", caption: "Whitespace-only label (no label)", status: "idle", config: { size: "14px", angle: "45deg", label: " " } },
|
|
365
|
+
{ key: "partial", caption: "Config with only a label (geometry from defaults)", status: "online", config: { label: "5" } },
|
|
366
|
+
{ key: "empty-config", caption: "Empty config object", status: "dnd", config: {} },
|
|
367
|
+
{ key: "zero", caption: "size 0px (no dot)", status: "online", config: { size: "0px", angle: "45deg" } },
|
|
368
|
+
{ key: "negative", caption: "size -10px, mask -4px (clamped to 0)", status: "online", config: { size: "-10px", maskWidth: "-4px", angle: "45deg" } },
|
|
369
|
+
{ key: "huge", caption: "size 64px on a 50px host", status: "idle", config: { size: "64px", angle: "45deg", label: "9" } },
|
|
370
|
+
{ key: "angles", caption: "angle -45deg, offset 40px", status: "online", config: { size: "12px", angle: "-45deg", offset: "40px" } },
|
|
371
|
+
{ key: "wrap", caption: "angle 720deg, offset -30px (square)", shape: "square", status: "dnd", config: { size: "12px", angle: "720deg", offset: "-30px" } },
|
|
372
|
+
{ key: "invalid", caption: "Invalid units: size 'abc', angle '45'", status: "online", config: { size: "abc", angle: "45" } },
|
|
373
|
+
{ key: "broken-icon", caption: "Broken icon name", status: "online", config: { size: "16px", angle: "45deg", icon: "not-a-real-set:missing" } },
|
|
374
|
+
{ key: "tiny-host", caption: "8px host", status: "online", hostSize: 8, config: { size: "6px", maskWidth: "1px", angle: "45deg" } },
|
|
375
|
+
{ key: "big-host", caption: "200px host, long host text", status: "online", hostSize: 200, hostText: "Donaudampfschifffahrtsgesellschaft", config: { size: "24px", angle: "135deg", label: "!" } },
|
|
376
|
+
{ key: "broken-image", caption: "Broken image as host", status: "idle", brokenImage: true, config: { size: "12px", angle: "45deg" } },
|
|
377
|
+
{ key: "no-slot", caption: "No slot content", status: "online", noSlot: true, config: { size: "12px", angle: "45deg" } },
|
|
378
|
+
];
|
|
379
|
+
|
|
380
|
+
export const StressTest: StoryFn<ChipStoryArgs> = () => ({
|
|
381
|
+
components: { StorybookComponent },
|
|
382
|
+
setup() {
|
|
383
|
+
return { stressChips, hostStyle };
|
|
384
|
+
},
|
|
385
|
+
template: `
|
|
386
|
+
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); gap: 4.8rem 2.4rem; padding: 4rem 2rem; font: 1.2rem sans-serif;">
|
|
387
|
+
<figure
|
|
388
|
+
v-for="chip in stressChips"
|
|
389
|
+
:key="chip.key"
|
|
390
|
+
:dir="chip.dir"
|
|
391
|
+
style="margin: 0; display: grid; justify-items: center; align-content: start; gap: 1.6rem; min-inline-size: 0;"
|
|
392
|
+
>
|
|
393
|
+
<StorybookComponent :shape="chip.shape ?? 'circle'" :status="chip.status" :config="chip.config" status-label="Status">
|
|
394
|
+
<template v-if="!chip.noSlot" #default>
|
|
395
|
+
<img
|
|
396
|
+
v-if="chip.brokenImage"
|
|
397
|
+
src="/does-not-exist.jpg"
|
|
398
|
+
alt="Broken avatar"
|
|
399
|
+
width="50"
|
|
400
|
+
height="50"
|
|
401
|
+
:style="hostStyle(chip.shape ?? 'circle')"
|
|
402
|
+
/>
|
|
403
|
+
<div v-else :style="hostStyle(chip.shape ?? 'circle', chip.hostSize)">
|
|
404
|
+
<span style="overflow-wrap: anywhere; text-align: center;">{{ chip.hostText ?? (chip.hostSize && chip.hostSize < 20 ? "" : "SRC") }}</span>
|
|
405
|
+
</div>
|
|
406
|
+
</template>
|
|
407
|
+
</StorybookComponent>
|
|
408
|
+
<figcaption style="text-align: center; overflow-wrap: anywhere;">{{ chip.caption }}</figcaption>
|
|
409
|
+
</figure>
|
|
410
|
+
</div>
|
|
411
|
+
`,
|
|
412
|
+
});
|
|
413
|
+
StressTest.storyName = "Stress Test (Worst-Case Data)";
|
|
414
|
+
StressTest.parameters = {
|
|
415
|
+
// Fixed showcase: hardcoded values, so Controls would do nothing here.
|
|
416
|
+
controls: { disable: true },
|
|
417
|
+
docs: {
|
|
418
|
+
description: {
|
|
419
|
+
story:
|
|
420
|
+
"Hostile config and labels: a ZWJ family emoji and a run of flags (must not split into broken characters), a label over the 3-character limit, " +
|
|
421
|
+
"the widest Latin glyphs, HTML-like and right-to-left text, a whitespace-only label, a config with missing or empty geometry, zero, negative, " +
|
|
422
|
+
"oversized and invalid sizes, out-of-range angles and offsets, a broken icon name, tiny and huge hosts, a broken image and no slot at all. " +
|
|
423
|
+
"Check that every label is whole and centred on its dot, missing geometry falls back to the default 12px dot at 90deg, negative and invalid sizes show no dot " +
|
|
424
|
+
"rather than a broken one, and the cutout ring always sits under the dot.",
|
|
425
|
+
},
|
|
426
|
+
},
|
|
427
|
+
};
|
|
@@ -37,7 +37,7 @@ describe("DisplayChip", () => {
|
|
|
37
37
|
|
|
38
38
|
it("renders correct HTML structure (square + styleClassPassthrough)", async () => {
|
|
39
39
|
const wrapper = await mountSuspended(DisplayChip, {
|
|
40
|
-
props: { shape: "square", styleClassPassthrough: ["
|
|
40
|
+
props: { shape: "square", status: "online", styleClassPassthrough: ["featured"] },
|
|
41
41
|
});
|
|
42
42
|
expect(wrapper.html()).toMatchSnapshot();
|
|
43
43
|
});
|
|
@@ -63,15 +63,41 @@ describe("DisplayChip", () => {
|
|
|
63
63
|
|
|
64
64
|
// ─── Shape ────────────────────────────────────────────────────────────────
|
|
65
65
|
|
|
66
|
-
it("
|
|
66
|
+
it("sets data-shape='circle' by default", async () => {
|
|
67
67
|
const wrapper = await mountSuspended(DisplayChip);
|
|
68
|
-
expect(wrapper.
|
|
68
|
+
expect(wrapper.attributes("data-shape")).toBe("circle");
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
-
it("
|
|
71
|
+
it("sets data-shape='square' when shape='square'", async () => {
|
|
72
72
|
const wrapper = await mountSuspended(DisplayChip, { props: { shape: "square" } });
|
|
73
|
-
expect(wrapper.
|
|
74
|
-
|
|
73
|
+
expect(wrapper.attributes("data-shape")).toBe("square");
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("does not put shape or status on the root as classes", async () => {
|
|
77
|
+
const wrapper = await mountSuspended(DisplayChip, { props: { shape: "square", status: "online" } });
|
|
78
|
+
expect(wrapper.classes()).toEqual(["display-chip"]);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// ─── Status ───────────────────────────────────────────────────────────────
|
|
82
|
+
|
|
83
|
+
it("sets data-status='offline' by default", async () => {
|
|
84
|
+
const wrapper = await mountSuspended(DisplayChip);
|
|
85
|
+
expect(wrapper.attributes("data-status")).toBe("offline");
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it.each(["online", "idle", "dnd"] as const)("sets data-status='%s' from the status prop", async (status) => {
|
|
89
|
+
const wrapper = await mountSuspended(DisplayChip, { props: { status } });
|
|
90
|
+
expect(wrapper.attributes("data-status")).toBe(status);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("renders statusLabel as screen-reader text", async () => {
|
|
94
|
+
const wrapper = await mountSuspended(DisplayChip, { props: { status: "online", statusLabel: "Online" } });
|
|
95
|
+
expect(wrapper.find(".sr-only").text()).toBe("Online");
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("renders no screen-reader text without statusLabel", async () => {
|
|
99
|
+
const wrapper = await mountSuspended(DisplayChip);
|
|
100
|
+
expect(wrapper.find(".sr-only").exists()).toBe(false);
|
|
75
101
|
});
|
|
76
102
|
|
|
77
103
|
// ─── CSS custom properties ────────────────────────────────────────────────
|
|
@@ -89,39 +115,81 @@ describe("DisplayChip", () => {
|
|
|
89
115
|
expect(style.getPropertyValue("--_chip-angle")).toBe("45deg");
|
|
90
116
|
});
|
|
91
117
|
|
|
92
|
-
it("
|
|
118
|
+
it("falls back to the public tokens when no config is provided", async () => {
|
|
93
119
|
const wrapper = await mountSuspended(DisplayChip);
|
|
94
120
|
const style = (wrapper.element as HTMLElement).style;
|
|
95
|
-
expect(style.getPropertyValue("--_chip-size")).toBe("
|
|
96
|
-
expect(style.getPropertyValue("--_chip-mask-width")).toBe("
|
|
97
|
-
expect(style.getPropertyValue("--_chip-offset")).toBe("
|
|
98
|
-
expect(style.getPropertyValue("--_chip-angle")).toBe("90deg");
|
|
121
|
+
expect(style.getPropertyValue("--_chip-size")).toBe("var(--display-chip-size, 1.2rem)");
|
|
122
|
+
expect(style.getPropertyValue("--_chip-mask-width")).toBe("var(--display-chip-mask-width, 0.4rem)");
|
|
123
|
+
expect(style.getPropertyValue("--_chip-offset")).toBe("var(--display-chip-offset, 0rem)");
|
|
124
|
+
expect(style.getPropertyValue("--_chip-angle")).toBe("var(--display-chip-angle, 90deg)");
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("falls back per field when config is partial", async () => {
|
|
128
|
+
const wrapper = await mountSuspended(DisplayChip, { props: { config: { label: "5", angle: "45deg" } } });
|
|
129
|
+
const style = (wrapper.element as HTMLElement).style;
|
|
130
|
+
expect(style.getPropertyValue("--_chip-size")).toBe("var(--display-chip-size, 1.2rem)");
|
|
131
|
+
expect(style.getPropertyValue("--_chip-angle")).toBe("45deg");
|
|
99
132
|
});
|
|
100
133
|
|
|
101
134
|
// ─── Label ────────────────────────────────────────────────────────────────
|
|
102
135
|
|
|
103
|
-
it("does not render .chip-label when config has no label", async () => {
|
|
136
|
+
it("does not render .display-chip-label when config has no label", async () => {
|
|
104
137
|
const wrapper = await mountSuspended(DisplayChip);
|
|
105
|
-
expect(wrapper.find(".chip-label").exists()).toBe(false);
|
|
138
|
+
expect(wrapper.find(".display-chip-label").exists()).toBe(false);
|
|
106
139
|
});
|
|
107
140
|
|
|
108
|
-
it("renders .chip-label when config.label is set", async () => {
|
|
141
|
+
it("renders .display-chip-label when config.label is set", async () => {
|
|
109
142
|
const wrapper = await mountSuspended(DisplayChip, {
|
|
110
143
|
props: { config: { size: "12px", maskWidth: "4px", offset: "0px", angle: "90deg", label: "5" } },
|
|
111
144
|
});
|
|
112
|
-
expect(wrapper.find(".chip-label").exists()).toBe(true);
|
|
113
|
-
expect(wrapper.find(".chip-label").text()).toBe("5");
|
|
145
|
+
expect(wrapper.find(".display-chip-label").exists()).toBe(true);
|
|
146
|
+
expect(wrapper.find(".display-chip-label").text()).toBe("5");
|
|
114
147
|
});
|
|
115
148
|
|
|
116
149
|
it.each([
|
|
117
|
-
["A", "
|
|
118
|
-
["+2", "
|
|
119
|
-
["DND", "
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
});
|
|
124
|
-
|
|
150
|
+
["A", "1"],
|
|
151
|
+
["+2", "2"],
|
|
152
|
+
["DND", "3"],
|
|
153
|
+
["👨👩👧👦", "1"],
|
|
154
|
+
["999+", "3"],
|
|
155
|
+
])("sets data-length for label '%s'", async (label, expected) => {
|
|
156
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
157
|
+
const wrapper = await mountSuspended(DisplayChip, { props: { config: { label } } });
|
|
158
|
+
expect(wrapper.find(".display-chip-label").attributes("data-length")).toBe(expected);
|
|
159
|
+
warnSpy.mockRestore();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("keeps a multi-codepoint emoji whole instead of splitting it", async () => {
|
|
163
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
164
|
+
const wrapper = await mountSuspended(DisplayChip, { props: { config: { label: "👨👩👧👦" } } });
|
|
165
|
+
expect(wrapper.find(".display-chip-label").text()).toBe("👨👩👧👦");
|
|
166
|
+
expect(warnSpy).not.toHaveBeenCalled();
|
|
167
|
+
warnSpy.mockRestore();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it("truncates by grapheme, not UTF-16 code unit", async () => {
|
|
171
|
+
const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
|
|
172
|
+
const wrapper = await mountSuspended(DisplayChip, { props: { config: { label: "🇬🇧🇺🇸🇫🇷🇩🇪" } } });
|
|
173
|
+
expect(wrapper.find(".display-chip-label").text()).toBe("🇬🇧🇺🇸🇫🇷");
|
|
174
|
+
warnSpy.mockRestore();
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("does not render a label for a whitespace-only label", async () => {
|
|
178
|
+
const wrapper = await mountSuspended(DisplayChip, { props: { config: { label: " " } } });
|
|
179
|
+
expect(wrapper.find(".display-chip-label").exists()).toBe(false);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it("renders an HTML-like label as text", async () => {
|
|
183
|
+
const wrapper = await mountSuspended(DisplayChip, { props: { config: { label: "<b>" } } });
|
|
184
|
+
expect(wrapper.find(".display-chip-label b").exists()).toBe(false);
|
|
185
|
+
expect(wrapper.find(".display-chip-label").text()).toBe("<b>");
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("updates the label when config changes after mount", async () => {
|
|
189
|
+
const wrapper = await mountSuspended(DisplayChip, { props: { config: { label: "1" } } });
|
|
190
|
+
await wrapper.setProps({ config: { label: "42" } });
|
|
191
|
+
expect(wrapper.find(".display-chip-label").text()).toBe("42");
|
|
192
|
+
expect(wrapper.find(".display-chip-label").attributes("data-length")).toBe("2");
|
|
125
193
|
});
|
|
126
194
|
|
|
127
195
|
it("truncates label to 3 characters when label exceeds maximum length", async () => {
|
|
@@ -129,7 +197,7 @@ describe("DisplayChip", () => {
|
|
|
129
197
|
const wrapper = await mountSuspended(DisplayChip, {
|
|
130
198
|
props: { config: { size: "12px", maskWidth: "4px", offset: "0px", angle: "90deg", label: "ABCD" } },
|
|
131
199
|
});
|
|
132
|
-
expect(wrapper.find(".chip-label").text()).toBe("ABC");
|
|
200
|
+
expect(wrapper.find(".display-chip-label").text()).toBe("ABC");
|
|
133
201
|
warnSpy.mockRestore();
|
|
134
202
|
});
|
|
135
203
|
|
|
@@ -144,16 +212,17 @@ describe("DisplayChip", () => {
|
|
|
144
212
|
|
|
145
213
|
// ─── Icon ─────────────────────────────────────────────────────────────────
|
|
146
214
|
|
|
147
|
-
it("does not render .chip-icon when config has no icon", async () => {
|
|
215
|
+
it("does not render .display-chip-icon when config has no icon", async () => {
|
|
148
216
|
const wrapper = await mountSuspended(DisplayChip);
|
|
149
|
-
expect(wrapper.find(".chip-icon").exists()).toBe(false);
|
|
217
|
+
expect(wrapper.find(".display-chip-icon").exists()).toBe(false);
|
|
150
218
|
});
|
|
151
219
|
|
|
152
|
-
it("renders .chip-icon when config.icon is set", async () => {
|
|
220
|
+
it("renders .display-chip-icon when config.icon is set", async () => {
|
|
153
221
|
const wrapper = await mountSuspended(DisplayChip, {
|
|
154
222
|
props: { config: { size: "12px", maskWidth: "4px", offset: "0px", angle: "90deg", icon: "mdi:check" } },
|
|
155
223
|
});
|
|
156
|
-
expect(wrapper.find(".chip-icon").exists()).toBe(true);
|
|
224
|
+
expect(wrapper.find(".display-chip-icon").exists()).toBe(true);
|
|
225
|
+
expect(wrapper.find(".display-chip-icon").attributes("aria-hidden")).toBe("true");
|
|
157
226
|
});
|
|
158
227
|
|
|
159
228
|
// ─── Slot ─────────────────────────────────────────────────────────────────
|
package/app/components/02.molecules/display-chip/tests/__snapshots__/DisplayChip.spec.ts.snap
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
|
-
exports[`DisplayChip > renders correct HTML structure (default) 1`] = `"<span class="display-chip circle" style="--_chip-size:
|
|
3
|
+
exports[`DisplayChip > renders correct HTML structure (default) 1`] = `"<span class="display-chip" data-shape="circle" data-status="offline" style="--_chip-size: var(--display-chip-size, 1.2rem); --_chip-mask-width: var(--display-chip-mask-width, 0.4rem); --_chip-offset: var(--display-chip-offset, 0rem); --_chip-angle: var(--display-chip-angle, 90deg);"><!--v-if--><!--v-if--><!--v-if--></span>"`;
|
|
4
4
|
|
|
5
|
-
exports[`DisplayChip > renders correct HTML structure (square + styleClassPassthrough) 1`] = `"<span class="display-chip square online" style="--_chip-size:
|
|
5
|
+
exports[`DisplayChip > renders correct HTML structure (square + styleClassPassthrough) 1`] = `"<span class="display-chip featured" data-shape="square" data-status="online" style="--_chip-size: var(--display-chip-size, 1.2rem); --_chip-mask-width: var(--display-chip-mask-width, 0.4rem); --_chip-offset: var(--display-chip-offset, 0rem); --_chip-angle: var(--display-chip-angle, 90deg);"><!--v-if--><!--v-if--><!--v-if--></span>"`;
|
|
6
6
|
|
|
7
7
|
exports[`DisplayChip > renders correct HTML structure (with icon) 1`] = `
|
|
8
|
-
"<span class="display-chip circle" style="--_chip-size: 12px; --_chip-mask-width: 4px; --_chip-offset: 0px; --_chip-angle: 90deg;"><span class="iconify i-mdi:check chip-icon" aria-hidden="true"></span>
|
|
8
|
+
"<span class="display-chip" data-shape="circle" data-status="offline" style="--_chip-size: 12px; --_chip-mask-width: 4px; --_chip-offset: 0px; --_chip-angle: 90deg;"><span class="iconify i-mdi:check display-chip-icon" aria-hidden="true"></span>
|
|
9
|
+
<!--v-if-->
|
|
9
10
|
<!--v-if--></span>"
|
|
10
11
|
`;
|
|
11
12
|
|
|
12
|
-
exports[`DisplayChip > renders correct HTML structure (with label) 1`] = `
|
|
13
|
+
exports[`DisplayChip > renders correct HTML structure (with label) 1`] = `
|
|
14
|
+
"<span class="display-chip" data-shape="circle" data-status="offline" style="--_chip-size: 12px; --_chip-mask-width: 4px; --_chip-offset: 0px; --_chip-angle: 90deg;"><!--v-if--><span class="display-chip-label" data-length="1">5</span>
|
|
15
|
+
<!--v-if--></span>"
|
|
16
|
+
`;
|