@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.
Files changed (38) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +83 -0
  3. package/cypress/support/mocks/vitepress.js +8 -1
  4. package/cypress.config.js +5 -0
  5. package/package.json +1 -1
  6. package/src/Layout.vue +58 -1
  7. package/src/authors.data.js +14 -0
  8. package/src/components/BlogList.vue +636 -0
  9. package/src/components/BlogPost.vue +450 -0
  10. package/src/components/FeatureCard/Index.vue +370 -26
  11. package/src/components/HeroSection.vue +1 -1
  12. package/src/components/ImageCarousel.cy.js +22 -0
  13. package/src/components/ImageCarousel.vue +268 -0
  14. package/src/components/ImageElement.cy.js +46 -0
  15. package/src/components/ImageElement.vue +269 -0
  16. package/src/components/ImageGallery.cy.js +52 -0
  17. package/src/components/ImageGallery.vue +622 -0
  18. package/src/components/SectionHeader.cy.js +54 -0
  19. package/src/components/SectionHeader.vue +115 -0
  20. package/src/components/SingleTweet.cy.js +27 -0
  21. package/src/components/SingleTweet.vue +155 -0
  22. package/src/components/TagList.vue +293 -0
  23. package/src/components/TeamPage.vue +333 -0
  24. package/src/components/TestimonialsSection.cy.js +79 -0
  25. package/src/components/TestimonialsSection.vue +265 -0
  26. package/src/index.js +21 -0
  27. package/src/pages/author/[author].md +4 -0
  28. package/src/pages/author/[author].paths.js +60 -0
  29. package/src/pages/blog.md +4 -0
  30. package/src/pages/tag/[tag].md +4 -0
  31. package/src/pages/tag/[tag].paths.js +49 -0
  32. package/src/pages/tag.md +4 -0
  33. package/src/pages/team.md +4 -0
  34. package/src/posts.data.js +96 -0
  35. package/src/style.css +160 -0
  36. package/src/tagUtils.js +148 -0
  37. package/src/team.data.js +51 -0
  38. package/src/vitepressConfig.mjs +97 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ # [1.9.0](https://gitlab.eox.at/eox/hub/eoxhub-portal/compare/v1.8.0...v1.9.0) (2026-06-11)
