Skip to content

Commit 849302d

Browse files
docs(figma): merge free and pro kits (#4707)
Co-authored-by: Benjamin Canac <[email protected]>
1 parent 0d63fc1 commit 849302d

21 files changed

+110
-261
lines changed

docs/app/pages/figma.vue

Lines changed: 63 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,86 @@
11
<script setup lang="ts">
22
import { animate } from 'motion-v'
3+
import { joinURL } from 'ufo'
34
45
const { data: page } = await useAsyncData('figma', () => queryCollection('figma').first())
56
if (!page.value) {
67
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
78
}
89
10+
const { url } = useSiteConfig()
11+
912
useSeoMeta({
1013
title: page.value.title,
1114
description: page.value.description,
1215
ogTitle: page.value.title,
13-
ogDescription: page.value.description
14-
})
15-
16-
defineOgImageComponent('Docs', {
17-
headline: 'Community'
16+
ogDescription: page.value.description,
17+
ogImage: joinURL(url, '/figma/og-image.png')
1818
})
1919
2020
const video = ref<HTMLVideoElement | null>(null)
2121
const played = ref(false)
2222
23+
const { width: windowWidth } = useWindowSize()
24+
const isMobile = computed(() => windowWidth.value < 768)
25+
2326
onMounted(async () => {
24-
// Animate cursors
2527
await new Promise(resolve => setTimeout(resolve, 1000))
2628
const figmaWordPosition = document.querySelector('#figma')?.getBoundingClientRect()
2729
const nuxtWordPosition = document.querySelector('#nuxt')?.getBoundingClientRect()
2830
const initialScrollX = window.scrollX
2931
const initialScrollY = window.scrollY
3032
3133
if (figmaWordPosition && nuxtWordPosition) {
32-
const cursor1Sequence = async () => {
33-
await animate('#cursor1', { left: Math.round(Math.random() * window.outerWidth), top: Math.round(Math.random() * window.outerHeight) }, { duration: 0.1 }).finished
34-
await animate('#cursor1', { opacity: 1 }, { duration: 0.3 }).finished
35-
await animate('#cursor1', {
36-
left: Math.round(figmaWordPosition.left + initialScrollX + figmaWordPosition.width / 2),
37-
top: Math.round(figmaWordPosition.top + initialScrollY - figmaWordPosition.height / 4)
38-
}, { duration: 1.5, delay: 0.2, ease: 'easeInOut' }).finished
39-
await animate('#cursor1', { scale: 0.8 }, { duration: 0.1, ease: 'easeOut' }).finished
40-
await animate('#cursor1', { scale: 1 }, { duration: 0.1, ease: 'easeOut' }).finished
41-
await animate('#figma', { color: 'var(--ui-info)' }, { duration: 0.3, ease: 'easeOut' }).finished
42-
await animate('#cursor1', {
43-
left: Math.round(figmaWordPosition.left + initialScrollX + figmaWordPosition.width),
44-
top: Math.round(figmaWordPosition.top + initialScrollY)
45-
}, { duration: 0.6, ease: 'easeInOut' }).finished
46-
}
34+
const createCursorSequence = async (
35+
cursorId: string,
36+
targetWord: DOMRect,
37+
targetColor: string,
38+
wordId: string,
39+
delay: number = 0
40+
) => {
41+
const maxWidth = isMobile.value ? windowWidth.value * 0.8 : window.outerWidth
42+
const maxHeight = isMobile.value ? window.innerHeight * 0.6 : window.outerHeight
43+
44+
await animate(cursorId, {
45+
left: Math.round(Math.random() * maxWidth),
46+
top: Math.round(Math.random() * maxHeight)
47+
}, { duration: 0.1, delay }).finished
48+
49+
await animate(cursorId, { opacity: 1 }, { duration: 0.3 }).finished
4750
48-
const cursor2Sequence = async () => {
49-
await animate('#cursor2', { left: Math.round(Math.random() * window.outerWidth), top: Math.round(Math.random() * window.outerHeight) }, { duration: 0.1, delay: 0.6 }).finished
50-
await animate('#cursor2', { opacity: 1 }, { duration: 0.3 }).finished
51-
await animate('#cursor2', {
52-
left: Math.round(nuxtWordPosition.left + initialScrollX + nuxtWordPosition.width / 2),
53-
top: Math.round(nuxtWordPosition.top + initialScrollY - nuxtWordPosition.height / 4)
54-
}, { duration: 1.5, delay: 0.2, ease: 'easeInOut' }).finished
55-
await animate('#cursor2', { scale: 0.8 }, { duration: 0.1, ease: 'easeOut' }).finished
56-
await animate('#cursor2', { scale: 1 }, { duration: 0.1, ease: 'easeOut' }).finished
57-
await animate('#nuxt', { color: 'var(--ui-success)' }, { duration: 0.3, ease: 'easeOut' }).finished
58-
await animate('#cursor2', {
59-
left: Math.round(nuxtWordPosition.left + initialScrollX + nuxtWordPosition.width),
60-
top: Math.round(nuxtWordPosition.top + initialScrollY)
61-
}, { duration: 0.6, ease: 'easeInOut' }).finished
51+
const clickPositionX = isMobile.value
52+
? Math.round(targetWord.left + initialScrollX + targetWord.width * 0.5)
53+
: Math.round(targetWord.left + initialScrollX + targetWord.width / 2)
54+
const clickPositionY = isMobile.value
55+
? Math.round(targetWord.top + initialScrollY - targetWord.height / 0.7)
56+
: Math.round(targetWord.top + initialScrollY - targetWord.height / 1.2)
57+
58+
await animate(cursorId, {
59+
left: clickPositionX,
60+
top: clickPositionY
61+
}, { duration: 1, delay: 0.2, ease: 'easeInOut' }).finished
62+
63+
await animate(cursorId, { scale: 0.8 }, { duration: 0.1, ease: 'easeOut' }).finished
64+
await animate(cursorId, { scale: 1 }, { duration: 0.1, ease: 'easeOut' }).finished
65+
await animate(wordId, { color: targetColor }, { duration: 0.3, ease: 'easeOut' }).finished
66+
67+
const finalPositionX = isMobile.value
68+
? Math.round(targetWord.left + initialScrollX + targetWord.width * 1)
69+
: Math.round(targetWord.left + initialScrollX + targetWord.width)
70+
const finalPositionY = isMobile.value
71+
? Math.round(targetWord.top + initialScrollY + targetWord.height * -1.2)
72+
: Math.round(targetWord.top + initialScrollY - targetWord.height / 2)
73+
74+
await animate(cursorId, {
75+
left: finalPositionX,
76+
top: finalPositionY
77+
}, { duration: 0.5, ease: 'easeInOut' }).finished
6278
}
6379
64-
await Promise.all([cursor1Sequence(), cursor2Sequence()])
80+
await Promise.all([
81+
createCursorSequence('#cursor1', figmaWordPosition, 'var(--ui-info)', '#figma'),
82+
createCursorSequence('#cursor2', nuxtWordPosition, 'var(--ui-success)', '#nuxt', 0.5)
83+
])
6584
}
6685
})
6786
</script>
@@ -148,7 +167,8 @@ onMounted(async () => {
148167
:ui="{
149168
container: 'lg:grid-cols-0 !gap-0 px-4 sm:px-6 lg:px-8',
150169
wrapper: 'grid grid-cols-1 lg:grid-cols-2',
151-
description: 'lg:mt-0' }"
170+
description: 'mt-2'
171+
}"
152172
orientation="horizontal"
153173
class="rounded-none bg-gradient-to-b from-elevated/50 to-default"
154174
>
@@ -174,20 +194,10 @@ onMounted(async () => {
174194
</UTabs>
175195
</UPageSection>
176196
<UPageSection v-bind="page.section2" orientation="horizontal" :ui="{ container: 'py-16 sm:py-16 lg:py-16' }">
177-
<NuxtImg
178-
v-if="page.section2.image"
179-
v-bind="page.section2.image"
180-
class="w-full h-auto rounded-lg"
181-
loading="lazy"
182-
/>
197+
<NuxtImg v-if="page.section2.image" v-bind="page.section2.image" class="w-full h-auto rounded-lg" loading="lazy" />
183198
</UPageSection>
184199
<UPageSection v-bind="page.section3" orientation="horizontal" :ui="{ container: 'py-16 sm:pt-16 lg:pt-16' }">
185-
<NuxtImg
186-
v-if="page.section3.image"
187-
v-bind="page.section3.image"
188-
class="w-full h-auto rounded-lg"
189-
loading="lazy"
190-
/>
200+
<NuxtImg v-if="page.section3.image" v-bind="page.section3.image" class="w-full h-auto rounded-lg" loading="lazy" />
191201
</UPageSection>
192202
<USeparator />
193203
<UPageSection
@@ -207,12 +217,7 @@ onMounted(async () => {
207217
<div aria-hidden="true" class="absolute z-[-1] border-x border-default inset-0 mx-4 sm:mx-6 lg:mx-8" />
208218
<ul class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 items-start justify-center border border-default border-b-0 sm:divide-x divide-y lg:divide-y-0 divide-default">
209219
<li v-for="(step, index) in page?.section4.steps" :key="step.title" class="flex flex-col gap-y-4 justify-start group h-full p-4">
210-
<NuxtImg
211-
v-if="step.image"
212-
v-bind="step.image"
213-
class="rounded-sm"
214-
loading="lazy"
215-
/>
220+
<NuxtImg v-if="step.image" v-bind="step.image" class="rounded-sm" loading="lazy" />
216221
<div>
217222
<h2 class="font-semibold inline-flex items-center gap-x-1">
218223
<UBadge :label="index + 1" size="sm" color="neutral" variant="subtle" class="rounded-full tabular-nums" /> {{ step.title }}
@@ -225,77 +230,15 @@ onMounted(async () => {
225230
</ul>
226231
</UPageSection>
227232
<UPageSection v-bind="page.features2" :ui="{ container: 'py-16 sm:py-16 lg:py-16', features: 'mt-0' }" class="border-y border-default" />
228-
<UPageSection
229-
v-if="page.pricing"
230-
:title="page.pricing.title"
231-
:description="page.pricing.description"
232-
orientation="vertical"
233-
:ui="{
234-
title: 'sm:text-left',
235-
description: 'sm:text-left',
236-
links: 'sm:justify-start',
237-
container: 'relative !pb-0',
238-
wrapper: 'sm:pl-8'
239-
}"
240-
>
241-
<div aria-hidden="true" class="absolute z-[-1] border-x border-default inset-0 mx-4 sm:mx-6 lg:mx-8" />
242-
<UPricingPlans compact class="-space-x-px">
243-
<UPricingPlan
244-
v-for="(plan, index) in page.pricing.plans"
245-
:key="index"
246-
:title="plan.title"
247-
:description="plan.description"
248-
:price="plan.price"
249-
:discount="plan.discount"
250-
:billing-period="plan.billing_period"
251-
:billing-cycle="plan.billing_cycle"
252-
:highlight="plan.highlight"
253-
:features="plan.features"
254-
:button="plan.button"
255-
:terms="plan.terms"
256-
class="rounded-none"
257-
:class="plan.class"
258-
>
259-
<template #features>
260-
<li v-for="(feature, i) in plan.features" :key="i" class="flex items-center gap-2 min-w-0">
261-
<UIcon name="i-lucide-circle-check" class="size-5 shrink-0 text-primary" />
262-
<MDC :value="feature" unwrap="p" tag="span" class="text-sm truncate text-accented" :cache-key="`figma-pricing-plan-${index}-feature-${i}`" />
263-
</li>
264-
</template>
265-
<template #button>
266-
<div class="flex flex-col w-full items-center gap-2">
267-
<UButton v-bind="plan.button" block size="lg" />
268-
<UButton
269-
v-if="plan.extraButton"
270-
v-bind="plan.extraButton"
271-
block
272-
size="lg"
273-
variant="outline"
274-
color="neutral"
275-
/>
276-
</div>
277-
</template>
278-
</UPricingPlan>
279-
</UPricingPlans>
280-
</UPageSection>
233+
281234
<UPageCTA v-if="page.customers" :title="page.customers.title" :ui="{ title: '!text-base font-medium', container: 'sm:py-12 sm:gap-8' }" variant="outline" class="rounded-none">
282235
<UPageMarquee pause-on-hover :ui="{ root: '[--duration:40s]' }">
283-
<img
284-
v-for="(logo, index) in page.customers.items"
285-
:key="index"
286-
v-bind="logo"
287-
class="h-6 shrink-0 max-w-[140px] filter invert dark:invert-0"
288-
loading="lazy"
289-
>
236+
<img v-for="(logo, index) in page.customers.items" :key="index" v-bind="logo" class="h-6 shrink-0 max-w-[140px] filter invert dark:invert-0" loading="lazy">
290237
</UPageMarquee>
291238
</UPageCTA>
292239
<UPageSection v-bind="page.faq" :ui="{ container: 'relative' }">
293240
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-default inset-0 mx-4 sm:mx-6 lg:mx-8" />
294-
<UPageAccordion
295-
multiple
296-
:items="(page.faq.items as any[])"
297-
class="max-w-4xl mx-auto"
298-
>
241+
<UPageAccordion multiple :items="(page.faq.items as any[])" class="max-w-4xl mx-auto">
299242
<template #body="{ item, index }">
300243
<MDC :value="item.content" unwrap="p" :cache-key="`figma-faq-${index}-content`" />
301244
</template>

docs/content.config.ts

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -145,24 +145,6 @@ export const collections = {
145145
image: Image
146146
}))
147147
}),
148-
pricing: z.object({
149-
title: z.string(),
150-
description: z.string(),
151-
plans: z.array(z.object({
152-
title: z.string(),
153-
description: z.string(),
154-
price: z.string(),
155-
discount: z.string().optional(),
156-
billing_period: z.string().optional(),
157-
billing_cycle: z.string().optional(),
158-
highlight: z.boolean().optional(),
159-
class: z.string().optional(),
160-
features: z.array(z.string()),
161-
terms: z.string().optional(),
162-
button: Button.optional(),
163-
extraButton: Button.optional()
164-
}))
165-
}),
166148
customers: z.object({
167149
title: z.string(),
168150
items: z.array(z.object({

0 commit comments

Comments
 (0)