srcdev-nuxt-components 9.0.18 → 9.1.1
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/settings.json +4 -2
- package/.claude/skills/component-inline-action-button.md +79 -0
- package/.claude/skills/components/input-copy-core.md +66 -0
- package/.claude/skills/components/page-hero-highlights.md +60 -0
- package/.claude/skills/components/site-navigation.md +120 -0
- package/.claude/skills/icon-sets.md +45 -0
- package/.claude/skills/index.md +7 -1
- package/.claude/skills/performance-review.md +105 -0
- package/.claude/skills/robots-env-aware.md +69 -0
- package/app/assets/styles/extends-layer/srcdev-forms/setup/themes/_error.css +1 -1
- package/app/assets/styles/setup/02.colours/_amber.css +2 -2
- package/app/assets/styles/setup/03.theming/default/_dark.css +20 -2
- package/app/assets/styles/setup/03.theming/default/_light.css +11 -1
- package/app/assets/styles/setup/03.theming/error/_dark.css +1 -1
- package/app/components/01.atoms/text-blocks/eyebrow-text/EyebrowText.vue +15 -12
- package/app/components/01.atoms/text-blocks/hero-text/HeroText.vue +3 -1
- package/app/components/02.molecules/navigation/site-navigation/SiteNavigation.vue +780 -0
- package/app/components/02.molecules/navigation/site-navigation/stories/SiteNavigation.stories.ts +335 -0
- package/app/components/02.molecules/navigation/site-navigation/tests/SiteNavigation.spec.ts +328 -0
- package/app/components/02.molecules/navigation/site-navigation/tests/__snapshots__/SiteNavigation.spec.ts.snap +30 -0
- package/app/components/04.templates/page-hero-highlights/PageHeroHighlights.vue +36 -21
- package/app/components/04.templates/page-hero-highlights/PageHeroHighlightsHeader.vue +66 -0
- package/app/components/04.templates/page-hero-highlights/stories/PageHeroHighlights.stories.ts +50 -3
- package/app/components/04.templates/page-hero-highlights/stories/PageHeroHighlightsHeader.stories.ts +77 -0
- package/app/components/04.templates/page-hero-highlights/tests/PageHeroHighlights.spec.ts +15 -7
- package/app/components/04.templates/page-hero-highlights/tests/PageHeroHighlightsHeader.spec.ts +51 -0
- package/app/components/04.templates/page-hero-highlights/tests/__snapshots__/PageHeroHighlights.spec.ts.snap +1 -1
- package/app/components/forms/form-errors/InputError.vue +104 -103
- package/app/components/forms/input-copy/InputCopyCore.vue +132 -0
- package/app/components/forms/input-copy/stories/InputCopyCore.stories.ts +89 -0
- package/app/components/forms/input-copy/tests/InputCopyCore.spec.ts +212 -0
- package/app/components/forms/input-copy/tests/__snapshots__/InputCopyCore.spec.ts.snap +28 -0
- package/app/layouts/default.vue +1 -0
- package/app/pages/index.vue +0 -5
- package/app/pages/page-hero-highlights.vue +15 -11
- package/modules/icon-sets.ts +53 -0
- package/nuxt.config.ts +8 -0
- package/package.json +49 -6
- package/app/components/03.organisms/treatment-consultant/TreatmentConsultant.vue +0 -2204
- package/app/components/03.organisms/treatment-consultant/stories/TreatmentConsultant.stories.ts +0 -38
- package/app/pages/ui/services/treatment-consultant.vue +0 -39
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<component
|
|
3
3
|
:is="tag"
|
|
4
4
|
class="page-hero-highlights"
|
|
5
|
-
:class="[elementClasses, componentClasses]"
|
|
5
|
+
:class="[elementClasses, componentClasses, { 'has-content-panel': contentPanel }]"
|
|
6
6
|
:aria-labelledby="ariaLabelledby"
|
|
7
7
|
>
|
|
8
8
|
<div class="header-row">
|
|
@@ -28,6 +28,7 @@ interface Props {
|
|
|
28
28
|
highlightsJustify?: "start" | "center" | "end" | "space-between" | "space-around";
|
|
29
29
|
maxWidth?: string;
|
|
30
30
|
contentAlign?: "start" | "center";
|
|
31
|
+
contentPanel?: boolean;
|
|
31
32
|
highlightTitleBaseline?: boolean;
|
|
32
33
|
styleClassPassthrough?: string | string[];
|
|
33
34
|
}
|
|
@@ -38,13 +39,14 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
38
39
|
highlightsJustify: "start",
|
|
39
40
|
maxWidth: undefined,
|
|
40
41
|
contentAlign: "center",
|
|
42
|
+
contentPanel: true,
|
|
41
43
|
highlightTitleBaseline: false,
|
|
42
44
|
styleClassPassthrough: () => [],
|
|
43
45
|
});
|
|
44
46
|
|
|
45
47
|
const gridColumns = computed(() => {
|
|
46
48
|
if (!props.maxWidth) return "16px 1fr 16px";
|
|
47
|
-
if (props.contentAlign === "start") return `16px minmax(0, ${props.maxWidth}) 1fr`;
|
|
49
|
+
if (props.contentAlign === "start") return `16px minmax(0, ${props.maxWidth}) minmax(16px, 1fr)`;
|
|
48
50
|
return `max(16px, (100% - ${props.maxWidth}) / 2) 1fr max(16px, (100% - ${props.maxWidth}) / 2)`;
|
|
49
51
|
});
|
|
50
52
|
|
|
@@ -122,6 +124,7 @@ watch(
|
|
|
122
124
|
.header-slot {
|
|
123
125
|
grid-column: 2;
|
|
124
126
|
grid-row: 1;
|
|
127
|
+
container-type: inline-size;
|
|
125
128
|
}
|
|
126
129
|
}
|
|
127
130
|
|
|
@@ -135,7 +138,7 @@ watch(
|
|
|
135
138
|
|
|
136
139
|
/* Element theme */
|
|
137
140
|
gap: var(--highlights-row-item-gap);
|
|
138
|
-
margin-inline-start:
|
|
141
|
+
margin-inline-start: 0;
|
|
139
142
|
|
|
140
143
|
&.equal-widths {
|
|
141
144
|
display: grid;
|
|
@@ -211,28 +214,40 @@ watch(
|
|
|
211
214
|
background-color: var(--content-row-background-color);
|
|
212
215
|
padding-block-end: var(--content-row-end-gap);
|
|
213
216
|
|
|
214
|
-
&:before {
|
|
215
|
-
/* Element geometry */
|
|
216
|
-
content: "";
|
|
217
|
-
grid-template-columns: subgrid;
|
|
218
|
-
grid-template-rows: subgrid;
|
|
219
|
-
display: grid;
|
|
220
|
-
grid-column: 2;
|
|
221
|
-
grid-row: 1 / span 2;
|
|
222
|
-
|
|
223
|
-
/* Element theme */
|
|
224
|
-
margin-top: var(--content-row-start-gap);
|
|
225
|
-
|
|
226
|
-
background-color: var(--content-slot-background-color);
|
|
227
|
-
border: var(--content-slot-border);
|
|
228
|
-
outline: var(--content-slot-outline);
|
|
229
|
-
border-radius: var(--content-slot-border-radius);
|
|
230
|
-
}
|
|
231
217
|
.content-slot {
|
|
232
218
|
grid-column: 2;
|
|
233
219
|
grid-row: 2;
|
|
234
220
|
margin-block: var(--content-slot-margin-block-start) var(--content-slot-margin);
|
|
235
|
-
margin-inline:
|
|
221
|
+
margin-inline: 0;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
&.has-content-panel {
|
|
226
|
+
.highlights-row {
|
|
227
|
+
margin-inline: var(--highlights-row-initial-item-offset);
|
|
228
|
+
}
|
|
229
|
+
.content-row {
|
|
230
|
+
&:before {
|
|
231
|
+
/* Element geometry */
|
|
232
|
+
content: "";
|
|
233
|
+
grid-template-columns: subgrid;
|
|
234
|
+
grid-template-rows: subgrid;
|
|
235
|
+
display: grid;
|
|
236
|
+
grid-column: 2;
|
|
237
|
+
grid-row: 1 / span 2;
|
|
238
|
+
|
|
239
|
+
/* Element theme */
|
|
240
|
+
margin-top: var(--content-row-start-gap);
|
|
241
|
+
|
|
242
|
+
background-color: var(--content-slot-background-color);
|
|
243
|
+
border: var(--content-slot-border);
|
|
244
|
+
outline: var(--content-slot-outline);
|
|
245
|
+
border-radius: var(--content-slot-border-radius);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.content-slot {
|
|
249
|
+
margin-inline: var(--content-slot-margin);
|
|
250
|
+
}
|
|
236
251
|
}
|
|
237
252
|
}
|
|
238
253
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="page-hero-highlights-header" :class="elementClasses">
|
|
3
|
+
<div class="phh-start">
|
|
4
|
+
<slot name="start"></slot>
|
|
5
|
+
</div>
|
|
6
|
+
<div v-if="hasEndSlot" class="phh-end">
|
|
7
|
+
<slot name="end"></slot>
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup lang="ts">
|
|
13
|
+
interface Props {
|
|
14
|
+
styleClassPassthrough?: string | string[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
18
|
+
styleClassPassthrough: () => [],
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const slots = useSlots();
|
|
22
|
+
const hasEndSlot = computed(() => Boolean(slots.end));
|
|
23
|
+
|
|
24
|
+
const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
|
|
25
|
+
|
|
26
|
+
watch(
|
|
27
|
+
() => props.styleClassPassthrough,
|
|
28
|
+
() => {
|
|
29
|
+
resetElementClasses(props.styleClassPassthrough);
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<style lang="css">
|
|
35
|
+
.page-hero-highlights-header {
|
|
36
|
+
/* User themable tokens */
|
|
37
|
+
--phh-padding-block: 1.6rem;
|
|
38
|
+
--phh-gap: 1.6rem;
|
|
39
|
+
--phh-end-gap: 0.8rem;
|
|
40
|
+
|
|
41
|
+
display: flex;
|
|
42
|
+
flex-direction: column;
|
|
43
|
+
gap: var(--phh-gap);
|
|
44
|
+
padding-block: var(--phh-padding-block);
|
|
45
|
+
|
|
46
|
+
&:has(.phh-end) {
|
|
47
|
+
@container (width >= 768px) {
|
|
48
|
+
display: grid;
|
|
49
|
+
grid-template-columns: repeat(2, 1fr);
|
|
50
|
+
align-items: flex-end;
|
|
51
|
+
justify-content: space-between;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.phh-start {
|
|
56
|
+
/* flex: 1; */
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.phh-end {
|
|
60
|
+
display: flex;
|
|
61
|
+
align-items: center;
|
|
62
|
+
gap: var(--phh-end-gap);
|
|
63
|
+
/* flex-shrink: 0; */
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
</style>
|
package/app/components/04.templates/page-hero-highlights/stories/PageHeroHighlights.stories.ts
CHANGED
|
@@ -8,6 +8,7 @@ type StoryArgs = {
|
|
|
8
8
|
highlightsJustify?: "start" | "center" | "end" | "space-between" | "space-around";
|
|
9
9
|
maxWidth?: string;
|
|
10
10
|
contentAlign?: "start" | "center";
|
|
11
|
+
contentPanel?: boolean;
|
|
11
12
|
highlightTitleBaseline?: boolean;
|
|
12
13
|
headerBackground?: string;
|
|
13
14
|
contentBackground?: string;
|
|
@@ -35,7 +36,7 @@ const meta: Meta<StoryArgs> = {
|
|
|
35
36
|
},
|
|
36
37
|
maxWidth: {
|
|
37
38
|
control: { type: "select" },
|
|
38
|
-
options: ["", "600px", "800px", "1024px", "1200px", "1440px"],
|
|
39
|
+
options: ["", "600px", "800px", "1024px", "1064px", "1200px", "1440px"],
|
|
39
40
|
description:
|
|
40
41
|
"Max width of the central content column. Gutters grow to enforce the constraint; below this width they hold at 16px.",
|
|
41
42
|
},
|
|
@@ -45,6 +46,11 @@ const meta: Meta<StoryArgs> = {
|
|
|
45
46
|
description:
|
|
46
47
|
"Align the content column to the start (left gutter stays 16px, right takes remaining space) or center (equal gutters). Only meaningful when maxWidth is set.",
|
|
47
48
|
},
|
|
49
|
+
contentPanel: {
|
|
50
|
+
control: "boolean",
|
|
51
|
+
description:
|
|
52
|
+
"When true (default), renders a decorative panel behind the content slot and offsets the highlights strip. Set to false for a flat layout with no backdrop.",
|
|
53
|
+
},
|
|
48
54
|
highlightTitleBaseline: {
|
|
49
55
|
control: "boolean",
|
|
50
56
|
description:
|
|
@@ -74,6 +80,7 @@ const meta: Meta<StoryArgs> = {
|
|
|
74
80
|
highlightsJustify: "start",
|
|
75
81
|
maxWidth: "",
|
|
76
82
|
contentAlign: "center",
|
|
83
|
+
contentPanel: true,
|
|
77
84
|
highlightTitleBaseline: false,
|
|
78
85
|
headerBackground: "",
|
|
79
86
|
contentBackground: "",
|
|
@@ -162,8 +169,8 @@ All layout and visual properties are customisable via CSS custom properties. Set
|
|
|
162
169
|
<PageHeroHighlights v-bind="componentArgs" :style="bgStyles">
|
|
163
170
|
<template #header>
|
|
164
171
|
<div style="color: white; padding-block: 1.6rem;">
|
|
165
|
-
<
|
|
166
|
-
<p class="page-body-normal">Overview of your account activity and key metrics.</p>
|
|
172
|
+
<h1 class="page-heading-1" style="color: white;">Dashboard</h1>
|
|
173
|
+
<p class="page-body-normal" style="color: white;">Overview of your account activity and key metrics.</p>
|
|
167
174
|
</div>
|
|
168
175
|
</template>
|
|
169
176
|
|
|
@@ -402,3 +409,43 @@ export const MaxWidthStart: Story = {
|
|
|
402
409
|
`,
|
|
403
410
|
}),
|
|
404
411
|
};
|
|
412
|
+
|
|
413
|
+
/** No content panel — flat layout with no backdrop or highlight offset behind the content slot. */
|
|
414
|
+
export const NoContentPanel: Story = {
|
|
415
|
+
name: "No Content Panel",
|
|
416
|
+
args: { contentPanel: false },
|
|
417
|
+
render: (args: StoryArgs) => ({
|
|
418
|
+
components: { PageHeroHighlights },
|
|
419
|
+
setup() {
|
|
420
|
+
return useStorySetup(args);
|
|
421
|
+
},
|
|
422
|
+
template: `
|
|
423
|
+
<PageHeroHighlights v-bind="componentArgs" :style="bgStyles">
|
|
424
|
+
<template #header>
|
|
425
|
+
<p class="page-heading-1">Dashboard</p>
|
|
426
|
+
<p class="page-body-normal">Flat layout — no decorative panel behind the content slot.</p>
|
|
427
|
+
</template>
|
|
428
|
+
|
|
429
|
+
<template #highlights>
|
|
430
|
+
<div style="border-radius: 12px; background: #1a1a2e; color: white; padding: 1.6rem;">
|
|
431
|
+
<p class="page-heading-2">Total Revenue</p>
|
|
432
|
+
<p class="page-body-normal">£24,500</p>
|
|
433
|
+
</div>
|
|
434
|
+
<div v-if="highlightCount >= 2" style="border-radius: 12px; background: #1a1a2e; color: white; padding: 1.6rem;">
|
|
435
|
+
<p class="page-heading-2">Active Users</p>
|
|
436
|
+
<p class="page-body-normal">1,284</p>
|
|
437
|
+
</div>
|
|
438
|
+
<div v-if="highlightCount >= 3" style="border-radius: 12px; background: #1a1a2e; color: white; padding: 1.6rem;">
|
|
439
|
+
<p class="page-heading-2">Open Tasks</p>
|
|
440
|
+
<p class="page-body-normal">37</p>
|
|
441
|
+
</div>
|
|
442
|
+
</template>
|
|
443
|
+
|
|
444
|
+
<template #content>
|
|
445
|
+
<p class="page-heading-2">Recent Activity</p>
|
|
446
|
+
<p class="page-body-normal">Your most recent transactions and events will appear here.</p>
|
|
447
|
+
</template>
|
|
448
|
+
</PageHeroHighlights>
|
|
449
|
+
`,
|
|
450
|
+
}),
|
|
451
|
+
};
|
package/app/components/04.templates/page-hero-highlights/stories/PageHeroHighlightsHeader.stories.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import PageHeroHighlights from "../PageHeroHighlights.vue";
|
|
2
|
+
import PageHeroHighlightsHeader from "../PageHeroHighlightsHeader.vue";
|
|
3
|
+
import type { Meta, StoryObj } from "@nuxtjs/storybook";
|
|
4
|
+
|
|
5
|
+
type StoryArgs = {
|
|
6
|
+
styleClassPassthrough?: string | string[];
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const meta: Meta<StoryArgs> = {
|
|
10
|
+
title: "Templates/PageHeroHighlightsHeader",
|
|
11
|
+
component: PageHeroHighlightsHeader,
|
|
12
|
+
argTypes: {
|
|
13
|
+
styleClassPassthrough: {
|
|
14
|
+
control: "object",
|
|
15
|
+
description: "Additional CSS classes applied to the root element",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
args: {
|
|
19
|
+
styleClassPassthrough: [],
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default meta;
|
|
24
|
+
type Story = StoryObj<typeof PageHeroHighlightsHeader>;
|
|
25
|
+
|
|
26
|
+
/** Default — start slot only, fills full width. */
|
|
27
|
+
export const Default: Story = {
|
|
28
|
+
render: (args: StoryArgs) => ({
|
|
29
|
+
components: { PageHeroHighlights, PageHeroHighlightsHeader },
|
|
30
|
+
setup() {
|
|
31
|
+
return { args };
|
|
32
|
+
},
|
|
33
|
+
template: `
|
|
34
|
+
<PageHeroHighlights tag="section" style="--header-row-background-colour: #2d4a35;">
|
|
35
|
+
<template #header>
|
|
36
|
+
<PageHeroHighlightsHeader v-bind="args">
|
|
37
|
+
<template #start>
|
|
38
|
+
<div style="color: white; padding-block: 1.6rem;">
|
|
39
|
+
<h1 class="page-heading-1" style="color: white;">Dashboard</h1>
|
|
40
|
+
<p class="page-body-normal" style="color: white;">Overview of your account activity and key metrics.</p>
|
|
41
|
+
</div>
|
|
42
|
+
</template>
|
|
43
|
+
</PageHeroHighlightsHeader>
|
|
44
|
+
</template>
|
|
45
|
+
</PageHeroHighlights>
|
|
46
|
+
`,
|
|
47
|
+
}),
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/** With actions — start slot for title/description, end slot for action buttons. */
|
|
51
|
+
export const WithActions: Story = {
|
|
52
|
+
name: "With Actions",
|
|
53
|
+
render: (args: StoryArgs) => ({
|
|
54
|
+
components: { PageHeroHighlights, PageHeroHighlightsHeader },
|
|
55
|
+
setup() {
|
|
56
|
+
return { args };
|
|
57
|
+
},
|
|
58
|
+
template: `
|
|
59
|
+
<PageHeroHighlights tag="section" style="--header-row-background-colour: #2d4a35;">
|
|
60
|
+
<template #header>
|
|
61
|
+
<PageHeroHighlightsHeader v-bind="args">
|
|
62
|
+
<template #start>
|
|
63
|
+
<div style="color: white; padding-block: 1.6rem;">
|
|
64
|
+
<h1 class="page-heading-1" style="color: white;">Dashboard</h1>
|
|
65
|
+
<p class="page-body-normal" style="color: white;">Overview of your account activity and key metrics.</p>
|
|
66
|
+
</div>
|
|
67
|
+
</template>
|
|
68
|
+
<template #end>
|
|
69
|
+
<button style="border: 2px solid white; color: white; background: transparent; border-radius: 50%; width: 4rem; height: 4rem; cursor: pointer;">?</button>
|
|
70
|
+
<button style="border: 2px solid white; color: white; background: transparent; border-radius: 0.8rem; padding: 1rem 1.6rem; cursor: pointer;">Create something new</button>
|
|
71
|
+
</template>
|
|
72
|
+
</PageHeroHighlightsHeader>
|
|
73
|
+
</template>
|
|
74
|
+
</PageHeroHighlights>
|
|
75
|
+
`,
|
|
76
|
+
}),
|
|
77
|
+
};
|
|
@@ -45,10 +45,7 @@ describe("PageHeroHighlights", () => {
|
|
|
45
45
|
it("renders highlights slot content", async () => {
|
|
46
46
|
const wrapper = await mountSuspended(PageHeroHighlights, {
|
|
47
47
|
slots: {
|
|
48
|
-
highlights: [
|
|
49
|
-
"<div class='highlight-card'>Card 1</div>",
|
|
50
|
-
"<div class='highlight-card'>Card 2</div>",
|
|
51
|
-
].join(""),
|
|
48
|
+
highlights: ["<div class='highlight-card'>Card 1</div>", "<div class='highlight-card'>Card 2</div>"].join(""),
|
|
52
49
|
},
|
|
53
50
|
});
|
|
54
51
|
expect(wrapper.findAll(".highlight-card").length).toBe(2);
|
|
@@ -101,8 +98,7 @@ describe("PageHeroHighlights", () => {
|
|
|
101
98
|
const wrapper = await mountSuspended(PageHeroHighlights, {
|
|
102
99
|
props: { tag: "section" },
|
|
103
100
|
slots: {
|
|
104
|
-
header: (props: Record<string, unknown>) =>
|
|
105
|
-
h("h1", { id: props.headingId, class: "page-title" }, "Dashboard"),
|
|
101
|
+
header: (props: Record<string, unknown>) => h("h1", { id: props.headingId, class: "page-title" }, "Dashboard"),
|
|
106
102
|
},
|
|
107
103
|
});
|
|
108
104
|
const labelledBy = wrapper.find(".page-hero-highlights").attributes("aria-labelledby");
|
|
@@ -139,6 +135,18 @@ describe("PageHeroHighlights", () => {
|
|
|
139
135
|
}
|
|
140
136
|
});
|
|
141
137
|
|
|
138
|
+
it("applies has-content-panel class by default", async () => {
|
|
139
|
+
const wrapper = await mountSuspended(PageHeroHighlights);
|
|
140
|
+
expect(wrapper.find(".page-hero-highlights").classes()).toContain("has-content-panel");
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("does not apply has-content-panel class when contentPanel is false", async () => {
|
|
144
|
+
const wrapper = await mountSuspended(PageHeroHighlights, {
|
|
145
|
+
props: { contentPanel: false },
|
|
146
|
+
});
|
|
147
|
+
expect(wrapper.find(".page-hero-highlights").classes()).not.toContain("has-content-panel");
|
|
148
|
+
});
|
|
149
|
+
|
|
142
150
|
it("does not apply highlight-title-baseline class by default", async () => {
|
|
143
151
|
const wrapper = await mountSuspended(PageHeroHighlights);
|
|
144
152
|
expect(wrapper.find(".page-hero-highlights").classes()).not.toContain("highlight-title-baseline");
|
|
@@ -184,7 +192,7 @@ describe("PageHeroHighlights", () => {
|
|
|
184
192
|
props: { maxWidth: "1064px", contentAlign: "start" },
|
|
185
193
|
});
|
|
186
194
|
const vm = wrapper.vm as unknown as ComponentInstance;
|
|
187
|
-
expect(vm.gridColumns).toBe("16px minmax(0, 1064px) 1fr");
|
|
195
|
+
expect(vm.gridColumns).toBe("16px minmax(0, 1064px) minmax(16px, 1fr)");
|
|
188
196
|
});
|
|
189
197
|
|
|
190
198
|
it("ignores contentAlign when maxWidth is not set", async () => {
|
package/app/components/04.templates/page-hero-highlights/tests/PageHeroHighlightsHeader.spec.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { mountSuspended } from "@nuxt/test-utils/runtime";
|
|
3
|
+
import PageHeroHighlightsHeader from "../PageHeroHighlightsHeader.vue";
|
|
4
|
+
|
|
5
|
+
describe("PageHeroHighlightsHeader", () => {
|
|
6
|
+
it("mounts without error", async () => {
|
|
7
|
+
const wrapper = await mountSuspended(PageHeroHighlightsHeader);
|
|
8
|
+
expect(wrapper.vm).toBeTruthy();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("renders start slot content", async () => {
|
|
12
|
+
const wrapper = await mountSuspended(PageHeroHighlightsHeader, {
|
|
13
|
+
slots: { start: "<h1 class='page-title'>Surplus needs</h1>" },
|
|
14
|
+
});
|
|
15
|
+
expect(wrapper.find(".phh-start .page-title").exists()).toBe(true);
|
|
16
|
+
expect(wrapper.html()).toContain("Surplus needs");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("renders end slot content when provided", async () => {
|
|
20
|
+
const wrapper = await mountSuspended(PageHeroHighlightsHeader, {
|
|
21
|
+
slots: {
|
|
22
|
+
start: "<h1>Title</h1>",
|
|
23
|
+
end: "<button class='cta'>Create new need</button>",
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
expect(wrapper.find(".phh-end .cta").exists()).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("does not render .phh-end when no end slot is provided", async () => {
|
|
30
|
+
const wrapper = await mountSuspended(PageHeroHighlightsHeader, {
|
|
31
|
+
slots: { start: "<h1>Title</h1>" },
|
|
32
|
+
});
|
|
33
|
+
expect(wrapper.find(".phh-end").exists()).toBe(false);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("renders .phh-start as full width when no end slot is provided", async () => {
|
|
37
|
+
const wrapper = await mountSuspended(PageHeroHighlightsHeader, {
|
|
38
|
+
slots: { start: "<h1>Title</h1>" },
|
|
39
|
+
});
|
|
40
|
+
expect(wrapper.find(".phh-start").exists()).toBe(true);
|
|
41
|
+
expect(wrapper.find(".phh-end").exists()).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("applies styleClassPassthrough classes", async () => {
|
|
45
|
+
const wrapper = await mountSuspended(PageHeroHighlightsHeader, {
|
|
46
|
+
props: { styleClassPassthrough: ["extra-class", "another-class"] },
|
|
47
|
+
});
|
|
48
|
+
expect(wrapper.find(".page-hero-highlights-header").classes()).toContain("extra-class");
|
|
49
|
+
expect(wrapper.find(".page-hero-highlights-header").classes()).toContain("another-class");
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
3
|
exports[`PageHeroHighlights > renders correct HTML structure 1`] = `
|
|
4
|
-
"<div class="page-hero-highlights">
|
|
4
|
+
"<div class="page-hero-highlights has-content-panel">
|
|
5
5
|
<div class="header-row">
|
|
6
6
|
<div class="header-slot">
|
|
7
7
|
<h1>Page Title</h1>
|