@eox/pages-theme-eox 1.8.0 → 2.0.0-alpha.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/CHANGELOG.md +6 -0
- package/README.md +83 -0
- package/cypress/support/mocks/vitepress.js +8 -1
- package/cypress.config.js +5 -0
- package/package.json +1 -1
- package/src/Layout.vue +58 -1
- package/src/authors.data.js +14 -0
- package/src/components/BlogList.vue +636 -0
- package/src/components/BlogPost.vue +450 -0
- package/src/components/FeatureCard/Index.vue +370 -26
- package/src/components/HeroSection.vue +1 -1
- package/src/components/ImageCarousel.cy.js +22 -0
- package/src/components/ImageCarousel.vue +268 -0
- package/src/components/ImageElement.cy.js +46 -0
- package/src/components/ImageElement.vue +269 -0
- package/src/components/ImageGallery.cy.js +52 -0
- package/src/components/ImageGallery.vue +622 -0
- package/src/components/SectionHeader.cy.js +54 -0
- package/src/components/SectionHeader.vue +115 -0
- package/src/components/SingleTweet.cy.js +27 -0
- package/src/components/SingleTweet.vue +155 -0
- package/src/components/TagList.vue +293 -0
- package/src/components/TeamPage.vue +333 -0
- package/src/components/TestimonialsSection.cy.js +79 -0
- package/src/components/TestimonialsSection.vue +265 -0
- package/src/index.js +21 -0
- package/src/pages/author/[author].md +4 -0
- package/src/pages/author/[author].paths.js +60 -0
- package/src/pages/blog.md +4 -0
- package/src/pages/tag/[tag].md +4 -0
- package/src/pages/tag/[tag].paths.js +49 -0
- package/src/pages/tag.md +4 -0
- package/src/pages/team.md +4 -0
- package/src/posts.data.js +96 -0
- package/src/style.css +160 -0
- package/src/tagUtils.js +148 -0
- package/src/team.data.js +51 -0
- package/src/vitepressConfig.mjs +97 -0
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
|
|
2
|
+
import { computed } from "vue";
|
|
3
|
+
import { data as authorsList } from "../../authors.data.js";
|
|
4
|
+
import { getTagColor } from "../../tagUtils.js";
|
|
5
|
+
|
|
6
|
+
const props = defineProps({
|
|
3
7
|
title: String,
|
|
4
8
|
content: String,
|
|
5
9
|
image: {
|
|
@@ -7,7 +11,7 @@ const { title, content, link, secondaryLink, icon } = defineProps({
|
|
|
7
11
|
required: false,
|
|
8
12
|
},
|
|
9
13
|
chips: {
|
|
10
|
-
/** @type {import('vue').PropType<{ text: string; class?: string }[]>} */
|
|
14
|
+
/** @type {import('vue').PropType<{ text: string; link?: string; href?: string; class?: string }[]>} */
|
|
11
15
|
type: Array,
|
|
12
16
|
required: false,
|
|
13
17
|
default: () => [],
|
|
@@ -33,18 +37,104 @@ const { title, content, link, secondaryLink, icon } = defineProps({
|
|
|
33
37
|
type: Object,
|
|
34
38
|
required: false,
|
|
35
39
|
},
|
|
40
|
+
date: {
|
|
41
|
+
type: String,
|
|
42
|
+
required: false,
|
|
43
|
+
},
|
|
44
|
+
authors: {
|
|
45
|
+
type: Array,
|
|
46
|
+
required: false,
|
|
47
|
+
default: () => [],
|
|
48
|
+
},
|
|
49
|
+
variant: {
|
|
50
|
+
type: String,
|
|
51
|
+
required: false,
|
|
52
|
+
default: "default",
|
|
53
|
+
},
|
|
36
54
|
});
|
|
55
|
+
|
|
37
56
|
const iconStyle = {
|
|
38
|
-
width: (icon?.width ?? 40) + "px",
|
|
39
|
-
height: (icon?.height ?? 40) + "px",
|
|
57
|
+
width: (props.icon?.width ?? 40) + "px",
|
|
58
|
+
height: (props.icon?.height ?? 40) + "px",
|
|
40
59
|
};
|
|
60
|
+
|
|
61
|
+
// Check if we should render a full-width cover image
|
|
62
|
+
const isCoverLayout = computed(() => {
|
|
63
|
+
return props.image && (props.variant === "cover" || props.date || props.authors.length);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Check if the card itself is fully clickable (has a link but NO link text)
|
|
67
|
+
const isClickableCard = computed(() => {
|
|
68
|
+
return props.link && !props.link.text;
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
function getAuthorName(authorId) {
|
|
72
|
+
if (!authorId) return "EOX Experts";
|
|
73
|
+
const author = authorsList.find(
|
|
74
|
+
(a) => a.id.toLowerCase().trim() === authorId.toLowerCase().trim()
|
|
75
|
+
);
|
|
76
|
+
return author ? author.name : authorId;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function getTagStyle(tag) {
|
|
80
|
+
const color = getTagColor(tag);
|
|
81
|
+
if (color.startsWith("rgb(255, 94, 94)")) {
|
|
82
|
+
return {
|
|
83
|
+
backgroundColor: "rgba(255, 94, 94, 0.15)",
|
|
84
|
+
border: "1px solid rgb(255, 94, 94)",
|
|
85
|
+
color: "#d32f2f"
|
|
86
|
+
};
|
|
87
|
+
} else if (color.startsWith("rgb(0, 177, 176)")) {
|
|
88
|
+
return {
|
|
89
|
+
backgroundColor: "rgba(0, 177, 176, 0.15)",
|
|
90
|
+
border: "1px solid rgb(0, 177, 176)",
|
|
91
|
+
color: "#00796b"
|
|
92
|
+
};
|
|
93
|
+
} else if (color.startsWith("rgb(219, 173, 66)")) {
|
|
94
|
+
return {
|
|
95
|
+
backgroundColor: "rgba(219, 173, 66, 0.15)",
|
|
96
|
+
border: "1px solid rgb(219, 173, 66)",
|
|
97
|
+
color: "#f57c00"
|
|
98
|
+
};
|
|
99
|
+
} else if (color.startsWith("rgb(218, 71, 228)")) {
|
|
100
|
+
return {
|
|
101
|
+
backgroundColor: "rgba(218, 71, 228, 0.15)",
|
|
102
|
+
border: "1px solid rgb(218, 71, 228)",
|
|
103
|
+
color: "#c2185b"
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
backgroundColor: "rgba(0, 0, 0, 0.05)",
|
|
108
|
+
border: "1px solid rgba(0, 0, 0, 0.1)",
|
|
109
|
+
color: "#475569"
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function formatDate(dateString) {
|
|
114
|
+
if (!dateString) return "";
|
|
115
|
+
const date = new Date(dateString);
|
|
116
|
+
return date.toLocaleDateString("en-US", {
|
|
117
|
+
year: "numeric",
|
|
118
|
+
month: "short",
|
|
119
|
+
day: "numeric",
|
|
120
|
+
});
|
|
121
|
+
}
|
|
41
122
|
</script>
|
|
123
|
+
|
|
42
124
|
<template>
|
|
43
125
|
<article
|
|
44
|
-
class="vertical large-padding no-margin"
|
|
45
|
-
:class="
|
|
126
|
+
class="vertical large-padding no-margin theme-feature-card"
|
|
127
|
+
:class="[
|
|
128
|
+
isClickableCard ? 'small-elevate clickable-card' : 'no-elevate',
|
|
129
|
+
isCoverLayout ? 'has-cover-image' : ''
|
|
130
|
+
]"
|
|
46
131
|
>
|
|
47
|
-
|
|
132
|
+
<!-- Cover Image for cover/blog/rich cards -->
|
|
133
|
+
<a v-if="isCoverLayout" :href="link?.href" class="card-cover-link">
|
|
134
|
+
<img :src="image" alt="" class="card-cover-image" loading="lazy" />
|
|
135
|
+
</a>
|
|
136
|
+
|
|
137
|
+
<div class="card-content-wrapper">
|
|
48
138
|
<i
|
|
49
139
|
v-if="typeof icon === 'string' && icon.startsWith('mdi-')"
|
|
50
140
|
:class="`mdi ${icon}`"
|
|
@@ -55,23 +145,73 @@ const iconStyle = {
|
|
|
55
145
|
v-html="icon.html"
|
|
56
146
|
class="icon"
|
|
57
147
|
></div>
|
|
58
|
-
|
|
59
|
-
<
|
|
148
|
+
<!-- Render small icon image only if NOT rendering a full cover image -->
|
|
149
|
+
<img v-else-if="image && !isCoverLayout" :src="image" alt="" class="icon" />
|
|
150
|
+
|
|
151
|
+
<!-- Metadata & Tags directly under place/author -->
|
|
152
|
+
<div v-if="date || (authors && authors.length)" class="metadata-wrapper">
|
|
153
|
+
<div class="blog-metadata">
|
|
154
|
+
<span v-if="date" class="date-span">
|
|
155
|
+
<i class="mdi mdi-clock-outline"></i>
|
|
156
|
+
<time :datetime="date">{{ formatDate(date) }}</time>
|
|
157
|
+
</span>
|
|
158
|
+
<span v-if="authors && authors.length" class="author-span">
|
|
159
|
+
<span class="author-icon">
|
|
160
|
+
<i class="mdi mdi-account-outline"></i>
|
|
161
|
+
</span>
|
|
162
|
+
<span v-for="(authorId, idx) in authors" :key="authorId" class="author-item">
|
|
163
|
+
<a :href="`/author/${authorId}/`" class="author-link">{{ getAuthorName(authorId) }}</a><span v-if="idx < authors.length - 1" class="author-separator">,</span>
|
|
164
|
+
</span>
|
|
165
|
+
</span>
|
|
166
|
+
</div>
|
|
167
|
+
|
|
168
|
+
<!-- Tags directly under metadata if chips are provided and this is a rich card -->
|
|
169
|
+
<div v-if="chips && chips.length" class="blog-tags-container">
|
|
170
|
+
<a
|
|
171
|
+
v-for="chip in chips"
|
|
172
|
+
:key="chip.text"
|
|
173
|
+
:href="chip.link || chip.href || `/tag/${chip.text}/`"
|
|
174
|
+
:style="getTagStyle(chip.text)"
|
|
175
|
+
class="tag-link"
|
|
176
|
+
>
|
|
177
|
+
{{ chip.text }}
|
|
178
|
+
</a>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
|
|
182
|
+
<h5 class="small card-title-text">
|
|
183
|
+
<a v-if="link?.href" :href="link.href">{{ title }}</a>
|
|
184
|
+
<span v-else>{{ title }}</span>
|
|
185
|
+
</h5>
|
|
186
|
+
|
|
187
|
+
<!-- Standard chips (rendered only for normal cards) -->
|
|
60
188
|
<div
|
|
61
|
-
v-if="chips && chips.length"
|
|
189
|
+
v-if="chips && chips.length && !date && !authors.length"
|
|
62
190
|
class="row wrap"
|
|
63
191
|
style="gap: 0.5rem; margin-bottom: 0.5rem"
|
|
64
192
|
>
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
193
|
+
<template v-for="chip in chips" :key="chip.text">
|
|
194
|
+
<a
|
|
195
|
+
v-if="chip.link || chip.href"
|
|
196
|
+
:href="chip.link || chip.href"
|
|
197
|
+
:style="getTagStyle(chip.text)"
|
|
198
|
+
class="chip small-chip border clickable-chip"
|
|
199
|
+
:class="chip.class"
|
|
200
|
+
>
|
|
201
|
+
{{ chip.text }}
|
|
202
|
+
</a>
|
|
203
|
+
<span
|
|
204
|
+
v-else
|
|
205
|
+
:style="getTagStyle(chip.text)"
|
|
206
|
+
class="chip small-chip border clickable-chip"
|
|
207
|
+
:class="chip.class"
|
|
208
|
+
>
|
|
209
|
+
{{ chip.text }}
|
|
210
|
+
</span>
|
|
211
|
+
</template>
|
|
73
212
|
</div>
|
|
74
|
-
|
|
213
|
+
|
|
214
|
+
<p v-if="metadata && metadata.length && !date && !authors.length" class="small-text">
|
|
75
215
|
<span
|
|
76
216
|
v-for="(item, index) in metadata"
|
|
77
217
|
:key="index"
|
|
@@ -87,14 +227,15 @@ const iconStyle = {
|
|
|
87
227
|
</span>
|
|
88
228
|
</p>
|
|
89
229
|
|
|
90
|
-
<p v-if="$slots.default">
|
|
230
|
+
<p v-if="$slots.default" class="card-body-text">
|
|
91
231
|
<slot>{{ content }}</slot>
|
|
92
232
|
</p>
|
|
93
|
-
<div v-else v-html="content"></div>
|
|
233
|
+
<div v-else-if="content" v-html="content" class="card-body-text"></div>
|
|
94
234
|
</div>
|
|
235
|
+
|
|
95
236
|
<nav
|
|
96
237
|
v-if="link || secondaryLink"
|
|
97
|
-
class="row wrap align-center"
|
|
238
|
+
class="row wrap align-center card-navigation"
|
|
98
239
|
style="gap: 1.5rem; margin-right: auto; position: relative; z-index: 11"
|
|
99
240
|
>
|
|
100
241
|
<a
|
|
@@ -121,6 +262,7 @@ const iconStyle = {
|
|
|
121
262
|
</nav>
|
|
122
263
|
</article>
|
|
123
264
|
</template>
|
|
265
|
+
|
|
124
266
|
<style scoped>
|
|
125
267
|
/**
|
|
126
268
|
* Undo Vitepress missing with @eox/ui styles
|
|
@@ -142,17 +284,33 @@ const iconStyle = {
|
|
|
142
284
|
/**
|
|
143
285
|
* Custom styles
|
|
144
286
|
*/
|
|
145
|
-
|
|
287
|
+
.theme-feature-card {
|
|
146
288
|
justify-content: space-between;
|
|
147
|
-
transition: all 0.3s ease-in-out;
|
|
148
289
|
width: 100%;
|
|
290
|
+
border-radius: 16px !important;
|
|
291
|
+
overflow: hidden !important;
|
|
292
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05) !important;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/* Clickable Cards Hover System */
|
|
296
|
+
.theme-feature-card.clickable-card {
|
|
297
|
+
cursor: pointer;
|
|
298
|
+
transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1), box-shadow 0.3s cubic-bezier(0.25, 0.8, 0.25, 1) !important;
|
|
299
|
+
will-change: transform, box-shadow;
|
|
149
300
|
}
|
|
301
|
+
|
|
302
|
+
.theme-feature-card.clickable-card:hover {
|
|
303
|
+
transform: translateY(-4px) !important;
|
|
304
|
+
box-shadow: 0 12px 28px rgba(0, 0, 0, 0.12), 0 4px 8px rgba(0, 0, 0, 0.04) !important;
|
|
305
|
+
}
|
|
306
|
+
|
|
150
307
|
.small-chip {
|
|
151
308
|
font-size: 0.75rem;
|
|
152
|
-
padding:
|
|
309
|
+
padding: 4px 10px !important;
|
|
153
310
|
height: auto;
|
|
154
|
-
line-height:
|
|
311
|
+
line-height: 1.2 !important;
|
|
155
312
|
margin: 0;
|
|
313
|
+
border-radius: 6px !important;
|
|
156
314
|
}
|
|
157
315
|
.arrow {
|
|
158
316
|
transition: transform 0.2s;
|
|
@@ -163,4 +321,190 @@ article {
|
|
|
163
321
|
.button.transparent:hover:after {
|
|
164
322
|
background: none;
|
|
165
323
|
}
|
|
324
|
+
|
|
325
|
+
/* Card with Cover Image Layout */
|
|
326
|
+
.theme-feature-card.has-cover-image {
|
|
327
|
+
padding: 0 !important;
|
|
328
|
+
display: flex;
|
|
329
|
+
flex-direction: column;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.theme-feature-card.has-cover-image .card-cover-link {
|
|
333
|
+
display: block;
|
|
334
|
+
width: 100%;
|
|
335
|
+
aspect-ratio: 16 / 9;
|
|
336
|
+
overflow: hidden;
|
|
337
|
+
position: relative;
|
|
338
|
+
flex-shrink: 0;
|
|
339
|
+
border-top-left-radius: 16px !important;
|
|
340
|
+
border-top-right-radius: 16px !important;
|
|
341
|
+
border-bottom-left-radius: 0 !important;
|
|
342
|
+
border-bottom-right-radius: 0 !important;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
.theme-feature-card.has-cover-image .card-cover-image {
|
|
346
|
+
width: 100%;
|
|
347
|
+
height: 100%;
|
|
348
|
+
object-fit: cover;
|
|
349
|
+
transition: transform 0.3s ease;
|
|
350
|
+
border-top-left-radius: 16px !important;
|
|
351
|
+
border-top-right-radius: 16px !important;
|
|
352
|
+
border-bottom-left-radius: 0 !important;
|
|
353
|
+
border-bottom-right-radius: 0 !important;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/* Zoom Image on Hover ONLY if the card itself is clickable */
|
|
357
|
+
.theme-feature-card.has-cover-image.clickable-card .card-cover-image {
|
|
358
|
+
transition: transform 0.5s cubic-bezier(0.25, 0.8, 0.25, 1) !important;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
.theme-feature-card.has-cover-image.clickable-card:hover .card-cover-image {
|
|
362
|
+
transform: scale(1.04) !important;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
.theme-feature-card.has-cover-image .card-content-wrapper {
|
|
366
|
+
padding: 1.5rem;
|
|
367
|
+
display: flex;
|
|
368
|
+
flex-direction: column;
|
|
369
|
+
flex-grow: 1;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.theme-feature-card.has-cover-image .card-navigation {
|
|
373
|
+
padding: 0 1.5rem 1.5rem 1.5rem;
|
|
374
|
+
margin-top: auto;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/* Metadata Styling */
|
|
378
|
+
.metadata-wrapper {
|
|
379
|
+
margin-bottom: 16px;
|
|
380
|
+
text-align: left;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.blog-metadata {
|
|
384
|
+
display: block !important;
|
|
385
|
+
font-size: 12px !important;
|
|
386
|
+
color: #64748b !important;
|
|
387
|
+
line-height: 1.6 !important;
|
|
388
|
+
margin-bottom: 8px;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.date-span {
|
|
392
|
+
display: inline-flex;
|
|
393
|
+
align-items: center;
|
|
394
|
+
gap: 4px;
|
|
395
|
+
white-space: nowrap !important;
|
|
396
|
+
margin-right: 12px;
|
|
397
|
+
vertical-align: middle;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
.date-span i {
|
|
401
|
+
font-size: 13px !important;
|
|
402
|
+
color: #64748b !important;
|
|
403
|
+
vertical-align: middle;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
.author-span {
|
|
407
|
+
display: inline;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.author-icon {
|
|
411
|
+
display: inline-flex;
|
|
412
|
+
align-items: center;
|
|
413
|
+
margin-right: 4px;
|
|
414
|
+
vertical-align: middle;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
.author-icon i {
|
|
418
|
+
font-size: 13px !important;
|
|
419
|
+
color: #64748b !important;
|
|
420
|
+
vertical-align: middle;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.author-item {
|
|
424
|
+
display: inline;
|
|
425
|
+
white-space: nowrap !important;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
.author-link {
|
|
429
|
+
color: #64748b !important;
|
|
430
|
+
text-decoration: none !important;
|
|
431
|
+
font-size: 12px !important;
|
|
432
|
+
font-weight: 600;
|
|
433
|
+
transition: color 0.15s ease;
|
|
434
|
+
vertical-align: middle;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
.author-link:hover {
|
|
438
|
+
color: var(--vp-c-brand) !important;
|
|
439
|
+
text-decoration: underline !important;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
.author-separator {
|
|
443
|
+
color: #64748b !important;
|
|
444
|
+
font-size: 12px !important;
|
|
445
|
+
vertical-align: middle;
|
|
446
|
+
margin-right: 4px;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.date-span time {
|
|
450
|
+
font-size: 12px !important;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/* Tags Styling */
|
|
454
|
+
.blog-tags-container {
|
|
455
|
+
display: flex;
|
|
456
|
+
flex-wrap: wrap;
|
|
457
|
+
gap: 6px;
|
|
458
|
+
margin-top: 8px;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
.tag-link {
|
|
462
|
+
display: inline-block !important;
|
|
463
|
+
font-size: 12px !important;
|
|
464
|
+
font-weight: 700 !important;
|
|
465
|
+
padding: 4px 10px !important;
|
|
466
|
+
border-radius: 6px !important;
|
|
467
|
+
text-decoration: none !important;
|
|
468
|
+
line-height: 1.2 !important;
|
|
469
|
+
transition: opacity 0.2s ease;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.tag-link:hover {
|
|
473
|
+
opacity: 0.8 !important;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/* card title overrides to make sure it respects the 20px request */
|
|
477
|
+
.VPHome .vp-doc h5.small.card-title-text {
|
|
478
|
+
font-size: 20px !important;
|
|
479
|
+
line-height: 1.4 !important;
|
|
480
|
+
font-weight: 700 !important;
|
|
481
|
+
margin-bottom: 0.75rem !important;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
.card-title-text a {
|
|
485
|
+
color: #0f172a !important;
|
|
486
|
+
text-decoration: none !important;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
.card-title-text a:hover {
|
|
490
|
+
color: var(--vp-c-brand) !important;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
.card-body-text {
|
|
494
|
+
font-size: 0.875rem !important;
|
|
495
|
+
line-height: 1.6 !important;
|
|
496
|
+
color: #475569 !important;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/* Clickable standard chips styling */
|
|
500
|
+
.clickable-chip {
|
|
501
|
+
text-decoration: none !important;
|
|
502
|
+
color: var(--vp-c-text-2) !important;
|
|
503
|
+
transition: all 0.2s ease;
|
|
504
|
+
border-radius: 6px !important;
|
|
505
|
+
border: 1px solid transparent !important;
|
|
506
|
+
}
|
|
507
|
+
.clickable-chip:hover {
|
|
508
|
+
opacity: 0.8 !important;
|
|
509
|
+
}
|
|
166
510
|
</style>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import ImageCarousel from "./ImageCarousel.vue";
|
|
2
|
+
|
|
3
|
+
describe("<ImageCarousel />", () => {
|
|
4
|
+
const images = [
|
|
5
|
+
{ src: "/slide1.jpg", alt: "Slide 1", caption: "Caption 1" },
|
|
6
|
+
{ src: "/slide2.jpg", alt: "Slide 2", caption: "Caption 2" },
|
|
7
|
+
];
|
|
8
|
+
|
|
9
|
+
it("renders slider images, captions, and buttons", () => {
|
|
10
|
+
cy.mount(ImageCarousel, {
|
|
11
|
+
props: {
|
|
12
|
+
images,
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
cy.get("img").should("have.length", 2);
|
|
17
|
+
cy.get("img").eq(0).should("have.attr", "src", "/slide1.jpg");
|
|
18
|
+
|
|
19
|
+
// Indicators should exist
|
|
20
|
+
cy.get("button").should("have.length", 4); // 2 nav arrows + 2 indicators
|
|
21
|
+
});
|
|
22
|
+
});
|