4
+
5
+ ### Features
6
+
7
+ - new components (ImageCarousel, ImageElement, ImageGallery, SingleTweet) and automated loaders (team) ([8ce5f28](https://gitlab.eox.at/eox/hub/eoxhub-portal/commit/8ce5f289f06c1d4ebd7ff4871008f0dec31dabcc))
8
+
3
9
  # [1.8.0](https://gitlab.eox.at/eox/hub/eoxhub-portal/compare/v1.7.0...v1.8.0) (2026-06-08)
4
10
 
5
11
  ### Bug Fixes
package/README.md CHANGED
@@ -239,6 +239,19 @@ A Call-to-Action section typically placed at the bottom of a page to encourage u
239
239
  />
240
240
  ```
241
241
 
242
+ #### Section Header
243
+
244
+ A standardized three-tier header block for page sections, matching EOX design tokens with a tag badge, a large display title, and an optional subtitle description. Supports light/dark context modes automatically.
245
+
246
+ ```html
247
+ <SectionHeader
248
+ tag="Viewing Ready & Basic"
249
+ icon="mdi-star-check-outline"
250
+ title="What our users say about Viewing Products"
251
+ subtitle="Optional paragraph providing context and detail for this section."
252
+ />
253
+ ```
254
+
242
255
  #### Logo Section
243
256
 
244
257
  Displays a grid of client or partner logos. It automatically handles logo sizing.
@@ -379,6 +392,76 @@ An image-overlay card where a background image fills the card and text is render
379
392
  />
380
393
  ```
381
394
 
395
+ #### Image Element
396
+
397
+ Displays standard images with optional caption and width, and supports interactive side-by-side comparison slider when a `compare` prop is provided.
398
+
399
+ ```html
400
+ <!-- Standard Image -->
401
+ <ImageElement
402
+ src="/images/someimage.jpg"
403
+ caption="Standard view"
404
+ width="450px"
405
+ />
406
+
407
+ <!-- Image Comparison Slider -->
408
+ <ImageElement
409
+ src="/images/eoxcloudless2024.jpg"
410
+ compare="/images/eoxcloudless2023.jpg"
411
+ caption="2024 vs. 2023 comparison"
412
+ />
413
+ ```
414
+
415
+ #### Image Gallery
416
+
417
+ A unified, responsive image grid and lightbox gallery. Supports both plain link/grid layouts and touch-friendly lightbox galleries.
418
+
419
+ ##### Properties
420
+
421
+ | Prop | Type | Default | Description |
422
+ | :--------- | :-------------- | :---------- | :---------------------------------------------------------------------------------------------------- |
423
+ | `images` | `String\|Array` | — | Comma-separated image paths string, array of paths, or array of image objects with caption and links. |
424
+ | `columns` | `Number` | `2` | Number of columns (1, 2, 3, 4, 5). |
425
+ | `layout` | `String` | `"gallery"` | Layout mode: `"gallery"` (featured image + thumbnails) or `"grid"` (regular grid of images). |
426
+ | `lightbox` | `Boolean` | `true` | Enable fullscreen lightbox overlay when clicking an image. |
427
+
428
+ ```html
429
+ <!-- Gallery with Lightbox -->
430
+ <ImageGallery images="/img1.jpg, /img2.jpg, /img3.jpg" layout="gallery" />
431
+
432
+ <!-- Direct Image Grid with Captions & Links -->
433
+ <ImageGallery
434
+ layout="grid"
435
+ :columns="3"
436
+ :images="[
437
+ { src: '/img1.jpg', caption: 'Link to A', link: '/page-a' },
438
+ { src: '/img2.jpg', caption: 'Only Caption' },
439
+ { src: '/img3.jpg', caption: 'Link to B', link: '/page-b' }
440
+ ]"
441
+ />
442
+ ```
443
+
444
+ #### Image Carousel
445
+
446
+ A simple CSS-driven accessible image slideshow.
447
+
448
+ ```html
449
+ <ImageCarousel
450
+ :images="[
451
+ { src: '/slide1.jpg', caption: 'Slide 1 Caption' },
452
+ { src: '/slide2.jpg', caption: 'Slide 2 Caption' }
453
+ ]"
454
+ />
455
+ ```
456
+
457
+ #### Single Tweet
458
+
459
+ A privacy-respecting Twitter/X embed wrapper that checks Matomo cookie consent before rendering.
460
+
461
+ ```html
462
+ <SingleTweet id="1276442045352226817" />
463
+ ```
464
+
382
465
  #### Feedback Form
383
466
 
384
467
  **Feedback Form** for collecting user feedback can be enabled by configuring the theme:
@@ -1,4 +1,11 @@
1
- import { reactive, ref } from "vue";
1
+ import { reactive, ref, defineComponent, h } from "vue";
2
+
3
+ export const VPNavBarSearch = defineComponent({
4
+ name: "VPNavBarSearch",
5
+ render() {
6
+ return h("div", { class: "VPNavBarSearch" }, "Search");
7
+ },
8
+ });
2
9
 
3
10
  const site = ref({
4
11
  title: "Test Site",
package/cypress.config.js CHANGED
@@ -10,6 +10,11 @@ export default defineConfig({
10
10
  viteConfig: {
11
11
  resolve: {
12
12
  alias: {
13
+ // Alias vitepress/theme to our mock
14
+ "vitepress/theme": path.resolve(
15
+ __dirname,
16
+ "cypress/support/mocks/vitepress.js",
17
+ ),
13
18
  // Alias vitepress to our mock
14
19
  vitepress: path.resolve(
15
20
  __dirname,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eox/pages-theme-eox",
3
- "version": "1.8.0",
3
+ "version": "2.0.0-alpha.1",
4
4
  "type": "module",
5
5
  "description": "Vitepress Theme with EOX branding",
6
6
  "main": "src/index.js",
package/src/Layout.vue CHANGED
@@ -1,5 +1,53 @@
1
1
  <template>
2
- <Layout :class="`layout-${frontmatter.layout}`">
2
+ <div
3
+ v-if="frontmatter.layout === 'blog'"
4
+ class="layout-blog min-h-screen flex flex-col"
5
+ >
6
+ <NavBar />
7
+ <NewsBanner v-if="theme.newsBanner" :content="theme.newsBanner" />
8
+ <main class="flex-grow">
9
+ <BlogList />
10
+ </main>
11
+ <Footer v-if="frontmatter.footer !== false" />
12
+ <CookieBanner v-if="theme.theme.brandConfig?.analytics"></CookieBanner>
13
+ </div>
14
+ <div
15
+ v-else-if="frontmatter.layout === 'tags'"
16
+ class="layout-tags min-h-screen flex flex-col"
17
+ >
18
+ <NavBar />
19
+ <NewsBanner v-if="theme.newsBanner" :content="theme.newsBanner" />
20
+ <main class="flex-grow">
21
+ <TagList />
22
+ </main>
23
+ <Footer v-if="frontmatter.footer !== false" />
24
+ <CookieBanner v-if="theme.theme.brandConfig?.analytics"></CookieBanner>
25
+ </div>
26
+ <div
27
+ v-else-if="frontmatter.layout === 'team'"
28
+ class="layout-team min-h-screen flex flex-col"
29
+ >
30
+ <NavBar />
31
+ <NewsBanner v-if="theme.newsBanner" :content="theme.newsBanner" />
32
+ <main class="flex-grow">
33
+ <TeamPage />
34
+ </main>
35
+ <Footer v-if="frontmatter.footer !== false" />
36
+ <CookieBanner v-if="theme.theme.brandConfig?.analytics"></CookieBanner>
37
+ </div>
38
+ <div
39
+ v-else-if="frontmatter.layout === 'post' || isBlogPost"
40
+ class="layout-post min-h-screen flex flex-col"
41
+ >
42
+ <NavBar />
43
+ <NewsBanner v-if="theme.newsBanner" :content="theme.newsBanner" />
44
+ <main class="flex-grow">
45
+ <BlogPost />
46
+ </main>
47
+ <Footer v-if="frontmatter.footer !== false" />
48
+ <CookieBanner v-if="theme.theme.brandConfig?.analytics"></CookieBanner>
49
+ </div>
50
+ <Layout v-else :class="`layout-${frontmatter.layout}`">
3
51
  <template #layout-top>
4
52
  <slot name="layout-top"></slot>
5
53
  <NavBar />
@@ -33,11 +81,20 @@
33
81
  </template>
34
82
 
35
83
  <script setup>
84
+ import { computed } from "vue";
36
85
  import DefaultTheme from "vitepress/theme";
37
86
  import { useData, useRouter } from "vitepress";
38
87
  const { Layout } = DefaultTheme;
39
88
  const { frontmatter, page, theme } = useData();
40
89
  const router = useRouter();
90
+
91
+ const isBlogPost = computed(() => {
92
+ return (
93
+ frontmatter.value.layout === "post" ||
94
+ page.value.relativePath.startsWith("_posts/") ||
95
+ /^\d{4}\/\d{2}\//.test(page.value.relativePath)
96
+ );
97
+ });
41
98
  </script>
42
99
 
43
100
  <style>
@@ -0,0 +1,14 @@
1
+ import { createContentLoader } from "vitepress";
2
+
3
+ export default createContentLoader("_team/*.md", {
4
+ transform(rawData) {
5
+ return rawData.map((page) => {
6
+ return {
7
+ id: page.frontmatter.id || "",
8
+ name: page.frontmatter.title || "",
9
+ url: page.url,
10
+ guest: page.frontmatter.guest || false,
11
+ };
12
+ });
13
+ },
14
+ });