@eox/pages-theme-eox 2.0.0-alpha.7 → 2.0.0-alpha.8
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/README.md +21 -46
- package/cypress/support/mocks/helpers.js +25 -3
- package/package.json +3 -4
- package/src/Layout.vue +6 -3
- package/src/components/BlogList.vue +38 -25
- package/src/components/CTASection.vue +1 -1
- package/src/components/FeatureCard/Index.vue +16 -1
- package/src/components/FeatureSection.vue +3 -8
- package/src/components/FeaturesGallery.vue +5 -0
- package/src/components/Footer.cy.js +40 -2
- package/src/components/Footer.vue +5 -3
- package/src/components/HeroSection.vue +103 -15
- package/src/components/LogoSection.vue +1 -0
- package/src/components/MobileNavDropdown.vue +6 -3
- package/src/components/NavBar.vue +95 -15
- package/src/components/NavDropdown.vue +5 -2
- package/src/components/TagList.vue +16 -3
- package/src/components/TeamPage.vue +13 -3
- package/src/components/TestimonialsSection.vue +119 -16
- package/src/components/Tutorial.vue +3 -2
- package/src/helpers.js +13 -5
- package/src/helpers.test.js +28 -0
- package/src/pages/author/[author].md +1 -0
- package/src/pages/blog.md +1 -0
- package/src/pages/tag/[tag].md +1 -0
- package/src/pages/tag.md +1 -0
- package/src/pages/team.md +1 -0
- package/src/style.css +19 -8
- package/src/vitepressConfig.mjs +0 -6
- package/src/llms/index.js +0 -64
- package/src/llms/llms.test.js +0 -980
- package/src/llms/storiesPlugin.js +0 -771
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<template v-for="item in items">
|
|
3
|
-
<li
|
|
3
|
+
<li
|
|
4
|
+
v-if="item.items && item.text"
|
|
5
|
+
:class="{ active: isActive(item, route.path) }"
|
|
6
|
+
>
|
|
4
7
|
<details>
|
|
5
|
-
<summary>
|
|
8
|
+
<summary :class="{ active: isActive(item, route.path) }">
|
|
6
9
|
<span class="max" :class="{ active: isActive(item, route.path) }">{{
|
|
7
10
|
t(item.text, theme.i18n)
|
|
8
11
|
}}</span>
|
|
@@ -14,7 +17,7 @@
|
|
|
14
17
|
</details>
|
|
15
18
|
</li>
|
|
16
19
|
<MobileNavDropdown v-else-if="item.items" :items="item.items" />
|
|
17
|
-
<li v-else>
|
|
20
|
+
<li v-else :class="{ active: isActive(item, route.path) }">
|
|
18
21
|
<a
|
|
19
22
|
v-if="item.link"
|
|
20
23
|
:href="withBase(item.link)"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="top-nav at-top row center-align">
|
|
2
|
+
<div class="top-nav at-top row center-align" :class="{ 'has-hero': hasHero }">
|
|
3
3
|
<nav class="large-padding no-margin center-align nav-mobile">
|
|
4
4
|
<a :href="withBase('/')">
|
|
5
5
|
<img
|
|
@@ -33,10 +33,17 @@
|
|
|
33
33
|
</button>
|
|
34
34
|
</nav>
|
|
35
35
|
<ul class="list border large-space">
|
|
36
|
-
<li
|
|
36
|
+
<li
|
|
37
|
+
v-for="item in theme.nav.filter((item) => !item.action)"
|
|
38
|
+
:class="{ active: isActive(item, route.path) }"
|
|
39
|
+
>
|
|
37
40
|
<details v-if="item.items">
|
|
38
|
-
<summary>
|
|
39
|
-
<span
|
|
41
|
+
<summary :class="{ active: isActive(item, route.path) }">
|
|
42
|
+
<span
|
|
43
|
+
class="max"
|
|
44
|
+
:class="{ active: isActive(item, route.path) }"
|
|
45
|
+
>{{ t(item.text, theme.i18n) }}</span
|
|
46
|
+
>
|
|
40
47
|
<i class="mdi mdi-chevron-down"></i>
|
|
41
48
|
</summary>
|
|
42
49
|
<ul class="list">
|
|
@@ -49,7 +56,10 @@
|
|
|
49
56
|
:href="withBase(item.link)"
|
|
50
57
|
:target="item.target"
|
|
51
58
|
:rel="item.rel"
|
|
52
|
-
:class="
|
|
59
|
+
:class="[
|
|
60
|
+
item.action ? 'button large medium-elevate cta' : '',
|
|
61
|
+
{ active: isActive(item, route.path) },
|
|
62
|
+
]"
|
|
53
63
|
>
|
|
54
64
|
<span>{{ t(item.text, theme.i18n) }}</span>
|
|
55
65
|
</a>
|
|
@@ -135,7 +145,10 @@
|
|
|
135
145
|
<div class="space"></div>
|
|
136
146
|
<nav>
|
|
137
147
|
<ul class="left-align no-margin">
|
|
138
|
-
<li
|
|
148
|
+
<li
|
|
149
|
+
v-for="item in theme.nav.filter((i) => !i.action)"
|
|
150
|
+
:class="{ active: isActive(item, route.path) }"
|
|
151
|
+
>
|
|
139
152
|
<div v-if="item.items">
|
|
140
153
|
<button
|
|
141
154
|
class="button text no-round"
|
|
@@ -229,7 +242,7 @@ import { t, trackEvent, isActive } from "../helpers";
|
|
|
229
242
|
import NavDropdown from "./NavDropdown.vue";
|
|
230
243
|
import MobileNavDropdown from "./MobileNavDropdown.vue";
|
|
231
244
|
|
|
232
|
-
const { site, theme, localeIndex } = useData();
|
|
245
|
+
const { site, theme, localeIndex, frontmatter, page } = useData();
|
|
233
246
|
const route = useRoute();
|
|
234
247
|
|
|
235
248
|
const langs = computed(() => {
|
|
@@ -271,6 +284,14 @@ const langs = computed(() => {
|
|
|
271
284
|
});
|
|
272
285
|
});
|
|
273
286
|
|
|
287
|
+
const hasHero = computed(() => {
|
|
288
|
+
return Boolean(
|
|
289
|
+
frontmatter.value.hero ||
|
|
290
|
+
frontmatter.value.layout === "home" ||
|
|
291
|
+
page.value.relativePath === "index.md",
|
|
292
|
+
);
|
|
293
|
+
});
|
|
294
|
+
|
|
274
295
|
if (!import.meta.env.SSR) {
|
|
275
296
|
const scrollListener = () => {
|
|
276
297
|
const nav = document.querySelector(".top-nav");
|
|
@@ -301,7 +322,24 @@ if (!import.meta.env.SSR) {
|
|
|
301
322
|
.top-nav.at-top {
|
|
302
323
|
box-shadow: none;
|
|
303
324
|
}
|
|
304
|
-
.
|
|
325
|
+
.top-nav.at-top .nav-desktop .button.primary,
|
|
326
|
+
.top-nav.has-hero.at-top .nav-desktop .button.primary,
|
|
327
|
+
.Layout.layout-home .top-nav.at-top .nav-desktop .button.primary {
|
|
328
|
+
background: #ffffff !important;
|
|
329
|
+
color: #000c14 !important;
|
|
330
|
+
border-radius: 9999px;
|
|
331
|
+
font-weight: 500;
|
|
332
|
+
display: inline-flex;
|
|
333
|
+
}
|
|
334
|
+
.top-nav.at-top .nav-desktop .button.primary i.mdi-arrow-right,
|
|
335
|
+
.top-nav.has-hero.at-top .nav-desktop .button.primary i.mdi-arrow-right,
|
|
336
|
+
.Layout.layout-home
|
|
337
|
+
.top-nav.at-top
|
|
338
|
+
.nav-desktop
|
|
339
|
+
.button.primary
|
|
340
|
+
i.mdi-arrow-right {
|
|
341
|
+
display: none;
|
|
342
|
+
}
|
|
305
343
|
.Layout.layout-home .top-nav.at-top .nav-desktop .button.secondary,
|
|
306
344
|
.Layout.layout-home .top-nav.at-top .nav-desktop .button.alt {
|
|
307
345
|
display: none;
|
|
@@ -317,43 +355,85 @@ if (!import.meta.env.SSR) {
|
|
|
317
355
|
padding-top: 0.5rem !important;
|
|
318
356
|
padding-bottom: 0.5rem !important;
|
|
319
357
|
}
|
|
320
|
-
.Layout.layout-home .top-nav.at-top
|
|
358
|
+
.Layout.layout-home .top-nav.at-top,
|
|
359
|
+
.top-nav.has-hero.at-top {
|
|
321
360
|
background: transparent;
|
|
322
361
|
color: #f7f8f8;
|
|
323
362
|
}
|
|
324
363
|
.Layout .top-nav nav .button {
|
|
325
364
|
color: var(--on-surface);
|
|
326
365
|
}
|
|
327
|
-
.Layout.layout-home .top-nav.at-top .nav-desktop .button
|
|
366
|
+
.Layout.layout-home .top-nav.at-top .nav-desktop .button,
|
|
367
|
+
.top-nav.has-hero.at-top .nav-desktop .button {
|
|
328
368
|
color: var(--on-surface);
|
|
329
369
|
background: var(--surface);
|
|
330
370
|
}
|
|
331
|
-
.Layout.layout-home .top-nav.at-top .nav-desktop .button.text
|
|
371
|
+
.Layout.layout-home .top-nav.at-top .nav-desktop .button.text,
|
|
372
|
+
.top-nav.has-hero.at-top .nav-desktop .button.text {
|
|
332
373
|
color: #f7f8f8;
|
|
333
374
|
background: none;
|
|
334
375
|
}
|
|
335
|
-
.Layout.layout-home
|
|
376
|
+
.Layout.layout-home
|
|
377
|
+
.top-nav.at-top
|
|
378
|
+
.nav-desktop
|
|
379
|
+
.button.text:hover:not(.active),
|
|
380
|
+
.top-nav.has-hero.at-top .nav-desktop .button.text:hover:not(.active) {
|
|
381
|
+
background: rgba(255, 255, 255, 0.1);
|
|
382
|
+
color: #ffffff;
|
|
383
|
+
}
|
|
384
|
+
.Layout.layout-home .top-nav.at-top .nav-desktop .button.text.active,
|
|
385
|
+
.top-nav.has-hero.at-top .nav-desktop .button.text.active {
|
|
386
|
+
background-color: var(--primary-container) !important;
|
|
387
|
+
color: var(--on-primary-container) !important;
|
|
388
|
+
}
|
|
389
|
+
.Layout.layout-home .top-nav.at-top .nav-desktop .button.border,
|
|
390
|
+
.top-nav.has-hero.at-top .nav-desktop .button.border {
|
|
336
391
|
color: #f7f8f8;
|
|
337
392
|
border-color: #f7f8f855;
|
|
338
393
|
background: none;
|
|
339
394
|
}
|
|
395
|
+
.Layout.layout-home .top-nav.at-top .nav-desktop .button.border.active,
|
|
396
|
+
.top-nav.has-hero.at-top .nav-desktop .button.border.active {
|
|
397
|
+
background-color: var(--primary-container) !important;
|
|
398
|
+
color: var(--on-primary-container) !important;
|
|
399
|
+
border-color: transparent !important;
|
|
400
|
+
}
|
|
401
|
+
.nav-desktop menu > li.active,
|
|
402
|
+
.nav-desktop menu > li:has(> a.active) {
|
|
403
|
+
background-color: var(--primary-container) !important;
|
|
404
|
+
color: var(--on-primary-container) !important;
|
|
405
|
+
}
|
|
406
|
+
.nav-desktop menu > li.active > a,
|
|
407
|
+
.nav-desktop menu > li:has(> a.active) > a {
|
|
408
|
+
color: var(--on-primary-container) !important;
|
|
409
|
+
}
|
|
410
|
+
#mobile-menu .list li.active > a,
|
|
411
|
+
#mobile-menu .list li.active > span,
|
|
412
|
+
#mobile-menu .list summary:has(.active),
|
|
413
|
+
#mobile-menu .list summary.active {
|
|
414
|
+
color: var(--primary) !important;
|
|
415
|
+
font-weight: 600;
|
|
416
|
+
}
|
|
340
417
|
.top-nav.at-top > nav > a:has(.logo.dark) > .logo.dark {
|
|
341
418
|
display: none;
|
|
342
419
|
}
|
|
343
|
-
.Layout.layout-home .top-nav.at-top > nav > a:has(.logo.dark) > .logo.light
|
|
420
|
+
.Layout.layout-home .top-nav.at-top > nav > a:has(.logo.dark) > .logo.light,
|
|
421
|
+
.top-nav.has-hero.at-top > nav > a:has(.logo.dark) > .logo.light {
|
|
344
422
|
display: none;
|
|
345
423
|
}
|
|
346
424
|
.Layout.layout-home
|
|
347
425
|
.top-nav.at-top
|
|
348
426
|
> nav
|
|
349
427
|
> a:not(:has(.logo.dark))
|
|
350
|
-
> .logo.light
|
|
428
|
+
> .logo.light,
|
|
429
|
+
.top-nav.has-hero.at-top > nav > a:not(:has(.logo.dark)) > .logo.light {
|
|
351
430
|
filter: brightness(0) invert(1);
|
|
352
431
|
}
|
|
353
432
|
.Layout .top-nav > nav > a > .logo.dark {
|
|
354
433
|
display: none;
|
|
355
434
|
}
|
|
356
|
-
.Layout.layout-home .top-nav.at-top > nav > a > .logo.dark
|
|
435
|
+
.Layout.layout-home .top-nav.at-top > nav > a > .logo.dark,
|
|
436
|
+
.top-nav.has-hero.at-top > nav > a > .logo.dark {
|
|
357
437
|
display: block;
|
|
358
438
|
}
|
|
359
439
|
img.logo {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<template v-for="item in items">
|
|
3
|
-
<li
|
|
3
|
+
<li
|
|
4
|
+
v-if="item.items && item.text"
|
|
5
|
+
:class="{ active: isActive(item, route.path) }"
|
|
6
|
+
>
|
|
4
7
|
<a
|
|
5
8
|
v-if="item.link"
|
|
6
9
|
:href="withBase(item.link)"
|
|
@@ -25,7 +28,7 @@
|
|
|
25
28
|
</menu>
|
|
26
29
|
</li>
|
|
27
30
|
<NavDropdown v-else-if="item.items" :items="item.items" />
|
|
28
|
-
<li v-else>
|
|
31
|
+
<li v-else :class="{ active: isActive(item, route.path) }">
|
|
29
32
|
<a
|
|
30
33
|
v-if="item.link"
|
|
31
34
|
:href="withBase(item.link)"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="tags-page">
|
|
3
|
-
|
|
2
|
+
<div class="tags-page" :class="{ 'has-hero': Boolean(frontmatter.hero) }">
|
|
3
|
+
<!-- Header (shown only when hero is not present) -->
|
|
4
|
+
<header v-if="!frontmatter.hero" class="tags-header">
|
|
4
5
|
<h1 class="tags-title">Blog Tags</h1>
|
|
5
6
|
<p class="tags-subtitle">
|
|
6
7
|
Explore our blog posts by topics and technology pillars.
|
|
@@ -69,10 +70,12 @@
|
|
|
69
70
|
|
|
70
71
|
<script setup>
|
|
71
72
|
import { computed } from "vue";
|
|
72
|
-
import { withBase } from "vitepress";
|
|
73
|
+
import { useData, withBase } from "vitepress";
|
|
73
74
|
import { data as posts } from "../posts.data.js";
|
|
74
75
|
import { getTagColor, getTagStyle } from "../tagUtils.js";
|
|
75
76
|
|
|
77
|
+
const { frontmatter } = useData();
|
|
78
|
+
|
|
76
79
|
const allTagsList = computed(() => {
|
|
77
80
|
// Aggregate all tag occurrences
|
|
78
81
|
const tagCounts = {};
|
|
@@ -111,6 +114,10 @@ const allTagsList = computed(() => {
|
|
|
111
114
|
box-sizing: border-box;
|
|
112
115
|
}
|
|
113
116
|
|
|
117
|
+
.tags-page.has-hero {
|
|
118
|
+
padding-top: 2rem;
|
|
119
|
+
}
|
|
120
|
+
|
|
114
121
|
@media (min-width: 640px) {
|
|
115
122
|
.tags-page {
|
|
116
123
|
padding-left: 1.5rem;
|
|
@@ -118,6 +125,9 @@ const allTagsList = computed(() => {
|
|
|
118
125
|
padding-top: calc(var(--vp-nav-height) + 40px);
|
|
119
126
|
padding-bottom: 64px;
|
|
120
127
|
}
|
|
128
|
+
.tags-page.has-hero {
|
|
129
|
+
padding-top: 2.5rem;
|
|
130
|
+
}
|
|
121
131
|
}
|
|
122
132
|
|
|
123
133
|
@media (min-width: 960px) {
|
|
@@ -127,6 +137,9 @@ const allTagsList = computed(() => {
|
|
|
127
137
|
padding-top: calc(var(--vp-nav-height) + 58px);
|
|
128
138
|
padding-bottom: 96px;
|
|
129
139
|
}
|
|
140
|
+
.tags-page.has-hero {
|
|
141
|
+
padding-top: 3rem;
|
|
142
|
+
}
|
|
130
143
|
}
|
|
131
144
|
|
|
132
145
|
/* Page Header */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="team-page">
|
|
3
|
-
<!-- Header -->
|
|
4
|
-
<header class="team-header">
|
|
2
|
+
<div class="team-page" :class="{ 'has-hero': Boolean(frontmatter.hero) }">
|
|
3
|
+
<!-- Header (shown only when hero is not present) -->
|
|
4
|
+
<header v-if="!frontmatter.hero" class="team-header">
|
|
5
5
|
<h1 class="team-title">
|
|
6
6
|
{{ frontmatter.title || "Our Team" }}
|
|
7
7
|
</h1>
|
|
@@ -137,6 +137,10 @@ const memberHasPosts = (memberId) => {
|
|
|
137
137
|
word-break: break-word;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
+
.team-page.has-hero {
|
|
141
|
+
padding-top: 2rem !important;
|
|
142
|
+
}
|
|
143
|
+
|
|
140
144
|
@media (min-width: 640px) {
|
|
141
145
|
.team-page {
|
|
142
146
|
padding-left: 1.5rem !important;
|
|
@@ -144,6 +148,9 @@ const memberHasPosts = (memberId) => {
|
|
|
144
148
|
padding-top: calc(var(--vp-nav-height) + 40px) !important;
|
|
145
149
|
padding-bottom: 64px !important;
|
|
146
150
|
}
|
|
151
|
+
.team-page.has-hero {
|
|
152
|
+
padding-top: 2.5rem !important;
|
|
153
|
+
}
|
|
147
154
|
}
|
|
148
155
|
|
|
149
156
|
@media (min-width: 960px) {
|
|
@@ -153,6 +160,9 @@ const memberHasPosts = (memberId) => {
|
|
|
153
160
|
padding-top: calc(var(--vp-nav-height) + 58px) !important;
|
|
154
161
|
padding-bottom: 96px !important;
|
|
155
162
|
}
|
|
163
|
+
.team-page.has-hero {
|
|
164
|
+
padding-top: 3rem !important;
|
|
165
|
+
}
|
|
156
166
|
}
|
|
157
167
|
|
|
158
168
|
/* Page Header */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<section class="testimonials-section full-width surface-container-
|
|
2
|
+
<section class="testimonials-section full-width surface-container-lowest">
|
|
3
3
|
<div class="holder">
|
|
4
4
|
<!-- Left Side: Headline -->
|
|
5
5
|
<div class="headline">
|
|
@@ -9,10 +9,27 @@
|
|
|
9
9
|
</div>
|
|
10
10
|
|
|
11
11
|
<!-- Right Side: Text Block -->
|
|
12
|
-
<div
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
<div
|
|
13
|
+
v-if="testimonials && testimonials.length > 0"
|
|
14
|
+
class="text-block"
|
|
15
|
+
role="region"
|
|
16
|
+
aria-roledescription="carousel"
|
|
17
|
+
:aria-label="title"
|
|
18
|
+
>
|
|
19
|
+
<!-- Testimonial Quotes Overlapping Grid -->
|
|
20
|
+
<div class="quotes-grid" aria-live="polite">
|
|
21
|
+
<div
|
|
22
|
+
v-for="(item, index) in testimonials"
|
|
23
|
+
:key="index"
|
|
24
|
+
class="quote-slide"
|
|
25
|
+
:class="{
|
|
26
|
+
active: index === currentIndex,
|
|
27
|
+
'quote-text': index === currentIndex,
|
|
28
|
+
}"
|
|
29
|
+
:aria-hidden="index !== currentIndex"
|
|
30
|
+
>
|
|
31
|
+
“{{ item.quote }}”
|
|
32
|
+
</div>
|
|
16
33
|
</div>
|
|
17
34
|
|
|
18
35
|
<!-- Divider / Separator -->
|
|
@@ -20,14 +37,28 @@
|
|
|
20
37
|
|
|
21
38
|
<!-- Frame 469: Author info & sliders -->
|
|
22
39
|
<div class="frame-469">
|
|
23
|
-
<!-- Frame 468: Author Name and Role -->
|
|
40
|
+
<!-- Frame 468: Author Name and Role Overlapping Grid -->
|
|
24
41
|
<div class="frame-468">
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
{
|
|
30
|
-
|
|
42
|
+
<div
|
|
43
|
+
v-for="(item, index) in testimonials"
|
|
44
|
+
:key="index"
|
|
45
|
+
class="author-slide"
|
|
46
|
+
:class="{ active: index === currentIndex }"
|
|
47
|
+
:aria-hidden="index !== currentIndex"
|
|
48
|
+
>
|
|
49
|
+
<span
|
|
50
|
+
class="author-name-text"
|
|
51
|
+
:class="{ 'author-name': index === currentIndex }"
|
|
52
|
+
>
|
|
53
|
+
{{ item.author }}
|
|
54
|
+
</span>
|
|
55
|
+
<span
|
|
56
|
+
class="author-role-text"
|
|
57
|
+
:class="{ 'author-role': index === currentIndex }"
|
|
58
|
+
>
|
|
59
|
+
{{ item.role }}
|
|
60
|
+
</span>
|
|
61
|
+
</div>
|
|
31
62
|
</div>
|
|
32
63
|
|
|
33
64
|
<!-- sliders: Navigation Buttons -->
|
|
@@ -57,7 +88,7 @@
|
|
|
57
88
|
</template>
|
|
58
89
|
|
|
59
90
|
<script setup>
|
|
60
|
-
import { ref, computed } from "vue";
|
|
91
|
+
import { ref, computed, watch } from "vue";
|
|
61
92
|
|
|
62
93
|
const props = defineProps({
|
|
63
94
|
title: {
|
|
@@ -91,6 +122,16 @@ const props = defineProps({
|
|
|
91
122
|
|
|
92
123
|
const currentIndex = ref(0);
|
|
93
124
|
|
|
125
|
+
// Clamp currentIndex if testimonials prop array changes dynamically
|
|
126
|
+
watch(
|
|
127
|
+
() => props.testimonials?.length,
|
|
128
|
+
(len) => {
|
|
129
|
+
if (len && currentIndex.value >= len) {
|
|
130
|
+
currentIndex.value = 0;
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
);
|
|
134
|
+
|
|
94
135
|
const currentTestimonial = computed(() => {
|
|
95
136
|
if (!props.testimonials || props.testimonials.length === 0) return null;
|
|
96
137
|
return props.testimonials[currentIndex.value];
|
|
@@ -118,6 +159,7 @@ section.testimonials-section {
|
|
|
118
159
|
margin-block-start: 6rem;
|
|
119
160
|
margin-block-end: 6rem;
|
|
120
161
|
box-sizing: border-box;
|
|
162
|
+
background-color: var(--surface-container-lowest, #ffffff);
|
|
121
163
|
}
|
|
122
164
|
|
|
123
165
|
@media (min-width: 1024px) {
|
|
@@ -168,6 +210,38 @@ section.testimonials-section {
|
|
|
168
210
|
gap: 24px;
|
|
169
211
|
}
|
|
170
212
|
|
|
213
|
+
.quotes-grid {
|
|
214
|
+
display: grid;
|
|
215
|
+
grid-template-columns: 1fr;
|
|
216
|
+
width: 100%;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.quote-slide {
|
|
220
|
+
grid-column: 1;
|
|
221
|
+
grid-row: 1;
|
|
222
|
+
align-self: start;
|
|
223
|
+
font-family: "Inter", sans-serif;
|
|
224
|
+
font-style: normal;
|
|
225
|
+
font-weight: 400;
|
|
226
|
+
font-size: 16px;
|
|
227
|
+
line-height: 24px;
|
|
228
|
+
letter-spacing: 0.5px;
|
|
229
|
+
color: #00060a;
|
|
230
|
+
min-height: 72px;
|
|
231
|
+
opacity: 0;
|
|
232
|
+
visibility: hidden;
|
|
233
|
+
transition:
|
|
234
|
+
opacity 0.25s ease,
|
|
235
|
+
visibility 0.25s ease;
|
|
236
|
+
pointer-events: none;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.quote-slide.active {
|
|
240
|
+
opacity: 1;
|
|
241
|
+
visibility: visible;
|
|
242
|
+
pointer-events: auto;
|
|
243
|
+
}
|
|
244
|
+
|
|
171
245
|
.quote-text {
|
|
172
246
|
font-family: "Inter", sans-serif;
|
|
173
247
|
font-style: normal;
|
|
@@ -195,14 +269,35 @@ section.testimonials-section {
|
|
|
195
269
|
}
|
|
196
270
|
|
|
197
271
|
.frame-468 {
|
|
272
|
+
display: grid;
|
|
273
|
+
grid-template-columns: 1fr;
|
|
274
|
+
align-items: flex-start;
|
|
275
|
+
flex-grow: 1;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.author-slide {
|
|
279
|
+
grid-column: 1;
|
|
280
|
+
grid-row: 1;
|
|
198
281
|
display: flex;
|
|
199
282
|
flex-direction: column;
|
|
200
283
|
align-items: flex-start;
|
|
201
284
|
gap: 8px;
|
|
202
|
-
|
|
285
|
+
opacity: 0;
|
|
286
|
+
visibility: hidden;
|
|
287
|
+
transition:
|
|
288
|
+
opacity 0.25s ease,
|
|
289
|
+
visibility 0.25s ease;
|
|
290
|
+
pointer-events: none;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.author-slide.active {
|
|
294
|
+
opacity: 1;
|
|
295
|
+
visibility: visible;
|
|
296
|
+
pointer-events: auto;
|
|
203
297
|
}
|
|
204
298
|
|
|
205
|
-
.author-name
|
|
299
|
+
.author-name,
|
|
300
|
+
.author-name-text {
|
|
206
301
|
font-family: "Inter", sans-serif;
|
|
207
302
|
font-style: normal;
|
|
208
303
|
font-weight: 700;
|
|
@@ -212,7 +307,8 @@ section.testimonials-section {
|
|
|
212
307
|
color: #00060a;
|
|
213
308
|
}
|
|
214
309
|
|
|
215
|
-
.author-role
|
|
310
|
+
.author-role,
|
|
311
|
+
.author-role-text {
|
|
216
312
|
font-family: "Inter", sans-serif;
|
|
217
313
|
font-style: normal;
|
|
218
314
|
font-weight: 400;
|
|
@@ -222,6 +318,13 @@ section.testimonials-section {
|
|
|
222
318
|
color: #00060a;
|
|
223
319
|
}
|
|
224
320
|
|
|
321
|
+
@media (prefers-reduced-motion: reduce) {
|
|
322
|
+
.quote-slide,
|
|
323
|
+
.author-slide {
|
|
324
|
+
transition: none;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
225
328
|
.sliders {
|
|
226
329
|
display: flex;
|
|
227
330
|
flex-direction: row;
|
|
@@ -98,8 +98,9 @@ defineProps({
|
|
|
98
98
|
:deep(samp),
|
|
99
99
|
:deep(var),
|
|
100
100
|
:deep(.monospace) {
|
|
101
|
-
font-family:
|
|
102
|
-
"
|
|
101
|
+
font-family:
|
|
102
|
+
"SFMono-Regular", "Menlo", "Monaco", "Consolas", "Liberation Mono",
|
|
103
|
+
"Ubuntu Mono", "Courier New", monospace !important;
|
|
103
104
|
}
|
|
104
105
|
|
|
105
106
|
/* Inline code */
|
package/src/helpers.js
CHANGED
|
@@ -283,6 +283,8 @@ export const getFlatList = (items) => {
|
|
|
283
283
|
* @returns {boolean}
|
|
284
284
|
*/
|
|
285
285
|
export const isActive = (item, path) => {
|
|
286
|
+
if (!item || !path) return false;
|
|
287
|
+
|
|
286
288
|
if (item.activeMatch) {
|
|
287
289
|
try {
|
|
288
290
|
return new RegExp(item.activeMatch).test(path);
|
|
@@ -292,20 +294,26 @@ export const isActive = (item, path) => {
|
|
|
292
294
|
}
|
|
293
295
|
}
|
|
294
296
|
|
|
295
|
-
if (item.items) {
|
|
296
|
-
return
|
|
297
|
+
if (item.items && item.items.some((sub) => isActive(sub, path))) {
|
|
298
|
+
return true;
|
|
297
299
|
}
|
|
298
300
|
|
|
299
301
|
if (item.link) {
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
+
const normalize = (p) =>
|
|
303
|
+
decodeURI(p)
|
|
304
|
+
.replace(/[?#].*$/, "")
|
|
305
|
+
.replace(/\.html$/, "")
|
|
306
|
+
.replace(/\/$/, "");
|
|
307
|
+
|
|
308
|
+
const linkPath = normalize(item.link);
|
|
309
|
+
const currentPath = normalize(path);
|
|
302
310
|
|
|
303
311
|
if (linkPath === currentPath) return true;
|
|
304
312
|
|
|
305
313
|
// Special case for home page to avoid matching everything
|
|
306
314
|
if (linkPath === "") return currentPath === "";
|
|
307
315
|
|
|
308
|
-
return currentPath.startsWith(linkPath);
|
|
316
|
+
return currentPath === linkPath || currentPath.startsWith(linkPath + "/");
|
|
309
317
|
}
|
|
310
318
|
|
|
311
319
|
return false;
|
package/src/helpers.test.js
CHANGED
|
@@ -144,10 +144,38 @@ describe("existing helpers", () => {
|
|
|
144
144
|
t("nav.unknown", { nav: { home: "Home Page" } }),
|
|
145
145
|
"nav.unknown",
|
|
146
146
|
);
|
|
147
|
+
assert.equal(t("Imprint", { Imprint: "Impressum" }), "Impressum");
|
|
148
|
+
assert.equal(t("Imprint", {}), "Imprint");
|
|
147
149
|
});
|
|
148
150
|
|
|
149
151
|
it("checks isActive links correctly", () => {
|
|
150
152
|
assert.equal(isActive({ link: "/explore/" }, "/explore"), true);
|
|
151
153
|
assert.equal(isActive({ link: "/explore" }, "/explore/"), true);
|
|
154
|
+
assert.equal(isActive({ link: "/explore" }, "/explore/subpage"), true);
|
|
155
|
+
assert.equal(isActive({ link: "/explore" }, "/explore-other"), false);
|
|
156
|
+
assert.equal(isActive({ link: "/explore" }, "/explore?tab=1#sec"), true);
|
|
157
|
+
assert.equal(isActive({ link: "/" }, "/"), true);
|
|
158
|
+
assert.equal(isActive({ link: "/" }, "/explore"), false);
|
|
159
|
+
|
|
160
|
+
// Parent dropdown with items
|
|
161
|
+
const parentDropdown = {
|
|
162
|
+
text: "Expertise",
|
|
163
|
+
items: [
|
|
164
|
+
{ text: "Data Management", link: "/expertise/data-management" },
|
|
165
|
+
{ text: "Data Visualization", link: "/expertise/data-visualization" },
|
|
166
|
+
],
|
|
167
|
+
};
|
|
168
|
+
assert.equal(isActive(parentDropdown, "/expertise/data-management"), true);
|
|
169
|
+
assert.equal(isActive(parentDropdown, "/expertise/data-management/"), true);
|
|
170
|
+
assert.equal(isActive(parentDropdown, "/solutions"), false);
|
|
171
|
+
|
|
172
|
+
// Parent with both link and items
|
|
173
|
+
const parentWithLinkAndItems = {
|
|
174
|
+
text: "Products",
|
|
175
|
+
link: "/products",
|
|
176
|
+
items: [{ text: "Product A", link: "/products/a" }],
|
|
177
|
+
};
|
|
178
|
+
assert.equal(isActive(parentWithLinkAndItems, "/products/a"), true);
|
|
179
|
+
assert.equal(isActive(parentWithLinkAndItems, "/products"), true);
|
|
152
180
|
});
|
|
153
181
|
});
|
package/src/pages/blog.md
CHANGED
package/src/pages/tag/[tag].md
CHANGED
package/src/pages/tag.md
CHANGED