@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
@@ -0,0 +1,333 @@
1
+ <template>
2
+ <div class="team-page">
3
+ <!-- Header -->
4
+ <header class="team-header">
5
+ <h1 class="team-title">
6
+ {{ frontmatter.title || "Our Team" }}
7
+ </h1>
8
+ <p class="team-subtitle">
9
+ Meet the diverse team of geospatial experts, engineers, and visionaries
10
+ driving EOX forward.
11
+ </p>
12
+ </header>
13
+
14
+ <!-- Team Photo Section -->
15
+ <section class="team-photo-section">
16
+ <img
17
+ :src="withBase('/images/team/team.jpg')"
18
+ alt="EOX Team Photo"
19
+ class="team-photo"
20
+ />
21
+ </section>
22
+
23
+ <!-- Team Grid - max 3 columns on large screens -->
24
+ <div class="team-grid">
25
+ <FeatureCard
26
+ v-for="member in sortedTeamMembers"
27
+ :key="member.id"
28
+ :title="member.name"
29
+ :image="member.image ? withBase(member.image) : withBase('/images/team/new_member.jpg')"
30
+ :link="memberHasPosts(member.id) ? {
31
+ text: 'View blog posts',
32
+ href: `/author/${member.id}/`,
33
+ target: '_self'
34
+ } : undefined"
35
+ variant="cover"
36
+ class="bg-surface-container-low team-member-card"
37
+ >
38
+ <!-- Role / Job Title -->
39
+ <span v-if="member.role" class="member-role">
40
+ {{ member.role }}
41
+ </span>
42
+
43
+ <span class="member-divider"></span>
44
+
45
+ <!-- Description / Bio -->
46
+ <span
47
+ v-if="member.bio"
48
+ class="member-bio"
49
+ v-html="member.bio"
50
+ ></span>
51
+
52
+ <!-- Social Links row at the bottom of slot -->
53
+ <span class="member-footer">
54
+ <!-- Social Icons - aligned to the left matching other content -->
55
+ <span class="social-links-row">
56
+ <template v-for="(url, platform) in member.sns" :key="platform">
57
+ <a
58
+ v-if="url"
59
+ :href="url"
60
+ target="_blank"
61
+ rel="noopener noreferrer"
62
+ class="social-link-btn"
63
+ :title="`${member.name} on ${platform}`"
64
+ >
65
+ <!-- Bluesky custom SVG -->
66
+ <svg
67
+ v-if="platform === 'bluesky'"
68
+ viewBox="0 0 512 512"
69
+ style="width: 18px; height: 18px; fill: currentColor"
70
+ >
71
+ <path
72
+ d="M111.8 109.6C166.1 154.2 226.8 231.1 256 271.7c29.2-40.6 89.9-117.5 144.2-162.1C443.3 74.3 512 57.4 512 121.7c0 23.3-12.7 101.4-19 123.5-16 56.6-70.3 70.8-111.8 62.4C443 328.1 512 361.3 512 411.1c0 51.5-68.7 65.1-111.8 18.2-70.3 76.5-161.4 11-200.2-29-38.8 40-129.9 105.5-200.2 29C56.7 476.2 0 462.6 0 411.1c0-49.8 69-83 130.8-103.5C89.3 316 35 301.8 19 245.2 12.7 223 0 145 0 121.7c0-64.3 68.7-47.4 111.8-12.1z"
73
+ />
74
+ </svg>
75
+ <i
76
+ v-else-if="platform === 'linkedin'"
77
+ class="mdi mdi-linkedin text-lg"
78
+ ></i>
79
+ <i
80
+ v-else-if="platform === 'github'"
81
+ class="mdi mdi-github text-lg"
82
+ ></i>
83
+ <i
84
+ v-else-if="platform === 'twitter'"
85
+ class="mdi mdi-twitter text-lg"
86
+ ></i>
87
+ <i
88
+ v-else-if="platform === 'facebook'"
89
+ class="mdi mdi-facebook text-lg"
90
+ ></i>
91
+ <i v-else :class="`mdi mdi-${platform} text-lg`"></i>
92
+ </a>
93
+ </template>
94
+ </span>
95
+ </span>
96
+ </FeatureCard>
97
+ </div>
98
+ </div>
99
+ </template>
100
+
101
+ <script setup>
102
+ import { computed } from "vue";
103
+ import { useData, withBase } from "vitepress";
104
+ import { data as teamMembers } from "../team.data.js";
105
+ import { data as posts } from "../posts.data.js";
106
+ import FeatureCard from "./FeatureCard/Index.vue";
107
+
108
+ const { frontmatter } = useData();
109
+
110
+ const sortedTeamMembers = computed(() => {
111
+ return teamMembers;
112
+ });
113
+
114
+ const memberHasPosts = (memberId) => {
115
+ if (!memberId || memberId === "new_member") return false;
116
+ return posts.some((post) => {
117
+ return Array.isArray(post.authors) && post.authors.includes(memberId);
118
+ });
119
+ };
120
+ </script>
121
+
122
+ <style scoped>
123
+ .team-page {
124
+ width: 100%;
125
+ max-width: 1200px !important;
126
+ margin-left: auto !important;
127
+ margin-right: auto !important;
128
+ padding-left: 1rem !important;
129
+ padding-right: 1rem !important;
130
+ box-sizing: border-box !important;
131
+ padding-top: calc(var(--vp-nav-height) + 28px) !important;
132
+ padding-bottom: 48px !important;
133
+ word-break: break-word;
134
+ }
135
+
136
+ @media (min-width: 640px) {
137
+ .team-page {
138
+ padding-left: 1.5rem !important;
139
+ padding-right: 1.5rem !important;
140
+ padding-top: calc(var(--vp-nav-height) + 40px) !important;
141
+ padding-bottom: 64px !important;
142
+ }
143
+ }
144
+
145
+ @media (min-width: 960px) {
146
+ .team-page {
147
+ padding-left: 2rem !important;
148
+ padding-right: 2rem !important;
149
+ padding-top: calc(var(--vp-nav-height) + 58px) !important;
150
+ padding-bottom: 96px !important;
151
+ }
152
+ }
153
+
154
+ /* Page Header */
155
+ .team-header {
156
+ margin-bottom: 2.5rem;
157
+ border-bottom: 1px solid #f1f5f9; /* slate-100 */
158
+ padding-bottom: 1.5rem !important;
159
+ padding-top: 0 !important;
160
+ padding-left: 0 !important;
161
+ padding-right: 0 !important;
162
+ background: transparent !important;
163
+ min-height: auto !important;
164
+ height: auto !important;
165
+ }
166
+
167
+ .team-title {
168
+ font-family: "Inter", sans-serif;
169
+ font-style: normal;
170
+ font-weight: 700;
171
+ font-size: 28px;
172
+ line-height: 36px;
173
+ letter-spacing: 0.5px;
174
+ color: #020617; /* slate-950 */
175
+ margin-top: 0;
176
+ margin-bottom: 0.5rem;
177
+ }
178
+
179
+ @media (min-width: 768px) {
180
+ .team-title {
181
+ font-size: 32px;
182
+ line-height: 40px;
183
+ }
184
+ }
185
+
186
+ .team-subtitle {
187
+ font-family: "Inter", sans-serif;
188
+ font-style: normal;
189
+ font-weight: 400;
190
+ font-size: 16px;
191
+ line-height: 24px;
192
+ letter-spacing: 0.5px;
193
+ color: #64748b; /* slate-500 */
194
+ max-width: 620px;
195
+ margin: 0;
196
+ padding: 0;
197
+ }
198
+
199
+ /* Team Photo Section */
200
+ .team-photo-section {
201
+ margin-bottom: 3.5rem;
202
+ overflow: hidden;
203
+ border-radius: 1rem; /* 16px */
204
+ border: 1px solid rgba(226, 232, 240, 0.5); /* border-slate-100/50 */
205
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
206
+ }
207
+
208
+ .team-photo {
209
+ width: 100%;
210
+ height: auto;
211
+ object-fit: cover;
212
+ max-height: 500px;
213
+ }
214
+
215
+ /* Team Grid - custom grid definition to prevent conflict with Beercss global .grid */
216
+ .team-grid {
217
+ display: grid;
218
+ grid-template-columns: repeat(1, minmax(0, 1fr));
219
+ gap: 2rem;
220
+ }
221
+
222
+ @media (min-width: 640px) {
223
+ .team-grid {
224
+ grid-template-columns: repeat(2, minmax(0, 1fr));
225
+ }
226
+ }
227
+
228
+ @media (min-width: 1024px) {
229
+ .team-grid {
230
+ grid-template-columns: repeat(3, minmax(0, 1fr));
231
+ }
232
+ }
233
+
234
+ /* Deep overrides to integrate with theme-provided FeatureCard */
235
+ .team-member-card {
236
+ height: 100% !important;
237
+ }
238
+
239
+ .team-member-card :deep(.card-cover-link) {
240
+ aspect-ratio: 1 / 1 !important; /* Override cover layout aspect ratio to square portrait */
241
+ }
242
+
243
+ /* Left-align card titles and override margin */
244
+ .team-member-card :deep(.card-title-text) {
245
+ text-align: left !important;
246
+ margin-top: 0 !important;
247
+ margin-bottom: 0.5rem !important;
248
+ font-size: 1.25rem !important; /* exactly 20px matching card expectations */
249
+ font-weight: 700 !important;
250
+ }
251
+
252
+ /* Deep override card navigation to align properly */
253
+ .team-member-card :deep(.card-navigation) {
254
+ margin-top: 1rem !important;
255
+ padding-left: 1.5rem !important;
256
+ padding-bottom: 1.5rem !important;
257
+ }
258
+
259
+ .team-member-card :deep(.card-content-wrapper) {
260
+ display: flex !important;
261
+ flex-direction: column !important;
262
+ height: 100% !important;
263
+ }
264
+
265
+ .team-member-card :deep(.card-body-text) {
266
+ display: flex !important;
267
+ flex-direction: column !important;
268
+ flex-grow: 1 !important;
269
+ margin: 0 !important;
270
+ text-align: left !important;
271
+ }
272
+
273
+ /* Member Content Slot Elements (all left-aligned) */
274
+ .member-role {
275
+ display: block;
276
+ color: var(--primary) !important;
277
+ font-weight: 600 !important;
278
+ font-size: 0.875rem !important; /* 14px */
279
+ margin-top: 0 !important;
280
+ margin-bottom: 1rem !important;
281
+ text-align: left !important;
282
+ }
283
+
284
+ .member-divider {
285
+ display: block;
286
+ border: 0;
287
+ border-top: 1px solid #f1f5f9 !important; /* slate-100 */
288
+ margin-top: 0.5rem !important;
289
+ margin-bottom: 0.75rem !important;
290
+ }
291
+
292
+ .member-bio {
293
+ display: block;
294
+ font-size: 0.875rem !important; /* 14px */
295
+ line-height: 1.6 !important;
296
+ color: #475569 !important; /* slate-600 */
297
+ margin-top: 0 !important;
298
+ margin-bottom: 1.5rem !important;
299
+ text-align: left !important;
300
+ flex-grow: 1;
301
+ }
302
+
303
+ .member-footer {
304
+ display: flex;
305
+ flex-direction: column;
306
+ gap: 1rem;
307
+ margin-top: auto !important;
308
+ }
309
+
310
+ .social-links-row {
311
+ display: flex;
312
+ align-items: center;
313
+ justify-content: flex-start; /* Aligned to left */
314
+ gap: 0.5rem;
315
+ }
316
+
317
+ .social-link-btn {
318
+ width: 2.25rem;
319
+ height: 2.25rem;
320
+ display: flex;
321
+ align-items: center;
322
+ justify-content: center;
323
+ border-radius: 9999px;
324
+ color: #94a3b8; /* slate-400 */
325
+ transition: all 0.15s ease;
326
+ margin-left: -0.5rem; /* subtle offset alignment for first icon */
327
+ }
328
+
329
+ .social-link-btn:hover {
330
+ color: var(--primary);
331
+ background-color: var(--surface-container-high);
332
+ }
333
+ </style>
@@ -0,0 +1,79 @@
1
+ import TestimonialsSection from "./TestimonialsSection.vue";
2
+
3
+ describe("<TestimonialsSection />", () => {
4
+ it("renders with default props and switches testimonials", () => {
5
+ cy.mount(TestimonialsSection);
6
+
7
+ // Verify title
8
+ cy.get(".section-display-title").should(
9
+ "contain",
10
+ "What our customers are saying",
11
+ );
12
+
13
+ // Verify first testimonial quote
14
+ cy.get(".quote-text").should(
15
+ "contain",
16
+ "The VirES platform has completely revolutionized",
17
+ );
18
+ cy.get(".author-name").should("contain", "Dr. Fiona Harrison");
19
+
20
+ // Click next button
21
+ cy.get("button[aria-label='Next testimonial']").click();
22
+
23
+ // Verify second testimonial quote
24
+ cy.get(".quote-text").should(
25
+ "contain",
26
+ "Deploying our Area Monitoring System",
27
+ );
28
+ cy.get(".author-name").should("contain", "Dr. Liam O'Connor");
29
+
30
+ // Click prev button
31
+ cy.get("button[aria-label='Previous testimonial']").click();
32
+
33
+ // Verify first testimonial quote again
34
+ cy.get(".quote-text").should(
35
+ "contain",
36
+ "The VirES platform has completely revolutionized",
37
+ );
38
+ cy.get(".author-name").should("contain", "Dr. Fiona Harrison");
39
+ });
40
+
41
+ it("renders custom title and custom testimonials list", () => {
42
+ const customTitle = "What Our Amazing Clients Think";
43
+ const customTestimonials = [
44
+ {
45
+ quote: "This is a custom quote that is extremely positive.",
46
+ author: "Alice Smith",
47
+ role: "Software Architect",
48
+ },
49
+ {
50
+ quote: "Another custom quote for testing purposes.",
51
+ author: "Bob Jones",
52
+ role: "Data Analyst",
53
+ },
54
+ ];
55
+
56
+ cy.mount(TestimonialsSection, {
57
+ props: {
58
+ title: customTitle,
59
+ testimonials: customTestimonials,
60
+ },
61
+ });
62
+
63
+ // Check title
64
+ cy.get(".section-display-title").should("contain", customTitle);
65
+
66
+ // Check first custom testimonial
67
+ cy.get(".quote-text").should("contain", "This is a custom quote");
68
+ cy.get(".author-name").should("contain", "Alice Smith");
69
+ cy.get(".author-role").should("contain", "Software Architect");
70
+
71
+ // Go next
72
+ cy.get("button[aria-label='Next testimonial']").click();
73
+
74
+ // Check second custom testimonial
75
+ cy.get(".quote-text").should("contain", "Another custom quote");
76
+ cy.get(".author-name").should("contain", "Bob Jones");
77
+ cy.get(".author-role").should("contain", "Data Analyst");
78
+ });
79
+ });
@@ -0,0 +1,265 @@
1
+ <template>
2
+ <section class="testimonials-section full-width surface-container-low">
3
+ <div class="holder">
4
+ <!-- Left Side: Headline -->
5
+ <div class="headline">
6
+ <h2>
7
+ {{ title }}
8
+ </h2>
9
+ </div>
10
+
11
+ <!-- Right Side: Text Block -->
12
+ <div v-if="testimonials && testimonials.length > 0" class="text-block">
13
+ <!-- Testimonial Quote -->
14
+ <div class="quote-text">
15
+ &ldquo;{{ currentTestimonial.quote }}&rdquo;
16
+ </div>
17
+
18
+ <!-- Divider / Separator -->
19
+ <div class="divider"></div>
20
+
21
+ <!-- Frame 469: Author info & sliders -->
22
+ <div class="frame-469">
23
+ <!-- Frame 468: Author Name and Role -->
24
+ <div class="frame-468">
25
+ <span class="author-name">
26
+ {{ currentTestimonial.author }}
27
+ </span>
28
+ <span class="author-role">
29
+ {{ currentTestimonial.role }}
30
+ </span>
31
+ </div>
32
+
33
+ <!-- sliders: Navigation Buttons -->
34
+ <div class="sliders">
35
+ <!-- Left Arrow Button -->
36
+ <button
37
+ class="nav-button"
38
+ @click="prev"
39
+ aria-label="Previous testimonial"
40
+ >
41
+ <i class="mdi mdi-arrow-left"></i>
42
+ </button>
43
+
44
+ <!-- Right Arrow Button -->
45
+ <button
46
+ class="nav-button"
47
+ @click="next"
48
+ aria-label="Next testimonial"
49
+ >
50
+ <i class="mdi mdi-arrow-right"></i>
51
+ </button>
52
+ </div>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ </section>
57
+ </template>
58
+
59
+ <script setup>
60
+ import { ref, computed } from "vue";
61
+
62
+ const props = defineProps({
63
+ title: {
64
+ type: String,
65
+ default: "What our customers are saying",
66
+ },
67
+ testimonials: {
68
+ type: Array,
69
+ default: () => [
70
+ {
71
+ quote:
72
+ "The VirES platform has completely revolutionized how Swarm mission data is accessed and analyzed by the global scientific community. Its cloud-native performance and seamless visualization are unmatched.",
73
+ author: "Dr. Fiona Harrison",
74
+ role: "Lead Swarm Researcher, Scientific Advisory Group",
75
+ },
76
+ {
77
+ quote:
78
+ "Deploying our Area Monitoring System on EOxHub workspaces allowed us to process millions of parcels in near real-time. This level of automation and reliability is precisely what we needed for the CAP implementation.",
79
+ author: "Dr. Liam O'Connor",
80
+ role: "Senior Spatial Scientist, Agricultural Paying Agency",
81
+ },
82
+ {
83
+ quote:
84
+ "The EOX base map layers are an essential asset for our global dashboard. Their Sentinel-2 cloudless composites provide a pristine, cloud-free visual experience that our users absolutely love.",
85
+ author: "Sarah Jenkins",
86
+ role: "Chief Product Officer, Global Earth Explorer Platform",
87
+ },
88
+ ],
89
+ },
90
+ });
91
+
92
+ const currentIndex = ref(0);
93
+
94
+ const currentTestimonial = computed(() => {
95
+ if (!props.testimonials || props.testimonials.length === 0) return null;
96
+ return props.testimonials[currentIndex.value];
97
+ });
98
+
99
+ function prev() {
100
+ if (!props.testimonials || props.testimonials.length === 0) return;
101
+ currentIndex.value =
102
+ (currentIndex.value - 1 + props.testimonials.length) %
103
+ props.testimonials.length;
104
+ }
105
+
106
+ function next() {
107
+ if (!props.testimonials || props.testimonials.length === 0) return;
108
+ currentIndex.value = (currentIndex.value + 1) % props.testimonials.length;
109
+ }
110
+ </script>
111
+
112
+ <style scoped>
113
+ section.testimonials-section {
114
+ display: flex;
115
+ justify-content: center;
116
+ overflow-x: hidden;
117
+ padding: 3rem 1.5rem;
118
+ margin-block-start: 6rem;
119
+ margin-block-end: 6rem;
120
+ box-sizing: border-box;
121
+ }
122
+
123
+ @media (min-width: 1024px) {
124
+ section.testimonials-section {
125
+ padding: 6rem 1.5rem;
126
+ }
127
+ }
128
+
129
+ .holder {
130
+ display: flex;
131
+ flex-direction: column;
132
+ gap: 32px;
133
+ width: 100%;
134
+ }
135
+
136
+ @media (min-width: 1024px) {
137
+ .holder {
138
+ flex-direction: row;
139
+ align-items: flex-start;
140
+ justify-content: space-between;
141
+ gap: 64px;
142
+ }
143
+ }
144
+
145
+ .headline {
146
+ flex: 1 1 50%;
147
+ max-width: 620px;
148
+ }
149
+
150
+ .headline h2 {
151
+ font-family: "Inter", sans-serif;
152
+ font-style: normal;
153
+ font-weight: 700;
154
+ font-size: 36px !important;
155
+ line-height: 44px;
156
+ letter-spacing: 0.5008px;
157
+ color: #00060a;
158
+ margin: 0 !important;
159
+ padding: 0 !important;
160
+ border-top: none !important;
161
+ }
162
+
163
+ .text-block {
164
+ flex: 1 1 50%;
165
+ max-width: 620px;
166
+ display: flex;
167
+ flex-direction: column;
168
+ gap: 24px;
169
+ }
170
+
171
+ .quote-text {
172
+ font-family: "Inter", sans-serif;
173
+ font-style: normal;
174
+ font-weight: 400;
175
+ font-size: 16px;
176
+ line-height: 24px;
177
+ letter-spacing: 0.5px;
178
+ color: #00060a;
179
+ min-height: 72px;
180
+ }
181
+
182
+ .divider {
183
+ width: 100%;
184
+ height: 1px;
185
+ background: #ccd9e2;
186
+ }
187
+
188
+ .frame-469 {
189
+ display: flex;
190
+ flex-direction: row;
191
+ align-items: center;
192
+ justify-content: space-between;
193
+ gap: 16px;
194
+ width: 100%;
195
+ }
196
+
197
+ .frame-468 {
198
+ display: flex;
199
+ flex-direction: column;
200
+ align-items: flex-start;
201
+ gap: 8px;
202
+ flex-grow: 1;
203
+ }
204
+
205
+ .author-name {
206
+ font-family: "Inter", sans-serif;
207
+ font-style: normal;
208
+ font-weight: 700;
209
+ font-size: 16px;
210
+ line-height: 24px;
211
+ letter-spacing: 0.5px;
212
+ color: #00060a;
213
+ }
214
+
215
+ .author-role {
216
+ font-family: "Inter", sans-serif;
217
+ font-style: normal;
218
+ font-weight: 400;
219
+ font-size: 16px;
220
+ line-height: 24px;
221
+ letter-spacing: 0.5px;
222
+ color: #00060a;
223
+ }
224
+
225
+ .sliders {
226
+ display: flex;
227
+ flex-direction: row;
228
+ align-items: center;
229
+ gap: 24px;
230
+ flex-shrink: 0;
231
+ }
232
+
233
+ .nav-button {
234
+ display: flex !important;
235
+ flex-direction: row !important;
236
+ justify-content: center !important;
237
+ align-items: center !important;
238
+ padding: 0 !important;
239
+ width: 48px !important;
240
+ min-width: 48px !important;
241
+ max-width: 48px !important;
242
+ height: 48px !important;
243
+ min-height: 48px !important;
244
+ max-height: 48px !important;
245
+ background: #004170 !important;
246
+ box-shadow:
247
+ 0px 24px 48px -8px rgba(62, 52, 69, 0.12),
248
+ 0px 2px 4px rgba(62, 52, 69, 0.04) !important;
249
+ border-radius: 999px !important;
250
+ border: none !important;
251
+ cursor: pointer !important;
252
+ transition: background-color 0.2s ease !important;
253
+ box-sizing: border-box !important;
254
+ }
255
+
256
+ .nav-button:hover {
257
+ background: #002e52;
258
+ }
259
+
260
+ .nav-button i {
261
+ color: #ffffff;
262
+ font-size: 24px;
263
+ line-height: 1;
264
+ }
265
+ </style>
package/src/index.js CHANGED
@@ -13,6 +13,16 @@ import CookieSettings from "./components/CookieSettings.vue";
13
13
  import NotFound from "./components/NotFound.vue";
