srcdev-nuxt-components 9.5.7 → 9.6.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/skills/component-compliance-checklist.md +8 -2
- 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/breadcrumb.md +5 -0
- package/.claude/skills/components/container-glow.md +21 -8
- package/.claude/skills/components/display-avatar.md +13 -7
- package/.claude/skills/components/display-chip.md +37 -24
- package/.claude/skills/components/display-pill.md +58 -8
- 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/input-button.md +3 -0
- package/.claude/skills/components/responsive-header.md +59 -0
- package/.claude/skills/components/select-menu.md +54 -5
- package/.claude/skills/components/service-detail.md +32 -0
- package/.claude/skills/components/service-summary.md +8 -0
- package/.claude/skills/components/services-card-grid.md +5 -3
- package/.claude/skills/components/services-card.md +22 -12
- package/.claude/skills/components/site-header.md +2 -2
- package/.claude/skills/components/slider-gallery.md +10 -4
- package/.claude/skills/components/tabbed-content.md +300 -0
- package/.claude/skills/composable-anchor-scroll.md +16 -15
- package/.claude/skills/index.md +4 -5
- package/.claude/skills/storybook-add-story.md +53 -0
- package/.claude/skills/theming-status-tokens.md +60 -0
- package/.vscode/srcdev-component-display-avatar.code-snippets +2 -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-responsive-header.code-snippets +16 -0
- package/.vscode/srcdev-component-select-menu.code-snippets +28 -0
- package/.vscode/srcdev-component-service-detail.code-snippets +1 -0
- package/.vscode/srcdev-component-service-summary.code-snippets +3 -1
- package/.vscode/srcdev-component-services-card.code-snippets +38 -36
- package/.vscode/srcdev-component-services-grids.code-snippets +2 -1
- 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 +78 -9
- package/app/components/01.atoms/display-pill/DisplayPill.vue +59 -23
- 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/navigation/breadcrumb/Breadcrumb.vue +16 -4
- package/app/components/01.atoms/navigation/breadcrumb/CONSUMER-STYLING.md +28 -5
- package/app/components/01.atoms/navigation/breadcrumb/stories/Breadcrumb.stories.ts +94 -0
- package/app/components/01.atoms/navigation/breadcrumb/tests/Breadcrumb.spec.ts +27 -0
- 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 +7 -5
- package/app/components/02.molecules/display-avatar/DisplayAvatar.vue +6 -2
- package/app/components/02.molecules/display-avatar/stories/DisplayAvatar.stories.ts +24 -3
- package/app/components/02.molecules/display-avatar/tests/DisplayAvatar.spec.ts +19 -0
- package/app/components/02.molecules/display-avatar/tests/__snapshots__/DisplayAvatar.spec.ts.snap +2 -1
- package/app/components/02.molecules/display-chip/CONSUMER-STYLING.md +52 -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/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/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/image-galleries/slider-gallery/CONSUMER-STYLING.md +19 -1
- package/app/components/03.organisms/image-galleries/slider-gallery/SliderGallery.vue +65 -7
- package/app/components/03.organisms/image-galleries/slider-gallery/stories/SliderGallery.stories.ts +201 -63
- package/app/components/03.organisms/image-galleries/slider-gallery/tests/SliderGallery.spec.ts +41 -2
- package/app/components/03.organisms/image-galleries/slider-gallery/tests/__snapshots__/SliderGallery.spec.ts.snap +6 -6
- package/app/components/03.organisms/responsive-header/CONSUMER-STYLING.md +42 -11
- package/app/components/03.organisms/responsive-header/NavigationItems.vue +60 -16
- package/app/components/03.organisms/responsive-header/ResponsiveHeader.vue +86 -24
- package/app/components/03.organisms/responsive-header/stories/ResponsiveHeader.stories.ts +52 -0
- package/app/components/03.organisms/responsive-header/tests/NavigationItems.spec.ts +20 -0
- package/app/components/03.organisms/responsive-header/tests/ResponsiveHeader.spec.ts +40 -0
- package/app/components/03.organisms/services/service-detail/CONSUMER-STYLING.md +92 -41
- package/app/components/03.organisms/services/service-detail/ServiceDetail.vue +198 -73
- package/app/components/03.organisms/services/service-detail/stories/ServiceDetail.stories.ts +157 -9
- package/app/components/03.organisms/services/service-detail/tests/ServiceDetail.spec.ts +58 -0
- package/app/components/03.organisms/services/service-detail/tests/__snapshots__/ServiceDetail.spec.ts.snap +5 -4
- package/app/components/03.organisms/services/service-summary/CONSUMER-STYLING.md +30 -0
- package/app/components/03.organisms/services/service-summary/ServiceSummary.vue +32 -8
- package/app/components/03.organisms/services/service-summary/stories/ServiceSummary.stories.ts +147 -0
- package/app/components/03.organisms/services/service-summary/tests/ServiceSummary.spec.ts +26 -0
- package/app/components/03.organisms/services/service-summary/tests/__snapshots__/ServiceSummary.spec.ts.snap +2 -2
- package/app/components/03.organisms/services/services-card/CONSUMER-STYLING.md +104 -63
- package/app/components/03.organisms/services/services-card/ServicesCard.vue +92 -66
- package/app/components/03.organisms/services/services-card/stories/ServicesCard.stories.ts +194 -27
- package/app/components/03.organisms/services/services-card/tests/ServicesCard.spec.ts +34 -8
- package/app/components/03.organisms/services/services-card/tests/__snapshots__/ServicesCard.spec.ts.snap +8 -8
- package/app/components/03.organisms/services/services-grids/CONSUMER-STYLING.md +9 -0
- package/app/components/03.organisms/services/services-grids/ServicesCardGrid.vue +2 -1
- package/app/components/03.organisms/services/services-grids/stories/ServiceSummaryGrid.stories.ts +46 -6
- package/app/components/03.organisms/services/services-grids/stories/ServicesCardGrid.stories.ts +89 -11
- package/app/components/03.organisms/services/services-grids/tests/ServicesCardGrid.spec.ts +8 -0
- package/app/components/03.organisms/services/services-grids/tests/__snapshots__/ServiceSummaryGrid.spec.ts.snap +6 -6
- package/app/components/03.organisms/services/services-grids/tests/__snapshots__/ServicesCardGrid.spec.ts.snap +24 -24
- package/app/components/05.forms/input-button/CONSUMER-STYLING.md +8 -0
- package/app/components/05.forms/input-button/InputButton.vue +3 -1
- package/app/composables/tests/useAnchorScroll.spec.ts +8 -0
- package/app/composables/useAnchorScroll.ts +1 -1
- 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/site-navigation.md +0 -145
- package/.claude/skills/components/tab-navigation.md +0 -272
- package/.claude/skills/components/tabs-core.md +0 -187
- package/.vscode/srcdev-component-site-navigation.code-snippets +0 -38
- 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/site-navigation/CONSUMER-STYLING.md +0 -109
- package/app/components/02.molecules/navigation/site-navigation/SiteNavigation.vue +0 -751
- package/app/components/02.molecules/navigation/site-navigation/stories/SiteNavigation.stories.ts +0 -356
- package/app/components/02.molecules/navigation/site-navigation/tests/SiteNavigation.spec.ts +0 -367
- package/app/components/02.molecules/navigation/site-navigation/tests/__snapshots__/SiteNavigation.spec.ts.snap +0 -30
- package/app/components/02.molecules/navigation/tab-navigation/CONSUMER-STYLING.md +0 -150
- package/app/components/02.molecules/navigation/tab-navigation/TabNavigation.vue +0 -518
- package/app/components/02.molecules/navigation/tab-navigation/stories/TabNavigation.stories.ts +0 -340
- package/app/components/02.molecules/navigation/tab-navigation/tests/TabNavigation.spec.ts +0 -339
- 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
|
@@ -25,7 +25,14 @@
|
|
|
25
25
|
:data-text-brightness="item.textBrightness"
|
|
26
26
|
:data-has-text="hasSlideText(item) ? '' : undefined"
|
|
27
27
|
>
|
|
28
|
-
<NuxtImg
|
|
28
|
+
<NuxtImg
|
|
29
|
+
:src="item.src"
|
|
30
|
+
:alt="item.alt"
|
|
31
|
+
width="1920"
|
|
32
|
+
height="1080"
|
|
33
|
+
@load="handleImageLoad(index)"
|
|
34
|
+
@error="handleImageError(index)"
|
|
35
|
+
/>
|
|
29
36
|
<div class="slider-gallery-item-content" :class="item.textBrightness">
|
|
30
37
|
<div v-if="item.stylist" class="slider-gallery-author">{{ item.stylist }}</div>
|
|
31
38
|
<div v-if="item.title" class="slider-gallery-title">{{ item.title }}</div>
|
|
@@ -41,7 +48,7 @@
|
|
|
41
48
|
<div ref="sliderGalleryThumbnailsList" class="slider-gallery-thumbnails" aria-hidden="true">
|
|
42
49
|
<div v-for="(item, index) in galleryData" :key="index" class="slider-gallery-item">
|
|
43
50
|
<div class="slider-gallery-thumbnail-overlay">
|
|
44
|
-
<NuxtImg :src="item.src" alt="" loading="lazy" />
|
|
51
|
+
<NuxtImg :src="item.src" alt="" width="640" height="940" loading="lazy" />
|
|
45
52
|
<div class="slider-gallery-item-content" :class="item.textBrightness">
|
|
46
53
|
<div v-if="item.thumbnail?.title" class="slider-gallery-title">{{ item.thumbnail.title }}</div>
|
|
47
54
|
<div v-if="item.thumbnail?.description" class="slider-gallery-description">
|
|
@@ -138,6 +145,12 @@ const prefersReducedMotion = () =>
|
|
|
138
145
|
typeof window !== "undefined" && !!window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
139
146
|
const shouldAutoRun = () => props.autoRun && !prefersReducedMotion();
|
|
140
147
|
|
|
148
|
+
const finiteOr = (value: number, fallback: number) => (Number.isFinite(value) ? value : fallback);
|
|
149
|
+
const safeAnimationDuration = computed(() => Math.max(0, finiteOr(props.animationDuration, 3000)));
|
|
150
|
+
const safeAutoRunInterval = computed(() =>
|
|
151
|
+
Math.max(1000, safeAnimationDuration.value, finiteOr(props.autoRunInterval, 7000))
|
|
152
|
+
);
|
|
153
|
+
|
|
141
154
|
onMounted(async () => {
|
|
142
155
|
await nextTick();
|
|
143
156
|
|
|
@@ -203,12 +216,12 @@ function scheduleAutoRun() {
|
|
|
203
216
|
if (runNextAuto) clearTimeout(runNextAuto);
|
|
204
217
|
runNextAuto = setTimeout(() => {
|
|
205
218
|
if (!shouldAutoRun() || isLoading.value) return;
|
|
206
|
-
if (isPaused.value) {
|
|
219
|
+
if (isPaused.value || transitionRunning.value) {
|
|
207
220
|
scheduleAutoRun();
|
|
208
221
|
return;
|
|
209
222
|
}
|
|
210
223
|
doNext();
|
|
211
|
-
},
|
|
224
|
+
}, safeAutoRunInterval.value);
|
|
212
225
|
}
|
|
213
226
|
|
|
214
227
|
function showSlider(type: "next" | "prev") {
|
|
@@ -249,7 +262,7 @@ function showSlider(type: "next" | "prev") {
|
|
|
249
262
|
sliderGalleryWrapper.value.querySelectorAll(".is-prepended").forEach((el) => el.classList.remove("is-prepended"));
|
|
250
263
|
}
|
|
251
264
|
transitionRunning.value = false;
|
|
252
|
-
},
|
|
265
|
+
}, safeAnimationDuration.value);
|
|
253
266
|
|
|
254
267
|
scheduleAutoRun();
|
|
255
268
|
}
|
|
@@ -286,13 +299,13 @@ onBeforeUnmount(() => {
|
|
|
286
299
|
<style lang="css">
|
|
287
300
|
@layer components {
|
|
288
301
|
.slider-gallery {
|
|
289
|
-
--_animation-duration: v-bind(
|
|
302
|
+
--_animation-duration: v-bind(safeAnimationDuration + "ms");
|
|
290
303
|
--_accent: var(--slider-gallery-accent, #f1683a);
|
|
291
304
|
--_thumbnail-width: var(--slider-gallery-thumbnail-width, 100px);
|
|
292
305
|
--_thumbnail-height: var(--slider-gallery-thumbnail-height, 165px);
|
|
293
306
|
|
|
294
307
|
height: var(--slider-gallery-height, 100svh);
|
|
295
|
-
width: 100vw;
|
|
308
|
+
width: var(--slider-gallery-width, 100vw);
|
|
296
309
|
overflow: hidden;
|
|
297
310
|
position: absolute;
|
|
298
311
|
inset: 0;
|
|
@@ -333,6 +346,10 @@ onBeforeUnmount(() => {
|
|
|
333
346
|
p {
|
|
334
347
|
font-size: 1.2em;
|
|
335
348
|
font-weight: 500;
|
|
349
|
+
max-inline-size: 100%;
|
|
350
|
+
padding-inline: 1.6rem;
|
|
351
|
+
text-align: center;
|
|
352
|
+
overflow-wrap: anywhere;
|
|
336
353
|
}
|
|
337
354
|
}
|
|
338
355
|
|
|
@@ -435,14 +452,41 @@ onBeforeUnmount(() => {
|
|
|
435
452
|
padding-right: 30%;
|
|
436
453
|
box-sizing: border-box;
|
|
437
454
|
text-shadow: 0 5px 10px #0004;
|
|
455
|
+
overflow-wrap: anywhere;
|
|
438
456
|
|
|
439
457
|
@container (width < 678px) {
|
|
440
458
|
padding-right: 0;
|
|
441
459
|
}
|
|
442
460
|
|
|
461
|
+
.slider-gallery-author,
|
|
462
|
+
.slider-gallery-title,
|
|
463
|
+
.slider-gallery-topic,
|
|
464
|
+
.slider-gallery-description {
|
|
465
|
+
display: -webkit-box;
|
|
466
|
+
-webkit-box-orient: vertical;
|
|
467
|
+
overflow: hidden;
|
|
468
|
+
}
|
|
469
|
+
|
|
443
470
|
.slider-gallery-author {
|
|
444
471
|
font-weight: bold;
|
|
445
472
|
letter-spacing: 10px;
|
|
473
|
+
-webkit-line-clamp: var(--slider-gallery-author-line-clamp, none);
|
|
474
|
+
line-clamp: var(--slider-gallery-author-line-clamp, none);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
.slider-gallery-title {
|
|
478
|
+
-webkit-line-clamp: var(--slider-gallery-title-line-clamp, none);
|
|
479
|
+
line-clamp: var(--slider-gallery-title-line-clamp, none);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
.slider-gallery-topic {
|
|
483
|
+
-webkit-line-clamp: var(--slider-gallery-topic-line-clamp, none);
|
|
484
|
+
line-clamp: var(--slider-gallery-topic-line-clamp, none);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
.slider-gallery-description {
|
|
488
|
+
-webkit-line-clamp: var(--slider-gallery-description-line-clamp, none);
|
|
489
|
+
line-clamp: var(--slider-gallery-description-line-clamp, none);
|
|
446
490
|
}
|
|
447
491
|
|
|
448
492
|
.slider-gallery-title,
|
|
@@ -466,7 +510,9 @@ onBeforeUnmount(() => {
|
|
|
466
510
|
place-items: center;
|
|
467
511
|
min-width: 130px;
|
|
468
512
|
min-height: 40px;
|
|
513
|
+
max-inline-size: 100%;
|
|
469
514
|
padding-inline: 1.2rem;
|
|
515
|
+
box-sizing: border-box;
|
|
470
516
|
background-color: var(--slider-gallery-cta-background, #99999975);
|
|
471
517
|
border: 1px solid var(--slider-gallery-cta-border-colour, #fff);
|
|
472
518
|
color: var(--slider-gallery-cta-colour, #fff);
|
|
@@ -528,13 +574,25 @@ onBeforeUnmount(() => {
|
|
|
528
574
|
bottom: 10px;
|
|
529
575
|
left: 10px;
|
|
530
576
|
right: 10px;
|
|
577
|
+
overflow-wrap: anywhere;
|
|
578
|
+
|
|
579
|
+
.slider-gallery-title,
|
|
580
|
+
.slider-gallery-description {
|
|
581
|
+
display: -webkit-box;
|
|
582
|
+
-webkit-box-orient: vertical;
|
|
583
|
+
overflow: hidden;
|
|
584
|
+
}
|
|
531
585
|
|
|
532
586
|
.slider-gallery-title {
|
|
533
587
|
font-weight: 500;
|
|
588
|
+
-webkit-line-clamp: var(--slider-gallery-thumbnail-title-line-clamp, 2);
|
|
589
|
+
line-clamp: var(--slider-gallery-thumbnail-title-line-clamp, 2);
|
|
534
590
|
}
|
|
535
591
|
|
|
536
592
|
.slider-gallery-description {
|
|
537
593
|
font-weight: 300;
|
|
594
|
+
-webkit-line-clamp: var(--slider-gallery-thumbnail-description-line-clamp, 2);
|
|
595
|
+
line-clamp: var(--slider-gallery-thumbnail-description-line-clamp, 2);
|
|
538
596
|
}
|
|
539
597
|
}
|
|
540
598
|
}
|
package/app/components/03.organisms/image-galleries/slider-gallery/stories/SliderGallery.stories.ts
CHANGED
|
@@ -1,11 +1,54 @@
|
|
|
1
|
+
import { computed, ref } from "vue";
|
|
1
2
|
import SliderGallery from "../SliderGallery.vue";
|
|
3
|
+
import CanvasSwitcher from "../../../../01.atoms/canvas-switcher/CanvasSwitcher.vue";
|
|
2
4
|
import type { Meta, StoryObj } from "@nuxtjs/storybook";
|
|
3
|
-
import type { IGalleryData } from "~/types/components";
|
|
5
|
+
import type { IGalleryData, MediaCanvas } from "~/types/components";
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
type LineClamp = "none" | "1" | "2" | "3" | "4";
|
|
8
|
+
|
|
9
|
+
// Story-only args: each drives a CSS token, not a SliderGallery prop. See the argTypes entries.
|
|
10
|
+
const lineClampTokens = {
|
|
11
|
+
authorLineClamp: { token: "--slider-gallery-author-line-clamp", label: "Author (stylist)", fallback: "none" },
|
|
12
|
+
titleLineClamp: { token: "--slider-gallery-title-line-clamp", label: "Title", fallback: "none" },
|
|
13
|
+
topicLineClamp: { token: "--slider-gallery-topic-line-clamp", label: "Topic (category)", fallback: "none" },
|
|
14
|
+
descriptionLineClamp: { token: "--slider-gallery-description-line-clamp", label: "Description", fallback: "none" },
|
|
15
|
+
thumbnailTitleLineClamp: { token: "--slider-gallery-thumbnail-title-line-clamp", label: "Thumbnail title", fallback: "2" },
|
|
16
|
+
thumbnailDescriptionLineClamp: {
|
|
17
|
+
token: "--slider-gallery-thumbnail-description-line-clamp",
|
|
18
|
+
label: "Thumbnail description",
|
|
19
|
+
fallback: "2",
|
|
20
|
+
},
|
|
21
|
+
} as const;
|
|
22
|
+
|
|
23
|
+
type LineClampArg = keyof typeof lineClampTokens;
|
|
24
|
+
|
|
25
|
+
type StoryArgs = InstanceType<typeof SliderGallery>["$props"] & Record<LineClampArg, LineClamp>;
|
|
26
|
+
|
|
27
|
+
const lineClampArgTypes = Object.fromEntries(
|
|
28
|
+
Object.entries(lineClampTokens).map(([arg, { token, label, fallback }]) => [
|
|
29
|
+
arg,
|
|
30
|
+
{
|
|
31
|
+
name: `${label} line clamp`,
|
|
32
|
+
control: "select",
|
|
33
|
+
options: ["none", "1", "2", "3", "4"] satisfies LineClamp[],
|
|
34
|
+
description:
|
|
35
|
+
`**Story control, not a prop.** Sets the \`${token}\` CSS token on a wrapper so you can try it here. ` +
|
|
36
|
+
`To use it in an app, set the token in your own CSS, e.g. \`.hero { ${token}: 2; }\`. ` +
|
|
37
|
+
`\`1\` is single-line ellipsis, \`none\` shows everything.`,
|
|
38
|
+
table: { category: "CSS tokens (story only, set in your CSS)", defaultValue: { summary: fallback } },
|
|
39
|
+
},
|
|
40
|
+
])
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const lineClampArgs = Object.fromEntries(
|
|
44
|
+
Object.entries(lineClampTokens).map(([arg, { fallback }]) => [arg, fallback])
|
|
45
|
+
) as Record<LineClampArg, LineClamp>;
|
|
46
|
+
|
|
47
|
+
const meta: Meta<StoryArgs> = {
|
|
6
48
|
title: "Organisms/Image Galleries/Slider Gallery",
|
|
7
49
|
component: SliderGallery,
|
|
8
50
|
argTypes: {
|
|
51
|
+
...lineClampArgTypes,
|
|
9
52
|
autoRun: {
|
|
10
53
|
control: { type: "boolean" },
|
|
11
54
|
description: "Automatically advance to the next slide",
|
|
@@ -40,6 +83,7 @@ const meta: Meta<typeof SliderGallery> = {
|
|
|
40
83
|
},
|
|
41
84
|
},
|
|
42
85
|
args: {
|
|
86
|
+
...lineClampArgs,
|
|
43
87
|
autoRun: true,
|
|
44
88
|
autoRunInterval: 7000,
|
|
45
89
|
animationDuration: 3000,
|
|
@@ -64,7 +108,7 @@ const meta: Meta<typeof SliderGallery> = {
|
|
|
64
108
|
};
|
|
65
109
|
|
|
66
110
|
export default meta;
|
|
67
|
-
type Story = StoryObj<
|
|
111
|
+
type Story = StoryObj<StoryArgs>;
|
|
68
112
|
|
|
69
113
|
// ─── Fixtures ─────────────────────────────────────────────────────────────────
|
|
70
114
|
|
|
@@ -123,17 +167,105 @@ const sampleSlides: IGalleryData[] = [
|
|
|
123
167
|
},
|
|
124
168
|
];
|
|
125
169
|
|
|
170
|
+
const longGerman =
|
|
171
|
+
"Donaudampfschifffahrtsgesellschaftskapitänsmützenbandherstellungsbetriebsgenossenschaftsvorsitzender";
|
|
172
|
+
const longUrl =
|
|
173
|
+
"https://example.com/a/very/long/path/that/never/breaks/because/it/has/no/spaces/at/all?utm_source=newsletter&utm_medium=email&utm_campaign=autumn-collection-2026-final-final-v3";
|
|
174
|
+
const longParagraph =
|
|
175
|
+
"Eine ausgesprochen lange Beschreibung, wie sie ein CMS liefert, wenn niemand die Zeichenanzahl prüft. ".repeat(8);
|
|
176
|
+
|
|
177
|
+
const stressSlides: IGalleryData[] = [
|
|
178
|
+
{
|
|
179
|
+
src: "https://picsum.photos/seed/stress1/1920/1080",
|
|
180
|
+
alt: "Long German copy in every field",
|
|
181
|
+
stylist: `STYLISTIN ${longGerman.toUpperCase()}`,
|
|
182
|
+
title: `${longGerman} und Freunde`,
|
|
183
|
+
category: "Haarverlängerungen, Strähnchen und vollständige Farbkorrekturen",
|
|
184
|
+
description: longParagraph,
|
|
185
|
+
thumbnail: { title: longGerman, description: longParagraph },
|
|
186
|
+
textBrightness: "light",
|
|
187
|
+
href: longUrl,
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
src: "https://picsum.photos/seed/stress2/1920/1080",
|
|
191
|
+
alt: "Emoji and HTML-like text",
|
|
192
|
+
stylist: "💇♀️✨ SALON 🎉",
|
|
193
|
+
title: "<script>alert('xss')</script>",
|
|
194
|
+
category: "<b>not bold</b> & <tags>",
|
|
195
|
+
description: "🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈",
|
|
196
|
+
thumbnail: { title: "😀 Emoji first", description: "<img src=x onerror=alert(1)>" },
|
|
197
|
+
textBrightness: "dark",
|
|
198
|
+
href: "#emoji",
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
src: "https://picsum.photos/seed/stress3/1920/1080",
|
|
202
|
+
alt: "صورة لصالون تصفيف الشعر",
|
|
203
|
+
stylist: "مصففة الشعر",
|
|
204
|
+
title: "تسريحات شعر جديدة لموسم الخريف",
|
|
205
|
+
category: "تلوين الشعر",
|
|
206
|
+
description: "وصف طويل باللغة العربية يمتد عبر عدة أسطر للتحقق من أن النص من اليمين إلى اليسار يعرض بشكل صحيح.",
|
|
207
|
+
thumbnail: { title: "تسريحات", description: "تلوين الشعر" },
|
|
208
|
+
textBrightness: "light",
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
src: "https://example.invalid/this-image-does-not-exist.jpg",
|
|
212
|
+
alt: "Broken image URL: the alt text should show instead",
|
|
213
|
+
stylist: "A",
|
|
214
|
+
title: "B",
|
|
215
|
+
category: "C",
|
|
216
|
+
description: "",
|
|
217
|
+
thumbnail: { title: "", description: "" },
|
|
218
|
+
textBrightness: "dark",
|
|
219
|
+
href: "",
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
src: "https://picsum.photos/seed/stress5/1920/1080",
|
|
223
|
+
alt: "",
|
|
224
|
+
textBrightness: "light",
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
src: "https://picsum.photos/seed/stress6/1920/1080",
|
|
228
|
+
alt: "Unbroken URL as description",
|
|
229
|
+
title: "Link soup",
|
|
230
|
+
description: longUrl,
|
|
231
|
+
thumbnail: { title: longUrl, description: longUrl },
|
|
232
|
+
textBrightness: "light",
|
|
233
|
+
href: "#link-soup",
|
|
234
|
+
},
|
|
235
|
+
...Array.from({ length: 24 }, (_, index): IGalleryData => ({
|
|
236
|
+
src: `https://picsum.photos/seed/stress-many-${index}/1920/1080`,
|
|
237
|
+
alt: `Filler slide ${index + 7}`,
|
|
238
|
+
title: `Slide ${index + 7}`,
|
|
239
|
+
thumbnail: { title: `Slide ${index + 7}`, description: "Filler" },
|
|
240
|
+
textBrightness: "light",
|
|
241
|
+
})),
|
|
242
|
+
];
|
|
243
|
+
|
|
126
244
|
// ─── Stories ──────────────────────────────────────────────────────────────────
|
|
127
245
|
|
|
246
|
+
function useStorySetup(args: StoryArgs) {
|
|
247
|
+
const componentArgs = computed(() =>
|
|
248
|
+
Object.fromEntries(Object.entries(args).filter(([arg]) => !(arg in lineClampTokens)))
|
|
249
|
+
);
|
|
250
|
+
const tokenStyles = computed(() =>
|
|
251
|
+
Object.fromEntries(
|
|
252
|
+
Object.entries(lineClampTokens).map(([arg, { token }]) => [token, args[arg as LineClampArg]])
|
|
253
|
+
)
|
|
254
|
+
);
|
|
255
|
+
return { componentArgs, tokenStyles };
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const renderWith = (slides: IGalleryData[]) => (args: StoryArgs) => ({
|
|
259
|
+
components: { SliderGallery },
|
|
260
|
+
setup() {
|
|
261
|
+
const galleryData = ref<IGalleryData[]>(slides);
|
|
262
|
+
return { ...useStorySetup(args), galleryData };
|
|
263
|
+
},
|
|
264
|
+
template: `<div :style="tokenStyles"><SliderGallery v-bind="componentArgs" v-model:gallery-data="galleryData" /></div>`,
|
|
265
|
+
});
|
|
266
|
+
|
|
128
267
|
export const Default: Story = {
|
|
129
|
-
render: (
|
|
130
|
-
components: { SliderGallery },
|
|
131
|
-
setup() {
|
|
132
|
-
const galleryData = ref<IGalleryData[]>(sampleSlides);
|
|
133
|
-
return { args, galleryData };
|
|
134
|
-
},
|
|
135
|
-
template: `<SliderGallery v-bind="args" v-model:gallery-data="galleryData" />`,
|
|
136
|
-
}),
|
|
268
|
+
render: renderWith(sampleSlides),
|
|
137
269
|
};
|
|
138
270
|
|
|
139
271
|
export const AutoRunDisabled: Story = {
|
|
@@ -141,14 +273,7 @@ export const AutoRunDisabled: Story = {
|
|
|
141
273
|
args: {
|
|
142
274
|
autoRun: false,
|
|
143
275
|
},
|
|
144
|
-
render: (
|
|
145
|
-
components: { SliderGallery },
|
|
146
|
-
setup() {
|
|
147
|
-
const galleryData = ref<IGalleryData[]>(sampleSlides);
|
|
148
|
-
return { args, galleryData };
|
|
149
|
-
},
|
|
150
|
-
template: `<SliderGallery v-bind="args" v-model:gallery-data="galleryData" />`,
|
|
151
|
-
}),
|
|
276
|
+
render: renderWith(sampleSlides),
|
|
152
277
|
parameters: {
|
|
153
278
|
docs: {
|
|
154
279
|
description: {
|
|
@@ -164,14 +289,7 @@ export const FastTransition: Story = {
|
|
|
164
289
|
animationDuration: 500,
|
|
165
290
|
autoRunInterval: 3000,
|
|
166
291
|
},
|
|
167
|
-
render: (
|
|
168
|
-
components: { SliderGallery },
|
|
169
|
-
setup() {
|
|
170
|
-
const galleryData = ref<IGalleryData[]>(sampleSlides);
|
|
171
|
-
return { args, galleryData };
|
|
172
|
-
},
|
|
173
|
-
template: `<SliderGallery v-bind="args" v-model:gallery-data="galleryData" />`,
|
|
174
|
-
}),
|
|
292
|
+
render: renderWith(sampleSlides),
|
|
175
293
|
};
|
|
176
294
|
|
|
177
295
|
export const SlowTransition: Story = {
|
|
@@ -180,14 +298,7 @@ export const SlowTransition: Story = {
|
|
|
180
298
|
animationDuration: 5000,
|
|
181
299
|
autoRunInterval: 10000,
|
|
182
300
|
},
|
|
183
|
-
render: (
|
|
184
|
-
components: { SliderGallery },
|
|
185
|
-
setup() {
|
|
186
|
-
const galleryData = ref<IGalleryData[]>(sampleSlides);
|
|
187
|
-
return { args, galleryData };
|
|
188
|
-
},
|
|
189
|
-
template: `<SliderGallery v-bind="args" v-model:gallery-data="galleryData" />`,
|
|
190
|
-
}),
|
|
301
|
+
render: renderWith(sampleSlides),
|
|
191
302
|
};
|
|
192
303
|
|
|
193
304
|
export const SingleSlide: Story = {
|
|
@@ -195,14 +306,7 @@ export const SingleSlide: Story = {
|
|
|
195
306
|
args: {
|
|
196
307
|
autoRun: false,
|
|
197
308
|
},
|
|
198
|
-
render: (
|
|
199
|
-
components: { SliderGallery },
|
|
200
|
-
setup() {
|
|
201
|
-
const galleryData = ref<IGalleryData[]>([sampleSlides[0]!]);
|
|
202
|
-
return { args, galleryData };
|
|
203
|
-
},
|
|
204
|
-
template: `<SliderGallery v-bind="args" v-model:gallery-data="galleryData" />`,
|
|
205
|
-
}),
|
|
309
|
+
render: renderWith([sampleSlides[0]!]),
|
|
206
310
|
parameters: {
|
|
207
311
|
docs: {
|
|
208
312
|
description: {
|
|
@@ -217,18 +321,11 @@ export const MinimalSlideData: Story = {
|
|
|
217
321
|
args: {
|
|
218
322
|
autoRun: false,
|
|
219
323
|
},
|
|
220
|
-
render: (
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
{ src: "https://picsum.photos/seed/min2/1920/1080", alt: "Image two", textBrightness: "dark" },
|
|
226
|
-
{ src: "https://picsum.photos/seed/min3/1920/1080", alt: "Image three", textBrightness: "light" },
|
|
227
|
-
]);
|
|
228
|
-
return { args, galleryData };
|
|
229
|
-
},
|
|
230
|
-
template: `<SliderGallery v-bind="args" v-model:gallery-data="galleryData" />`,
|
|
231
|
-
}),
|
|
324
|
+
render: renderWith([
|
|
325
|
+
{ src: "https://picsum.photos/seed/min1/1920/1080", alt: "Image one", textBrightness: "light" },
|
|
326
|
+
{ src: "https://picsum.photos/seed/min2/1920/1080", alt: "Image two", textBrightness: "dark" },
|
|
327
|
+
{ src: "https://picsum.photos/seed/min3/1920/1080", alt: "Image three", textBrightness: "light" },
|
|
328
|
+
]),
|
|
232
329
|
parameters: {
|
|
233
330
|
docs: {
|
|
234
331
|
description: {
|
|
@@ -240,14 +337,7 @@ export const MinimalSlideData: Story = {
|
|
|
240
337
|
|
|
241
338
|
export const EmptyGallery: Story = {
|
|
242
339
|
name: "Empty Gallery",
|
|
243
|
-
render: (
|
|
244
|
-
components: { SliderGallery },
|
|
245
|
-
setup() {
|
|
246
|
-
const galleryData = ref<IGalleryData[]>([]);
|
|
247
|
-
return { args, galleryData };
|
|
248
|
-
},
|
|
249
|
-
template: `<SliderGallery v-bind="args" v-model:gallery-data="galleryData" />`,
|
|
250
|
-
}),
|
|
340
|
+
render: renderWith([]),
|
|
251
341
|
parameters: {
|
|
252
342
|
docs: {
|
|
253
343
|
description: {
|
|
@@ -256,3 +346,51 @@ export const EmptyGallery: Story = {
|
|
|
256
346
|
},
|
|
257
347
|
},
|
|
258
348
|
};
|
|
349
|
+
|
|
350
|
+
export const StressTest: Story = {
|
|
351
|
+
name: "Stress Test (Worst-Case Data)",
|
|
352
|
+
args: {
|
|
353
|
+
autoRunInterval: 0,
|
|
354
|
+
loadingText: "Die Galerie wird geladen, bitte haben Sie einen Augenblick Geduld...",
|
|
355
|
+
seeMoreText: "WEITERE INFORMATIONEN ZU DIESEM BEITRAG ANZEIGEN",
|
|
356
|
+
ariaLabel: "",
|
|
357
|
+
},
|
|
358
|
+
render: renderWith(stressSlides),
|
|
359
|
+
decorators: [
|
|
360
|
+
(story, context) => ({
|
|
361
|
+
components: { story, CanvasSwitcher },
|
|
362
|
+
setup() {
|
|
363
|
+
const canvasName = ref<MediaCanvas>(context.parameters.initialCanvas ?? "fullWidthCanvas");
|
|
364
|
+
return { canvasName };
|
|
365
|
+
},
|
|
366
|
+
template: `
|
|
367
|
+
<div style="padding: 1.2rem 1.6rem; border-block-end: 1px solid currentColor;">
|
|
368
|
+
<CanvasSwitcher v-model:canvas-name="canvasName" />
|
|
369
|
+
</div>
|
|
370
|
+
<div
|
|
371
|
+
:class="canvasName"
|
|
372
|
+
style="position: relative; block-size: 80svh; margin-inline: auto; outline: 1px dashed currentColor; --slider-gallery-width: 100%; --slider-gallery-height: 100%;"
|
|
373
|
+
>
|
|
374
|
+
<story />
|
|
375
|
+
</div>
|
|
376
|
+
`,
|
|
377
|
+
}),
|
|
378
|
+
],
|
|
379
|
+
parameters: {
|
|
380
|
+
initialCanvas: "mobileCanvas",
|
|
381
|
+
docs: {
|
|
382
|
+
description: {
|
|
383
|
+
story:
|
|
384
|
+
"Deliberately hostile data to find breakage, sized to the canvas with `--slider-gallery-width: 100%` and " +
|
|
385
|
+
"`--slider-gallery-height: 100%`: long German copy and unbroken strings (a 100-character compound word, a long URL) " +
|
|
386
|
+
"in every field including the see-more and loading copy, emoji (including first), HTML-like text (must render as text), " +
|
|
387
|
+
"right-to-left Arabic, a broken image URL (its alt text shows), single characters, empty strings (no empty elements or " +
|
|
388
|
+
"empty link are rendered), a slide with an empty alt and no text, an empty carousel label, and 30 slides. " +
|
|
389
|
+
"`autoRunInterval` is 0: auto-advance is floored to the transition length (minimum 1s), so it keeps cycling rather than " +
|
|
390
|
+
"stalling; try a negative `animationDuration` too. Hover the gallery to pause it while you look. " +
|
|
391
|
+
"Check at every canvas width: no text runs off the slide, thumbnail text stays inside its card (2 lines each by default), " +
|
|
392
|
+
"and the arrows stay usable. Try the line clamp controls too: they set CSS tokens, they are not props.",
|
|
393
|
+
},
|
|
394
|
+
},
|
|
395
|
+
},
|
|
396
|
+
};
|
package/app/components/03.organisms/image-galleries/slider-gallery/tests/SliderGallery.spec.ts
CHANGED
|
@@ -43,9 +43,13 @@ type MockImageInstance = {
|
|
|
43
43
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
44
44
|
|
|
45
45
|
/** Mount the gallery and simulate the first image loading successfully. */
|
|
46
|
-
async function mountAndLoad(
|
|
46
|
+
async function mountAndLoad(
|
|
47
|
+
galleryData: IGalleryData[],
|
|
48
|
+
mockImage: MockImageInstance,
|
|
49
|
+
props: Record<string, unknown> = {}
|
|
50
|
+
) {
|
|
47
51
|
const wrapper = await mountSuspended(SliderGallery, {
|
|
48
|
-
props: { galleryData },
|
|
52
|
+
props: { galleryData, ...props },
|
|
49
53
|
});
|
|
50
54
|
mockImage.onload?.();
|
|
51
55
|
await nextTick(); // let onMounted resume after Promise.race resolves
|
|
@@ -310,4 +314,39 @@ describe("SliderGallery", () => {
|
|
|
310
314
|
await nextTick();
|
|
311
315
|
expect(wrapper.classes()).not.toContain("is-next");
|
|
312
316
|
});
|
|
317
|
+
|
|
318
|
+
// ─── Worst-case numbers ─────────────────────────────────────────────────
|
|
319
|
+
|
|
320
|
+
const activeAlt = (wrapper: Awaited<ReturnType<typeof mountAndLoad>>) =>
|
|
321
|
+
wrapper.find(".slider-gallery-list .slider-gallery-item img").attributes("alt");
|
|
322
|
+
|
|
323
|
+
// Mount with motion allowed, then let the load chain settle so the first auto-run timer is queued.
|
|
324
|
+
async function mountForAutoRun(props: Record<string, unknown>) {
|
|
325
|
+
vi.stubGlobal("matchMedia", vi.fn(() => ({ matches: false })));
|
|
326
|
+
const wrapper = await mountAndLoad(mockGalleryData, mockImage, props);
|
|
327
|
+
vi.advanceTimersByTime(1000);
|
|
328
|
+
await nextTick();
|
|
329
|
+
return wrapper;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
it("keeps auto-advancing when autoRunInterval is shorter than the transition", async () => {
|
|
333
|
+
const wrapper = await mountForAutoRun({ autoRunInterval: 0, animationDuration: 3000 });
|
|
334
|
+
expect(activeAlt(wrapper)).toBe("Slide 1");
|
|
335
|
+
vi.advanceTimersByTime(3000);
|
|
336
|
+
await nextTick();
|
|
337
|
+
expect(activeAlt(wrapper)).toBe("Slide 2");
|
|
338
|
+
vi.advanceTimersByTime(3000);
|
|
339
|
+
await nextTick();
|
|
340
|
+
expect(activeAlt(wrapper)).toBe("Slide 3");
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
it("floors auto-advance at 1s when both timings are zero or negative", async () => {
|
|
344
|
+
const wrapper = await mountForAutoRun({ autoRunInterval: 0, animationDuration: -500 });
|
|
345
|
+
vi.advanceTimersByTime(999);
|
|
346
|
+
await nextTick();
|
|
347
|
+
expect(activeAlt(wrapper)).toBe("Slide 1");
|
|
348
|
+
vi.advanceTimersByTime(1);
|
|
349
|
+
await nextTick();
|
|
350
|
+
expect(activeAlt(wrapper)).toBe("Slide 2");
|
|
351
|
+
});
|
|
313
352
|
});
|
|
@@ -8,7 +8,7 @@ exports[`SliderGallery > renders correct HTML structure after load 1`] = `
|
|
|
8
8
|
</div>
|
|
9
9
|
<div class="slider-gallery-content">
|
|
10
10
|
<div class="slider-gallery-list">
|
|
11
|
-
<div class="slider-gallery-item" data-text-brightness="light" data-has-text=""><img data-nuxt-img="" srcset="/_ipx/
|
|
11
|
+
<div class="slider-gallery-item" data-text-brightness="light" data-has-text=""><img width="1920" height="1080" data-nuxt-img="" srcset="/_ipx/s_1920x1080/images/slide-1.jpg 1x, /_ipx/s_3840x2160/images/slide-1.jpg 2x" alt="Slide 1" src="/_ipx/s_1920x1080/images/slide-1.jpg">
|
|
12
12
|
<div class="slider-gallery-item-content light">
|
|
13
13
|
<div class="slider-gallery-author">Stylist One</div>
|
|
14
14
|
<div class="slider-gallery-title">First Slide</div>
|
|
@@ -17,7 +17,7 @@ exports[`SliderGallery > renders correct HTML structure after load 1`] = `
|
|
|
17
17
|
<!--v-if-->
|
|
18
18
|
</div>
|
|
19
19
|
</div>
|
|
20
|
-
<div class="slider-gallery-item" data-text-brightness="dark" data-has-text=""><img data-nuxt-img="" srcset="/_ipx/
|
|
20
|
+
<div class="slider-gallery-item" data-text-brightness="dark" data-has-text=""><img width="1920" height="1080" data-nuxt-img="" srcset="/_ipx/s_1920x1080/images/slide-2.jpg 1x, /_ipx/s_3840x2160/images/slide-2.jpg 2x" alt="Slide 2" src="/_ipx/s_1920x1080/images/slide-2.jpg">
|
|
21
21
|
<div class="slider-gallery-item-content dark">
|
|
22
22
|
<!--v-if-->
|
|
23
23
|
<div class="slider-gallery-title">Second Slide</div>
|
|
@@ -26,7 +26,7 @@ exports[`SliderGallery > renders correct HTML structure after load 1`] = `
|
|
|
26
26
|
<!--v-if-->
|
|
27
27
|
</div>
|
|
28
28
|
</div>
|
|
29
|
-
<div class="slider-gallery-item" data-text-brightness="light"><img data-nuxt-img="" srcset="/_ipx/
|
|
29
|
+
<div class="slider-gallery-item" data-text-brightness="light"><img width="1920" height="1080" data-nuxt-img="" srcset="/_ipx/s_1920x1080/images/slide-3.jpg 1x, /_ipx/s_3840x2160/images/slide-3.jpg 2x" alt="Slide 3" src="/_ipx/s_1920x1080/images/slide-3.jpg">
|
|
30
30
|
<div class="slider-gallery-item-content light">
|
|
31
31
|
<!--v-if-->
|
|
32
32
|
<!--v-if-->
|
|
@@ -38,7 +38,7 @@ exports[`SliderGallery > renders correct HTML structure after load 1`] = `
|
|
|
38
38
|
</div>
|
|
39
39
|
<div class="slider-gallery-thumbnails" aria-hidden="true">
|
|
40
40
|
<div class="slider-gallery-item">
|
|
41
|
-
<div class="slider-gallery-thumbnail-overlay"><img data-nuxt-img="" srcset="/_ipx/
|
|
41
|
+
<div class="slider-gallery-thumbnail-overlay"><img width="640" height="940" data-nuxt-img="" srcset="/_ipx/s_640x940/images/slide-1.jpg 1x, /_ipx/s_1280x1880/images/slide-1.jpg 2x" alt="" loading="lazy" src="/_ipx/s_640x940/images/slide-1.jpg">
|
|
42
42
|
<div class="slider-gallery-item-content light">
|
|
43
43
|
<div class="slider-gallery-title">Thumb 1</div>
|
|
44
44
|
<div class="slider-gallery-description">Thumb desc 1</div>
|
|
@@ -46,7 +46,7 @@ exports[`SliderGallery > renders correct HTML structure after load 1`] = `
|
|
|
46
46
|
</div>
|
|
47
47
|
</div>
|
|
48
48
|
<div class="slider-gallery-item">
|
|
49
|
-
<div class="slider-gallery-thumbnail-overlay"><img data-nuxt-img="" srcset="/_ipx/
|
|
49
|
+
<div class="slider-gallery-thumbnail-overlay"><img width="640" height="940" data-nuxt-img="" srcset="/_ipx/s_640x940/images/slide-2.jpg 1x, /_ipx/s_1280x1880/images/slide-2.jpg 2x" alt="" loading="lazy" src="/_ipx/s_640x940/images/slide-2.jpg">
|
|
50
50
|
<div class="slider-gallery-item-content dark">
|
|
51
51
|
<div class="slider-gallery-title">Thumb 2</div>
|
|
52
52
|
<div class="slider-gallery-description">Thumb desc 2</div>
|
|
@@ -54,7 +54,7 @@ exports[`SliderGallery > renders correct HTML structure after load 1`] = `
|
|
|
54
54
|
</div>
|
|
55
55
|
</div>
|
|
56
56
|
<div class="slider-gallery-item">
|
|
57
|
-
<div class="slider-gallery-thumbnail-overlay"><img data-nuxt-img="" srcset="/_ipx/
|
|
57
|
+
<div class="slider-gallery-thumbnail-overlay"><img width="640" height="940" data-nuxt-img="" srcset="/_ipx/s_640x940/images/slide-3.jpg 1x, /_ipx/s_1280x1880/images/slide-3.jpg 2x" alt="" loading="lazy" src="/_ipx/s_640x940/images/slide-3.jpg">
|
|
58
58
|
<div class="slider-gallery-item-content light">
|
|
59
59
|
<!--v-if-->
|
|
60
60
|
<!--v-if-->
|