@hyvor/design 2.1.8-beta.2 → 2.1.8-beta.3
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/dist/marketing/AllFeaturesAccordion/AllFeaturesAccordion.svelte +251 -0
- package/dist/marketing/AllFeaturesAccordion/AllFeaturesAccordion.svelte.d.ts +23 -0
- package/dist/marketing/AllFeaturesAccordion/AllFeaturesAccordionFeature.svelte +75 -0
- package/dist/marketing/AllFeaturesAccordion/AllFeaturesAccordionFeature.svelte.d.ts +10 -0
- package/dist/marketing/FAQ/FAQ.svelte +233 -0
- package/dist/marketing/FAQ/FAQ.svelte.d.ts +13 -0
- package/dist/marketing/FeatureSplit/FeatureSplit.svelte +325 -0
- package/dist/marketing/FeatureSplit/FeatureSplit.svelte.d.ts +24 -0
- package/dist/marketing/FullTrialSignup/FullTrialSignup.svelte +164 -0
- package/dist/marketing/FullTrialSignup/FullTrialSignup.svelte.d.ts +18 -0
- package/dist/marketing/Hero/Hero.svelte +353 -0
- package/dist/marketing/Hero/Hero.svelte.d.ts +16 -0
- package/dist/marketing/Testimonials/Testimonials.svelte +382 -0
- package/dist/marketing/Testimonials/Testimonials.svelte.d.ts +23 -0
- package/dist/marketing/index.d.ts +7 -0
- package/dist/marketing/index.js +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface TextReview {
|
|
3
|
+
type: 'text';
|
|
4
|
+
name: string;
|
|
5
|
+
role: string;
|
|
6
|
+
quote: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface VideoReview {
|
|
10
|
+
type: 'video';
|
|
11
|
+
name: string;
|
|
12
|
+
role: string;
|
|
13
|
+
videoUrl?: string;
|
|
14
|
+
posterUrl?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type Review = TextReview | VideoReview;
|
|
18
|
+
|
|
19
|
+
interface Props {
|
|
20
|
+
label?: string;
|
|
21
|
+
title?: string;
|
|
22
|
+
reviews: Review[];
|
|
23
|
+
// the reviewer name is set in a handwritten-style font (Caveat, loaded
|
|
24
|
+
// from Bunny Fonts) by default — turn off to use the regular typeface,
|
|
25
|
+
// e.g. if the host page can't reach an external font host
|
|
26
|
+
handwrittenNames?: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
let {
|
|
30
|
+
label = 'Testimonials',
|
|
31
|
+
title = 'Loved by our customers.',
|
|
32
|
+
reviews,
|
|
33
|
+
handwrittenNames = true
|
|
34
|
+
}: Props = $props();
|
|
35
|
+
|
|
36
|
+
// deterministic, non-photographic "identicon" per reviewer name — used as a
|
|
37
|
+
// placeholder avatar when no photo is available for a text review
|
|
38
|
+
function identicon(seed: string) {
|
|
39
|
+
let hash = 0;
|
|
40
|
+
for (let i = 0; i < seed.length; i++) {
|
|
41
|
+
hash = (hash * 31 + seed.charCodeAt(i)) | 0;
|
|
42
|
+
}
|
|
43
|
+
const hue = Math.abs(hash) % 360;
|
|
44
|
+
const cells: { x: number; y: number }[] = [];
|
|
45
|
+
for (let col = 0; col < 3; col++) {
|
|
46
|
+
for (let row = 0; row < 5; row++) {
|
|
47
|
+
const bit = (hash >> (col * 5 + row)) & 1;
|
|
48
|
+
if (!bit) continue;
|
|
49
|
+
cells.push({ x: col, y: row });
|
|
50
|
+
if (col < 2) cells.push({ x: 4 - col, y: row });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
bg: `hsl(${hue} 45% 92%)`,
|
|
55
|
+
fg: `hsl(${hue} 50% 40%)`,
|
|
56
|
+
cells
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let scrollEl: HTMLDivElement | undefined = $state();
|
|
61
|
+
let dragging = $state(false);
|
|
62
|
+
let dragStartX = 0;
|
|
63
|
+
let dragStartScroll = 0;
|
|
64
|
+
|
|
65
|
+
function onPointerDown(e: PointerEvent) {
|
|
66
|
+
if (!scrollEl) return;
|
|
67
|
+
dragging = true;
|
|
68
|
+
dragStartX = e.clientX;
|
|
69
|
+
dragStartScroll = scrollEl.scrollLeft;
|
|
70
|
+
scrollEl.setPointerCapture(e.pointerId);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function onPointerMove(e: PointerEvent) {
|
|
74
|
+
if (!dragging || !scrollEl) return;
|
|
75
|
+
scrollEl.scrollLeft = dragStartScroll - (e.clientX - dragStartX);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function onPointerUp() {
|
|
79
|
+
dragging = false;
|
|
80
|
+
}
|
|
81
|
+
</script>
|
|
82
|
+
|
|
83
|
+
<svelte:head>
|
|
84
|
+
{#if handwrittenNames}
|
|
85
|
+
<link href="https://fonts.bunny.net/css?family=caveat:600,700" rel="stylesheet" />
|
|
86
|
+
{/if}
|
|
87
|
+
</svelte:head>
|
|
88
|
+
|
|
89
|
+
<section class="hds-testimonials" class:handwritten={handwrittenNames}>
|
|
90
|
+
<div class="hds-container head">
|
|
91
|
+
<p class="label">{label}</p>
|
|
92
|
+
<h2>{@html title}</h2>
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
96
|
+
<div
|
|
97
|
+
class="scroll-row"
|
|
98
|
+
class:dragging
|
|
99
|
+
bind:this={scrollEl}
|
|
100
|
+
onpointerdown={onPointerDown}
|
|
101
|
+
onpointermove={onPointerMove}
|
|
102
|
+
onpointerup={onPointerUp}
|
|
103
|
+
onpointerleave={onPointerUp}
|
|
104
|
+
role="region"
|
|
105
|
+
aria-label={label}
|
|
106
|
+
>
|
|
107
|
+
{#each reviews as review}
|
|
108
|
+
{#if review.type === 'text'}
|
|
109
|
+
{@const av = identicon(review.name)}
|
|
110
|
+
<figure class="card text-card hds-box">
|
|
111
|
+
<svg class="avatar" viewBox="0 0 5 5" style="background: {av.bg}" aria-hidden="true">
|
|
112
|
+
{#each av.cells as cell}
|
|
113
|
+
<rect x={cell.x} y={cell.y} width="1" height="1" fill={av.fg} />
|
|
114
|
+
{/each}
|
|
115
|
+
</svg>
|
|
116
|
+
<blockquote>“{review.quote}”</blockquote>
|
|
117
|
+
<figcaption>
|
|
118
|
+
<span class="name">{review.name}</span>
|
|
119
|
+
<span class="role">{review.role}</span>
|
|
120
|
+
</figcaption>
|
|
121
|
+
</figure>
|
|
122
|
+
{:else}
|
|
123
|
+
<figure class="card video-card hds-box">
|
|
124
|
+
<div class="poster">
|
|
125
|
+
<img src={review.posterUrl} alt="" />
|
|
126
|
+
<div class="poster-scrim"></div>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
<div class="video-avatar">
|
|
130
|
+
<img src={review.posterUrl} alt="" />
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
<button class="play-btn" aria-label="Play video testimonial" disabled>
|
|
134
|
+
<svg width="20" height="20" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">
|
|
135
|
+
<path d="M5 3.5v9l8-4.5-8-4.5z" />
|
|
136
|
+
</svg>
|
|
137
|
+
</button>
|
|
138
|
+
|
|
139
|
+
<figcaption>
|
|
140
|
+
<span class="name">{review.name}</span>
|
|
141
|
+
<span class="role">{review.role}</span>
|
|
142
|
+
</figcaption>
|
|
143
|
+
</figure>
|
|
144
|
+
{/if}
|
|
145
|
+
{/each}
|
|
146
|
+
</div>
|
|
147
|
+
</section>
|
|
148
|
+
|
|
149
|
+
<style>
|
|
150
|
+
.hds-testimonials {
|
|
151
|
+
background: var(--accent-lightest);
|
|
152
|
+
padding: 100px 0 96px;
|
|
153
|
+
overflow: hidden;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.head {
|
|
157
|
+
margin-bottom: 44px;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.label {
|
|
161
|
+
font-size: 14px;
|
|
162
|
+
font-weight: 600;
|
|
163
|
+
letter-spacing: 0.09em;
|
|
164
|
+
text-transform: uppercase;
|
|
165
|
+
color: var(--accent);
|
|
166
|
+
margin: 0 0 16px;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
h2 {
|
|
170
|
+
font-size: clamp(30px, 4vw, 44px);
|
|
171
|
+
font-weight: 800;
|
|
172
|
+
letter-spacing: -0.02em;
|
|
173
|
+
line-height: 1.15;
|
|
174
|
+
color: var(--text);
|
|
175
|
+
margin: 0;
|
|
176
|
+
font-family: var(--font-serif);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.scroll-row {
|
|
180
|
+
display: flex;
|
|
181
|
+
align-items: stretch;
|
|
182
|
+
gap: 20px;
|
|
183
|
+
overflow-x: auto;
|
|
184
|
+
/* explicit, not left to default — a lone overflow-x: auto silently
|
|
185
|
+
forces overflow-y to auto too (per spec, when only one axis is
|
|
186
|
+
'visible'), which was clipping each card's box-shadow into a hard
|
|
187
|
+
line at the top/bottom of the row instead of letting it fade out */
|
|
188
|
+
overflow-y: visible;
|
|
189
|
+
scroll-snap-type: x proximity;
|
|
190
|
+
cursor: grab;
|
|
191
|
+
/* top/bottom padding must clear --box-shadow's blur radius, or the
|
|
192
|
+
shadow still gets clipped by the row's own padding-box edge */
|
|
193
|
+
padding: 32px 15px 36px max(15px, calc((100vw - 1000px) / 2));
|
|
194
|
+
scrollbar-width: none;
|
|
195
|
+
-webkit-overflow-scrolling: touch;
|
|
196
|
+
touch-action: pan-y;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.scroll-row.dragging {
|
|
200
|
+
cursor: grabbing;
|
|
201
|
+
scroll-snap-type: none;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.scroll-row::-webkit-scrollbar {
|
|
205
|
+
display: none;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.card {
|
|
209
|
+
position: relative;
|
|
210
|
+
flex: 0 0 auto;
|
|
211
|
+
width: 320px;
|
|
212
|
+
height: 440px;
|
|
213
|
+
margin: 0;
|
|
214
|
+
box-sizing: border-box;
|
|
215
|
+
scroll-snap-align: start;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.text-card {
|
|
219
|
+
padding: 28px;
|
|
220
|
+
display: flex;
|
|
221
|
+
flex-direction: column;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.avatar {
|
|
225
|
+
width: 46px;
|
|
226
|
+
height: 46px;
|
|
227
|
+
border-radius: 50%;
|
|
228
|
+
flex-shrink: 0;
|
|
229
|
+
display: block;
|
|
230
|
+
shape-rendering: crispEdges;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
blockquote {
|
|
234
|
+
font-size: 16px;
|
|
235
|
+
line-height: 1.7;
|
|
236
|
+
color: var(--text);
|
|
237
|
+
margin: 20px 0 0;
|
|
238
|
+
flex: 1;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.text-card figcaption {
|
|
242
|
+
display: flex;
|
|
243
|
+
flex-direction: column;
|
|
244
|
+
gap: 0;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.name {
|
|
248
|
+
font-size: 16px;
|
|
249
|
+
font-weight: 600;
|
|
250
|
+
color: var(--text);
|
|
251
|
+
line-height: 1.2;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.handwritten .name {
|
|
255
|
+
font-family: 'Caveat', cursive;
|
|
256
|
+
font-size: 28px;
|
|
257
|
+
font-weight: 600;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.role {
|
|
261
|
+
font-size: 13px;
|
|
262
|
+
color: var(--text-light);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.video-card {
|
|
266
|
+
width: 280px;
|
|
267
|
+
overflow: hidden;
|
|
268
|
+
padding: 0;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.poster {
|
|
272
|
+
position: absolute;
|
|
273
|
+
inset: 0;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.poster img {
|
|
277
|
+
width: 100%;
|
|
278
|
+
height: 100%;
|
|
279
|
+
object-fit: cover;
|
|
280
|
+
display: block;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/* even out contrast across whatever poster photo lands here, so the
|
|
284
|
+
play button and captions stay legible */
|
|
285
|
+
.poster-scrim {
|
|
286
|
+
position: absolute;
|
|
287
|
+
inset: 0;
|
|
288
|
+
background: linear-gradient(160deg, rgba(20, 14, 12, 0.45), rgba(20, 14, 12, 0.65));
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.video-avatar {
|
|
292
|
+
position: absolute;
|
|
293
|
+
top: 16px;
|
|
294
|
+
left: 16px;
|
|
295
|
+
width: 40px;
|
|
296
|
+
height: 40px;
|
|
297
|
+
border-radius: 50%;
|
|
298
|
+
overflow: hidden;
|
|
299
|
+
box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.85);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.video-avatar img {
|
|
303
|
+
width: 100%;
|
|
304
|
+
height: 100%;
|
|
305
|
+
object-fit: cover;
|
|
306
|
+
display: block;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.play-btn {
|
|
310
|
+
position: absolute;
|
|
311
|
+
top: 50%;
|
|
312
|
+
left: 50%;
|
|
313
|
+
transform: translate(-50%, -50%);
|
|
314
|
+
width: 56px;
|
|
315
|
+
height: 56px;
|
|
316
|
+
border-radius: 50%;
|
|
317
|
+
background: rgba(255, 255, 255, 0.18);
|
|
318
|
+
backdrop-filter: blur(6px);
|
|
319
|
+
-webkit-backdrop-filter: blur(6px);
|
|
320
|
+
border: 1px solid rgba(255, 255, 255, 0.4);
|
|
321
|
+
color: #fff;
|
|
322
|
+
display: flex;
|
|
323
|
+
align-items: center;
|
|
324
|
+
justify-content: center;
|
|
325
|
+
cursor: default;
|
|
326
|
+
transition:
|
|
327
|
+
transform 0.2s,
|
|
328
|
+
background 0.2s;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.play-btn:not(:disabled):hover {
|
|
332
|
+
transform: translate(-50%, -50%) scale(1.08);
|
|
333
|
+
background: rgba(255, 255, 255, 0.28);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.play-btn svg {
|
|
337
|
+
margin-left: 3px;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.video-card figcaption {
|
|
341
|
+
position: absolute;
|
|
342
|
+
left: 0;
|
|
343
|
+
right: 0;
|
|
344
|
+
bottom: 0;
|
|
345
|
+
padding: 40px 20px 20px;
|
|
346
|
+
background: linear-gradient(to top, rgba(0, 0, 0, 0.75), transparent);
|
|
347
|
+
display: flex;
|
|
348
|
+
flex-direction: column;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.video-card .name {
|
|
352
|
+
color: #fff;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
.video-card .role {
|
|
356
|
+
color: rgba(255, 255, 255, 0.75);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
@media (max-width: 600px) {
|
|
360
|
+
/* keep in step with the wider .hds-container gutter set globally for
|
|
361
|
+
the host page at this same breakpoint */
|
|
362
|
+
.scroll-row {
|
|
363
|
+
padding: 32px 20px 36px max(20px, calc((100vw - 1000px) / 2));
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
@media (max-width: 768px) {
|
|
368
|
+
.head {
|
|
369
|
+
text-align: center;
|
|
370
|
+
margin-bottom: 32px;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
.card {
|
|
374
|
+
width: 280px;
|
|
375
|
+
height: 400px;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
.video-card {
|
|
379
|
+
width: 240px;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
</style>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
interface TextReview {
|
|
2
|
+
type: 'text';
|
|
3
|
+
name: string;
|
|
4
|
+
role: string;
|
|
5
|
+
quote: string;
|
|
6
|
+
}
|
|
7
|
+
interface VideoReview {
|
|
8
|
+
type: 'video';
|
|
9
|
+
name: string;
|
|
10
|
+
role: string;
|
|
11
|
+
videoUrl?: string;
|
|
12
|
+
posterUrl?: string;
|
|
13
|
+
}
|
|
14
|
+
type Review = TextReview | VideoReview;
|
|
15
|
+
interface Props {
|
|
16
|
+
label?: string;
|
|
17
|
+
title?: string;
|
|
18
|
+
reviews: Review[];
|
|
19
|
+
handwrittenNames?: boolean;
|
|
20
|
+
}
|
|
21
|
+
declare const Testimonials: import("svelte").Component<Props, {}, "">;
|
|
22
|
+
type Testimonials = ReturnType<typeof Testimonials>;
|
|
23
|
+
export default Testimonials;
|
|
@@ -12,3 +12,10 @@ export type { NavSectionConfig, NavConfig, NavPageConfig, NavFoldingSectionConfi
|
|
|
12
12
|
export { default as Footer } from './Footer/Footer.svelte';
|
|
13
13
|
export { default as FooterLinkList } from './Footer/FooterLinkList.svelte';
|
|
14
14
|
export { default as Document } from './Document/Document.svelte';
|
|
15
|
+
export { default as Hero } from './Hero/Hero.svelte';
|
|
16
|
+
export { default as FeatureSplit } from './FeatureSplit/FeatureSplit.svelte';
|
|
17
|
+
export { default as Testimonials } from './Testimonials/Testimonials.svelte';
|
|
18
|
+
export { default as FullTrialSignup } from './FullTrialSignup/FullTrialSignup.svelte';
|
|
19
|
+
export { default as AllFeaturesAccordion } from './AllFeaturesAccordion/AllFeaturesAccordion.svelte';
|
|
20
|
+
export { default as AllFeaturesAccordionFeature } from './AllFeaturesAccordion/AllFeaturesAccordionFeature.svelte';
|
|
21
|
+
export { default as FAQ } from './FAQ/FAQ.svelte';
|
package/dist/marketing/index.js
CHANGED
|
@@ -10,3 +10,10 @@ export { loadDocsPage } from './Docs/fulldocs.js';
|
|
|
10
10
|
export { default as Footer } from './Footer/Footer.svelte';
|
|
11
11
|
export { default as FooterLinkList } from './Footer/FooterLinkList.svelte';
|
|
12
12
|
export { default as Document } from './Document/Document.svelte';
|
|
13
|
+
export { default as Hero } from './Hero/Hero.svelte';
|
|
14
|
+
export { default as FeatureSplit } from './FeatureSplit/FeatureSplit.svelte';
|
|
15
|
+
export { default as Testimonials } from './Testimonials/Testimonials.svelte';
|
|
16
|
+
export { default as FullTrialSignup } from './FullTrialSignup/FullTrialSignup.svelte';
|
|
17
|
+
export { default as AllFeaturesAccordion } from './AllFeaturesAccordion/AllFeaturesAccordion.svelte';
|
|
18
|
+
export { default as AllFeaturesAccordionFeature } from './AllFeaturesAccordion/AllFeaturesAccordionFeature.svelte';
|
|
19
|
+
export { default as FAQ } from './FAQ/FAQ.svelte';
|