14
14
  import DataTable from "./components/DataTable.vue";
15
15
  import Tutorial from "./components/Tutorial.vue";
16
+ import ImageElement from "./components/ImageElement.vue";
17
+ import ImageGallery from "./components/ImageGallery.vue";
18
+ import ImageCarousel from "./components/ImageCarousel.vue";
19
+ import SingleTweet from "./components/SingleTweet.vue";
20
+ import BlogPost from "./components/BlogPost.vue";
21
+ import TagList from "./components/TagList.vue";
22
+ import BlogList from "./components/BlogList.vue";
23
+ import TeamPage from "./components/TeamPage.vue";
24
+ import SectionHeader from "./components/SectionHeader.vue";
25
+ import TestimonialsSection from "./components/TestimonialsSection.vue";
16
26
  import Layout from "./Layout.vue";
17
27
  import "./style.css";
18
28
 
@@ -34,6 +44,17 @@ export default {
34
44
  app.component("NotFound", NotFound);
35
45
  app.component("DataTable", DataTable);
36
46
  app.component("Tutorial", Tutorial);
47
+ app.component("ImageElement", ImageElement);
48
+ app.component("ImageGallery", ImageGallery);
49
+ app.component("GalleryGrid", ImageGallery);
50
+ app.component("ImageCarousel", ImageCarousel);
51
+ app.component("SingleTweet", SingleTweet);
52
+ app.component("BlogPost", BlogPost);
53
+ app.component("TagList", TagList);
54
+ app.component("BlogList", BlogList);
55
+ app.component("TeamPage", TeamPage);
56
+ app.component("SectionHeader", SectionHeader);
57
+ app.component("TestimonialsSection", TestimonialsSection);
37
58
 
38
59
  router.onAfterRouteChanged = () => {
39
60
  if (!import.meta.env.SSR) {