docs: various marketing improvements (#3400)
Co-authored-by: HugoRCD <hugo.richard@epitech.eu>
@@ -6,6 +6,7 @@ const props = defineProps<{
|
|||||||
links: NavigationMenuItem[]
|
links: NavigationMenuItem[]
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
const config = useRuntimeConfig().public
|
const config = useRuntimeConfig().public
|
||||||
const { module } = useSharedData()
|
const { module } = useSharedData()
|
||||||
|
|
||||||
@@ -21,7 +22,8 @@ onMounted(() => {
|
|||||||
|
|
||||||
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
|
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
|
||||||
|
|
||||||
const items = computed(() => props.links.map(({ icon, ...link }) => link))
|
const desktopLinks = computed(() => props.links.map(({ icon, ...link }) => link))
|
||||||
|
const mobileLinks = computed(() => props.links.map(link => ({ ...link, defaultOpen: link.children && route.path.startsWith(link.to as string) })))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -53,7 +55,7 @@ const items = computed(() => props.links.map(({ icon, ...link }) => link))
|
|||||||
</UDropdownMenu>
|
</UDropdownMenu>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<UNavigationMenu :items="items" variant="link" />
|
<UNavigationMenu :items="desktopLinks" variant="link" />
|
||||||
|
|
||||||
<template #right>
|
<template #right>
|
||||||
<ThemePicker />
|
<ThemePicker />
|
||||||
@@ -76,7 +78,7 @@ const items = computed(() => props.links.map(({ icon, ...link }) => link))
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #body>
|
<template #body>
|
||||||
<UNavigationMenu orientation="vertical" :items="links" class="-mx-2.5" />
|
<UNavigationMenu orientation="vertical" :items="mobileLinks" class="-mx-2.5" default-open />
|
||||||
|
|
||||||
<USeparator type="dashed" class="mt-4 mb-6" />
|
<USeparator type="dashed" class="mt-4 mb-6" />
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="relative">
|
|
||||||
<UPageCard
|
|
||||||
variant="subtle"
|
|
||||||
class="rounded-[calc(var(--ui-radius)*6)]"
|
|
||||||
>
|
|
||||||
<video
|
|
||||||
class="rounded-[calc(var(--ui-radius)*2)]"
|
|
||||||
preload="none"
|
|
||||||
poster="https://res.cloudinary.com/nuxt/video/upload/so_3.3/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.jpg"
|
|
||||||
:controls="true"
|
|
||||||
>
|
|
||||||
<source
|
|
||||||
src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.webm"
|
|
||||||
type="video/webm"
|
|
||||||
>
|
|
||||||
<source
|
|
||||||
src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.mp4"
|
|
||||||
type="video/mp4"
|
|
||||||
>
|
|
||||||
<source
|
|
||||||
src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.ogg"
|
|
||||||
type="video/ogg"
|
|
||||||
>
|
|
||||||
</video>
|
|
||||||
</UPageCard>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@@ -10,6 +10,7 @@ export function useLinks() {
|
|||||||
label: 'Components',
|
label: 'Components',
|
||||||
icon: 'i-lucide-square-code',
|
icon: 'i-lucide-square-code',
|
||||||
to: '/components',
|
to: '/components',
|
||||||
|
active: route.path === '/components',
|
||||||
children: [{
|
children: [{
|
||||||
label: 'Layout',
|
label: 'Layout',
|
||||||
to: '/components#layout',
|
to: '/components#layout',
|
||||||
|
|||||||
@@ -54,6 +54,22 @@ const categories = [{
|
|||||||
title: 'Overlay',
|
title: 'Overlay',
|
||||||
description: 'Floating UI elements like modals, dialogs, tooltips, popovers, and other components that overlay the main content.'
|
description: 'Floating UI elements like modals, dialogs, tooltips, popovers, and other components that overlay the main content.'
|
||||||
}]
|
}]
|
||||||
|
|
||||||
|
const { y } = useWindowScroll()
|
||||||
|
onMounted(() => {
|
||||||
|
const stickyElements = document.querySelectorAll('[data-track-sticky]') as NodeListOf<HTMLElement>
|
||||||
|
watch(y, () => {
|
||||||
|
stickyElements.forEach((el) => {
|
||||||
|
const rect = el.getBoundingClientRect()
|
||||||
|
const topComputed = Number.parseInt(window.getComputedStyle(el).top || '0', 10)
|
||||||
|
if (rect.top <= topComputed) {
|
||||||
|
el.dataset.stuck = ''
|
||||||
|
} else {
|
||||||
|
delete el.dataset.stuck
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, { immediate: true })
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -62,8 +78,9 @@ const categories = [{
|
|||||||
description="Build your Vue or Nuxt application faster with Nuxt UI and Nuxt UI Pro components. Powered by Tailwind CSS and Reka UI, delivering responsive and customizable components."
|
description="Build your Vue or Nuxt application faster with Nuxt UI and Nuxt UI Pro components. Powered by Tailwind CSS and Reka UI, delivering responsive and customizable components."
|
||||||
class="relative"
|
class="relative"
|
||||||
orientation="vertical"
|
orientation="vertical"
|
||||||
:ui="{ title: 'text-balance' }"
|
:ui="{ title: 'text-balance', container: 'relative' }"
|
||||||
>
|
>
|
||||||
|
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
||||||
<template #headline>
|
<template #headline>
|
||||||
<UButton
|
<UButton
|
||||||
to="https://tailwindcss.com"
|
to="https://tailwindcss.com"
|
||||||
@@ -102,24 +119,25 @@ const categories = [{
|
|||||||
</template>
|
</template>
|
||||||
</UPageHero>
|
</UPageHero>
|
||||||
|
|
||||||
<UContainer>
|
<div v-for="category in categories" :key="category.id">
|
||||||
<div v-for="category in categories" :key="category.id">
|
<div data-track-sticky class="group mb-4 sm:mb-6 lg:mb-8 sticky top-[calc(var(--ui-header-height)-1px)] bg-(--ui-bg)/75 backdrop-blur z-[1]">
|
||||||
<div class="mb-4 sm:mb-6 lg:mb-8 sticky top-(--ui-header-height) bg-(--ui-bg)/75 backdrop-blur z-[1] -mx-4 px-4 sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
|
<div class="relative border-y border-(--ui-border) py-4 sm:not-group-[[data-stuck]]:py-6 lg:not-group-[[data-stuck]]:py-8 transition-all duration-300">
|
||||||
<div class="relative border-b border-(--ui-border) py-4 sm:py-6 lg:py-8">
|
<UContainer>
|
||||||
<h2 class="relative text-pretty font-bold text-(--ui-text-highlighted) text-base sm:text-xl lg:text-2xl">
|
<h2 class="relative text-pretty font-bold text-(--ui-text-highlighted) text-base sm:not-group-[[data-stuck]]:text-xl lg:not-group-[[data-stuck]]:text-2xl transition-all duration-300 ">
|
||||||
<a :href="`#${category.id}`" class="group lg:ps-2 lg:-ms-2">
|
<a :href="`#${category.id}`" class="group lg:not-group-[[data-stuck]]:ps-2 lg:not-group-[[data-stuck]]:-ms-2">
|
||||||
<span class="absolute -ms-8 top-1 opacity-0 group-hover:opacity-100 group-focus:opacity-100 p-1 bg-(--ui-bg-elevated) hover:text-(--ui-primary) rounded-[calc(var(--ui-radius)*1.5)] hidden lg:flex text-(--ui-text-muted) transition">
|
<span class="absolute -ms-8 top-1 opacity-0 group-hover:opacity-100 group-focus:opacity-100 p-1 bg-(--ui-bg-elevated) hover:text-(--ui-primary) rounded-[calc(var(--ui-radius)*1.5)] hidden lg:not-group-[[data-stuck]]:flex text-(--ui-text-muted) transition">
|
||||||
<UIcon name="i-lucide-hash" class="size-4 shrink-0" />
|
<UIcon name="i-lucide-hash" class="size-4 shrink-0" />
|
||||||
</span>
|
</span>
|
||||||
{{ category.title }}
|
{{ category.title }}
|
||||||
</a>
|
</a>
|
||||||
</h2>
|
</h2>
|
||||||
<p class="text-pretty text-(--ui-text-muted) text-sm sm:text-base lg:text-lg mt-1 sm:mt-2 line-clamp-1">
|
<p class="text-pretty text-(--ui-text-muted) text-sm sm:not-group-[[data-stuck]]:text-base lg:not-group-[[data-stuck]]:text-lg mt-1 sm:not-group-[[data-stuck]]:mt-2 line-clamp-1 transition-all duration-300">
|
||||||
{{ category.description }}
|
{{ category.description }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</UContainer>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<UContainer>
|
||||||
<UPageGrid :id="category.id" class="xl:grid-cols-4 gap-4 sm:gap-6 lg:gap-8 pb-24 scroll-mt-[calc(97px+var(--ui-header-height))] sm:scroll-mt-[calc(133px+var(--ui-header-height))] lg:scroll-mt-[calc(165px+var(--ui-header-height))]">
|
<UPageGrid :id="category.id" class="xl:grid-cols-4 gap-4 sm:gap-6 lg:gap-8 pb-24 scroll-mt-[calc(97px+var(--ui-header-height))] sm:scroll-mt-[calc(133px+var(--ui-header-height))] lg:scroll-mt-[calc(165px+var(--ui-header-height))]">
|
||||||
<UPageCard
|
<UPageCard
|
||||||
v-for="(component, index) in componentsPerCategory[category.id]"
|
v-for="(component, index) in componentsPerCategory[category.id]"
|
||||||
@@ -149,7 +167,7 @@ const categories = [{
|
|||||||
</div>
|
</div>
|
||||||
</UPageCard>
|
</UPageCard>
|
||||||
</UPageGrid>
|
</UPageGrid>
|
||||||
</div>
|
</UContainer>
|
||||||
</UContainer>
|
</div>
|
||||||
</UMain>
|
</UMain>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -124,7 +124,9 @@ onMounted(async () => {
|
|||||||
</UButton>
|
</UButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div aria-hidden="true" class="absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
<Motion as-child :initial="{ height: 0 }" :animate="{ height: 'auto' }" :transition="{ delay: 0.2, duration: 1 }">
|
||||||
|
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
||||||
|
</Motion>
|
||||||
</UPageHero>
|
</UPageHero>
|
||||||
<UPageSection v-bind="page.features1" :ui="{ container: 'py-16 sm:py-16 lg:py-16', features: 'mt-0' }" class="border-y border-(--ui-border)" />
|
<UPageSection v-bind="page.features1" :ui="{ container: 'py-16 sm:py-16 lg:py-16', features: 'mt-0' }" class="border-y border-(--ui-border)" />
|
||||||
<UPageCTA
|
<UPageCTA
|
||||||
|
|||||||
@@ -7,17 +7,15 @@ pricing:
|
|||||||
freePlan:
|
freePlan:
|
||||||
title: Free in development
|
title: Free in development
|
||||||
description: Try Nuxt UI Pro for free in development, no credit card required. Upgrade when ready to deploy.
|
description: Try Nuxt UI Pro for free in development, no credit card required. Upgrade when ready to deploy.
|
||||||
variant: soft
|
|
||||||
orientation: horizontal
|
orientation: horizontal
|
||||||
button:
|
button:
|
||||||
label: Get started for Free
|
label: Get started for Free
|
||||||
to: '/getting-started/installation/pro/nuxt'
|
to: '/getting-started/installation/pro/nuxt'
|
||||||
color: 'neutral'
|
color: 'neutral'
|
||||||
variant: 'outline'
|
variant: 'subtle'
|
||||||
figma:
|
figma:
|
||||||
title: Figma Kit Pro
|
title: Figma Kit Pro
|
||||||
description: Get all Nuxt UI Pro components in a Figma kit to design your next application before coding. Everything you need, from wire-framing to high-fidelity web integration.
|
description: Get all Nuxt UI Pro components in a Figma kit to design your next application before coding. Everything you need, from wire-framing to high-fidelity web integration.
|
||||||
variant: soft
|
|
||||||
orientation: horizontal
|
orientation: horizontal
|
||||||
price: $149 - $349
|
price: $149 - $349
|
||||||
terms: Solo & Team licenses available.
|
terms: Solo & Team licenses available.
|
||||||
|
|||||||
@@ -2,18 +2,18 @@ title: Build faster with Nuxt UI Pro.
|
|||||||
description: A collection of premium Vue components, composables and utils built on top of Nuxt UI, oriented on structure and layout and designed to be used as building blocks for your application.
|
description: A collection of premium Vue components, composables and utils built on top of Nuxt UI, oriented on structure and layout and designed to be used as building blocks for your application.
|
||||||
hero:
|
hero:
|
||||||
title: Build faster with Nuxt UI [Pro]{class="text-(--ui-primary)"}.
|
title: Build faster with Nuxt UI [Pro]{class="text-(--ui-primary)"}.
|
||||||
description: A collection of premium Vue components, composables and utils built on top of Nuxt UI. :br Focused on structure and layout, these **responsive components** are designed to be the perfect **building blocks for your next idea**.
|
description: A collection of premium Vue components, composables and utils built on top of Nuxt UI. :br Focused on structure and layout, these [responsive components]{class="text-(--ui-text)"} are designed to be the perfect [building blocks for your next idea]{class="text-(--ui-text)"}.
|
||||||
links:
|
links:
|
||||||
|
- label: Buy a license
|
||||||
|
size: xl
|
||||||
|
to: /pro/pricing
|
||||||
|
trailing-icon: i-lucide-arrow-right
|
||||||
- label: Get started
|
- label: Get started
|
||||||
icon: i-lucide-arrow-right
|
|
||||||
trailing: true
|
trailing: true
|
||||||
|
color: neutral
|
||||||
|
variant: ghost
|
||||||
to: /getting-started/installation/pro/nuxt
|
to: /getting-started/installation/pro/nuxt
|
||||||
size: xl
|
size: xl
|
||||||
- label: Purchase a license
|
|
||||||
size: xl
|
|
||||||
color: neutral
|
|
||||||
variant: outline
|
|
||||||
to: /pro/pricing
|
|
||||||
features:
|
features:
|
||||||
title: Create stunning Vue applications faster.
|
title: Create stunning Vue applications faster.
|
||||||
description: Nuxt UI Pro comes packed with powerful features to help you build modern, performant, accessible and responsive Nuxt applications at record speed. From pre-built UI sections to Figma design kits, every detail is crafted to speed up your development and deliver a polished user experience.
|
description: Nuxt UI Pro comes packed with powerful features to help you build modern, performant, accessible and responsive Nuxt applications at record speed. From pre-built UI sections to Figma design kits, every detail is crafted to speed up your development and deliver a polished user experience.
|
||||||
@@ -45,18 +45,30 @@ features:
|
|||||||
- title: Figma Design Kits
|
- title: Figma Design Kits
|
||||||
description: Match your development workflow with Nuxt UI & UI Pro Figma UI kits, ensuring a fast transition from design to code.
|
description: Match your development workflow with Nuxt UI & UI Pro Figma UI kits, ensuring a fast transition from design to code.
|
||||||
icon: i-simple-icons-figma
|
icon: i-simple-icons-figma
|
||||||
authorQuote:
|
testimonial:
|
||||||
quote: Nuxt UI, born from a desire to improve Vue component development, is the go-to library for building modern web interfaces. We aim to provide you with a comprehensive set of tools to create and customize your next UI while maintaining the best developer experience.
|
quote: Nuxt UI has allowed me to develop my SaaS without any prior mockups. The design quality of their components and the intelligence of the DX meant that I was able to try many different layouts for my application until I found the perfect UX for my users. Nuxt UI is the ui-kit I would have dreamed of building myself, and Nuxt UI Pro makes things even easier when you want to go further with your SaaS. Kudos to the team.
|
||||||
user:
|
user:
|
||||||
name: Benjamin Canac
|
name: Benjamin Code
|
||||||
description: Author of Nuxt UI
|
description: YouTuber and Founder
|
||||||
to: https://github.com/benjamincanac
|
to: https://x.com/benjamincode
|
||||||
avatar:
|
avatar:
|
||||||
src: https://github.com/benjamincanac.png
|
src: https://pbs.twimg.com/profile_images/1607353032420769793/I8qQSUfQ_400x400.jpg
|
||||||
|
# authorQuote:
|
||||||
|
# quote: Nuxt UI, born from a desire to improve Vue component development, is the go-to library for building modern web interfaces. We aim to provide you with a comprehensive set of tools to create and customize your next UI while maintaining the best developer experience.
|
||||||
|
# user:
|
||||||
|
# name: Benjamin Canac
|
||||||
|
# description: Author of Nuxt UI
|
||||||
|
# to: https://github.com/benjamincanac
|
||||||
|
# avatar:
|
||||||
|
# src: https://github.com/benjamincanac.png
|
||||||
|
mainSection:
|
||||||
|
title: Meet the [Pro Components]{class="text-(--ui-primary)"}.
|
||||||
|
description: Code with 50+ components and sections of Nuxt UI Pro to build your next application by reducing the amount of code you need to write.
|
||||||
sections:
|
sections:
|
||||||
- title: The freedom to build anything
|
- title: The freedom to build anything
|
||||||
description: Nuxt UI Pro ships with an extensive set of advanced components that cover a wide range of use-cases. Carefully crafted to reduce boilerplate code without sacrificing flexibility.
|
description: Nuxt UI Pro ships with an extensive set of advanced components that cover a wide range of use-cases. Carefully crafted to reduce boilerplate code without sacrificing flexibility.
|
||||||
id: features
|
id: features
|
||||||
|
reverse: true
|
||||||
features:
|
features:
|
||||||
- name: Fully customizable
|
- name: Fully customizable
|
||||||
description: Like Nuxt UI, change the style of any component from your App Config or customize them specifically through the ui prop.
|
description: Like Nuxt UI, change the style of any component from your App Config or customize them specifically through the ui prop.
|
||||||
@@ -99,9 +111,8 @@ sections:
|
|||||||
</UApp>
|
</UApp>
|
||||||
</template>
|
</template>
|
||||||
```
|
```
|
||||||
- title: The flexibility to control your data
|
- title: The flexibility to display your data
|
||||||
description: Although you can use any data source you want, Nuxt UI Pro is fully integrated with Nuxt Content and provides additional features when the module is detected.
|
description: Although you can use any data source you want, Nuxt UI Pro is fully integrated with Nuxt Content and provides additional features when the module is detected.
|
||||||
reverse: true
|
|
||||||
features:
|
features:
|
||||||
- name: 'Write Markdown with ease'
|
- name: 'Write Markdown with ease'
|
||||||
description: Nuxt UI Pro overrides Nuxt Content prose components to make them awesome but also adds new ones like Callout, CodeGroup, Field, etc.
|
description: Nuxt UI Pro overrides Nuxt Content prose components to make them awesome but also adds new ones like Callout, CodeGroup, Field, etc.
|
||||||
@@ -110,7 +121,7 @@ sections:
|
|||||||
description: 'Nuxt UI Pro ships with a ready to use command palette component. No need to setup Algolia DocSearch anymore.'
|
description: 'Nuxt UI Pro ships with a ready to use command palette component. No need to setup Algolia DocSearch anymore.'
|
||||||
icon: i-lucide-search
|
icon: i-lucide-search
|
||||||
links:
|
links:
|
||||||
- label: Nuxt Content integration
|
- label: Nuxt Content Integration
|
||||||
to: /getting-started/content
|
to: /getting-started/content
|
||||||
icon: i-lucide-arrow-right
|
icon: i-lucide-arrow-right
|
||||||
trailing: true
|
trailing: true
|
||||||
@@ -144,10 +155,10 @@ cta:
|
|||||||
title: Start with Nuxt UI Pro today!
|
title: Start with Nuxt UI Pro today!
|
||||||
description: Nuxt UI Pro is free in development, but you need a license to use it in production.
|
description: Nuxt UI Pro is free in development, but you need a license to use it in production.
|
||||||
links:
|
links:
|
||||||
- label: Purchase a license
|
- label: Buy a license
|
||||||
to: '/pro/pricing'
|
to: '/pro/pricing'
|
||||||
icon: i-lucide-shopping-cart
|
trailing-icon: i-lucide-arrow-right
|
||||||
- label: License
|
- label: Get started
|
||||||
to: '/getting-started/license'
|
to: '/getting-started/license'
|
||||||
trailingIcon: i-lucide-circle-help
|
variant: ghost
|
||||||
variant: subtle
|
color: neutral
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import type { FormSubmitEvent } from '@nuxt/ui'
|
import type { FormSubmitEvent } from '@nuxt/ui'
|
||||||
|
import { joinURL } from 'ufo'
|
||||||
|
|
||||||
const title = 'Activate your Nuxt UI Pro License'
|
const title = 'Activate your Nuxt UI Pro License'
|
||||||
const description = 'Enable Nuxt UI Pro in your production projects by activating your license key received by email and get invited to the GitHub private repository.'
|
const description = 'Enable Nuxt UI Pro in your production projects by activating your license key received by email and get invited to the GitHub private repository.'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const { url } = useSiteConfig()
|
||||||
|
|
||||||
useSeoMeta({
|
useSeoMeta({
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
ogTitle: `${title} - Nuxt UI Pro`,
|
ogTitle: `${title} - Nuxt UI Pro`,
|
||||||
ogDescription: description
|
ogDescription: description,
|
||||||
})
|
ogImage: joinURL(url, '/pro/og-image.png')
|
||||||
|
|
||||||
defineOgImageComponent('Docs', {
|
|
||||||
headline: 'Pro'
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
@@ -70,46 +69,52 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<UPageHero headline="License Activation" :title="title" :description="description">
|
<UMain>
|
||||||
<template #top>
|
<UPageHero headline="License Activation" :title="title" :description="description" :ui="{ container: 'relative' }">
|
||||||
<div class="absolute z-[-1] rounded-full bg-(--ui-primary) blur-[300px] size-60 sm:size-80 transform -translate-x-1/2 left-1/2 -translate-y-80" />
|
<template #top>
|
||||||
<StarsBg />
|
<div class="absolute z-[-1] rounded-full bg-(--ui-primary) blur-[300px] size-60 sm:size-80 transform -translate-x-1/2 left-1/2 -translate-y-80" />
|
||||||
</template>
|
<StarsBg />
|
||||||
<div>
|
</template>
|
||||||
<UCard class="lg:w-1/2 m-auto backdrop-blur-sm">
|
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
||||||
<UForm
|
|
||||||
:schema="schema"
|
<div class="lg:border-y border-(--ui-border)">
|
||||||
:validate-on="['blur']"
|
<UCard class="lg:w-1/2 m-auto lg:rounded-none overflow-hidden" variant="outline" :ui="{ footer: 'bg-(--ui-bg-muted)' }">
|
||||||
:state="state"
|
<UForm
|
||||||
class="space-y-4"
|
:schema="schema"
|
||||||
@submit="submit"
|
:validate-on="['blur']"
|
||||||
>
|
:state="state"
|
||||||
<UFormField label="License Key" name="license">
|
class="space-y-4"
|
||||||
<UInput v-model="state.license" autocomplete="off" :ui="{ root: 'flex' }" />
|
@submit="submit"
|
||||||
</UFormField>
|
>
|
||||||
<UFormField label="GitHub Username" name="username">
|
<UFormField label="License Key" name="license">
|
||||||
<UInput v-model="state.username" autocomplete="off" :ui="{ root: 'flex' }" />
|
<UInput v-model="state.license" autocomplete="off" :ui="{ root: 'flex' }" />
|
||||||
</UFormField>
|
</UFormField>
|
||||||
<UButton type="submit" :loading="activating" :disabled="state.license?.length !== 36 || !state.username">
|
<UFormField label="GitHub Username" name="username">
|
||||||
Activate the license
|
<UInput v-model="state.username" autocomplete="off" :ui="{ root: 'flex' }" />
|
||||||
</UButton>
|
</UFormField>
|
||||||
<UAlert v-if="successMessage" color="success" variant="subtle" :title="successMessage">
|
<UButton type="submit" :loading="activating" :disabled="state.license?.length !== 36 || !state.username">
|
||||||
<template #description>
|
Activate the license
|
||||||
The GitHub invitation to <NuxtLink to="https://github.com/nuxt/ui-pro/invitations" external target="_blank" class="font-bold text-primary hover:underline">
|
</UButton>
|
||||||
Nuxt UI Pro repository
|
<UAlert v-if="successMessage" color="success" variant="subtle" :title="successMessage">
|
||||||
</NuxtLink> has been sent and
|
<template #description>
|
||||||
you can now use your license key in your projects, checkout the
|
The GitHub invitation to <NuxtLink to="https://github.com/nuxt/ui-pro/invitations" external target="_blank" class="font-bold text-primary hover:underline">
|
||||||
<NuxtLink class="font-bold underline" to="/pro/getting-started/installation">
|
Nuxt UI Pro repository
|
||||||
installation guide
|
</NuxtLink> has been sent and
|
||||||
</NuxtLink>
|
you can now use your license key in your projects, checkout the
|
||||||
</template>
|
<NuxtLink class="font-bold underline" to="/pro/getting-started/installation">
|
||||||
</UAlert>
|
installation guide
|
||||||
<UAlert v-else-if="errorMessage" color="error" variant="subtle" :title="errorMessage" />
|
</NuxtLink>
|
||||||
</UForm>
|
</template>
|
||||||
</UCard>
|
</UAlert>
|
||||||
<p class="text-sm text-center text-neutral-500 dark:text-neutral-400 my-4">
|
<UAlert v-else-if="errorMessage" color="error" variant="subtle" :title="errorMessage" />
|
||||||
If you purchased a license with multiple seats, activate the license key for each of your team members.
|
</UForm>
|
||||||
</p>
|
<template #footer>
|
||||||
</div>
|
<p class="text-sm text-center text-neutral-500 dark:text-neutral-400">
|
||||||
</UPageHero>
|
If you purchased a license with multiple seats, activate the license key for each member of your team.
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
</UCard>
|
||||||
|
</div>
|
||||||
|
</UPageHero>
|
||||||
|
</UMain>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { joinURL } from 'ufo'
|
||||||
// @ts-expect-error yaml is not typed
|
// @ts-expect-error yaml is not typed
|
||||||
import page from '.content/pro.yml'
|
import page from '.content/pro.yml'
|
||||||
// @ts-expect-error yaml is not typed
|
// @ts-expect-error yaml is not typed
|
||||||
import templatesPage from '.content/templates.yml'
|
import templatesPage from '.content/templates.yml'
|
||||||
|
|
||||||
|
const { url } = useSiteConfig()
|
||||||
|
|
||||||
useSeoMeta({
|
useSeoMeta({
|
||||||
title: page.title,
|
title: page.title,
|
||||||
ogTitle: page.title,
|
ogTitle: page.title,
|
||||||
|
ogImage: joinURL(url, '/pro/og-image.png'),
|
||||||
description: page.description,
|
description: page.description,
|
||||||
ogDescription: page.description
|
ogDescription: page.description
|
||||||
})
|
})
|
||||||
defineOgImageComponent('Docs', {
|
|
||||||
headline: 'Pro'
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -20,7 +21,9 @@ defineOgImageComponent('Docs', {
|
|||||||
<UPageHero
|
<UPageHero
|
||||||
:links="page.hero.links"
|
:links="page.hero.links"
|
||||||
class="relative"
|
class="relative"
|
||||||
orientation="horizontal"
|
:ui="{
|
||||||
|
container: 'relative !pb-0'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
<MDC :value="page.hero.title" unwrap="p" />
|
<MDC :value="page.hero.title" unwrap="p" />
|
||||||
@@ -29,36 +32,81 @@ defineOgImageComponent('Docs', {
|
|||||||
<MDC :value="page.hero.description" unwrap="p" />
|
<MDC :value="page.hero.description" unwrap="p" />
|
||||||
</template>
|
</template>
|
||||||
<template #top>
|
<template #top>
|
||||||
<div class="absolute z-[-1] rounded-full bg-(--ui-primary) blur-[300px] size-60 sm:size-80 transform -translate-x-1/2 left-1/2 -translate-y-80" />
|
|
||||||
<StarsBg />
|
<StarsBg />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<PromotionalVideo />
|
<Motion as-child :initial="{ height: 0 }" :animate="{ height: 'auto' }" :transition="{ delay: 0.2, duration: 1 }">
|
||||||
|
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
||||||
|
</Motion>
|
||||||
|
<Motion as-child :initial="{ opacity: 0 }" :animate="{ opacity: 1 }" :transition="{ delay: 0.6, duration: 0.6 }">
|
||||||
|
<NuxtImg src="/pro/hero.png" width="1374" height="439" alt="Nuxt UI Pro" class="w-full border-t border-x border-(--ui-border) bg-(--ui-bg-muted)" />
|
||||||
|
</Motion>
|
||||||
</UPageHero>
|
</UPageHero>
|
||||||
|
<UPageCTA
|
||||||
|
variant="outline"
|
||||||
|
class="rounded-none"
|
||||||
|
:ui="{
|
||||||
|
container: 'sm:py-12 lg:py-12 sm:gap-4',
|
||||||
|
description: 'sm:text-base'
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<template #description>
|
||||||
|
<Motion :initial="{ opacity: 0, transform: 'translateY(10px)' }" :in-view="{ opacity: 1, transform: 'translateY(0)' }" :in-view-options="{ once: true }" :transition="{ delay: 0.2 }">
|
||||||
|
<MDC :value="page.testimonial.quote" unwrap="p" class="before:content-[open-quote] after:content-[close-quote] " />
|
||||||
|
</Motion>
|
||||||
|
</template>
|
||||||
|
<Motion :initial="{ opacity: 0, transform: 'translateY(10px)' }" :in-view="{ opacity: 1, transform: 'translateY(0)' }" :in-view-options="{ once: true }" :transition="{ delay: 0.3 }">
|
||||||
|
<UUser
|
||||||
|
v-bind="page.testimonial.user"
|
||||||
|
class="justify-center"
|
||||||
|
/>
|
||||||
|
</Motion>
|
||||||
|
</UPageCTA>
|
||||||
<UPageSection
|
<UPageSection
|
||||||
v-bind="page.features"
|
v-bind="page.features"
|
||||||
:ui="{ title: 'text-left', description: 'text-left' }"
|
:ui="{
|
||||||
/>
|
title: 'text-left',
|
||||||
|
description: 'text-left',
|
||||||
|
container: 'relative',
|
||||||
|
wrapper: 'sm:px-8'
|
||||||
|
}"
|
||||||
|
class="border-t border-(--ui-border)"
|
||||||
|
>
|
||||||
|
<Motion as-child :initial="{ height: 0 }" :in-view="{ height: 'auto' }" :transition="{ delay: 0.4, duration: 1 }">
|
||||||
|
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
||||||
|
</Motion>
|
||||||
|
</UPageSection>
|
||||||
|
|
||||||
<UPageCTA
|
<UPageCTA
|
||||||
:description="page.authorQuote.quote"
|
v-if="page.mainSection"
|
||||||
variant="soft"
|
variant="naked"
|
||||||
class="rounded-none"
|
:ui="{
|
||||||
:ui="{ container: 'sm:py-12 lg:py-12 sm:gap-8', description: 'before:content-[open-quote] after:content-[close-quote]' }"
|
container: 'lg:grid-cols-0 !gap-0 px-4 sm:px-6 lg:px-8',
|
||||||
|
wrapper: 'grid grid-cols-1 lg:grid-cols-2',
|
||||||
|
description: 'lg:mt-0' }"
|
||||||
|
orientation="horizontal"
|
||||||
|
class="rounded-none border-t border-(--ui-border) bg-gradient-to-b from-(--ui-bg-muted) to-(--ui-bg)"
|
||||||
>
|
>
|
||||||
<UUser
|
<template #title>
|
||||||
v-bind="page.authorQuote.user"
|
<MDC :value="page.mainSection.title" unwrap="p" />
|
||||||
size="xl"
|
</template>
|
||||||
class="justify-center"
|
<template #description>
|
||||||
/>
|
<MDC :value="page.mainSection.description" unwrap="p" />
|
||||||
|
</template>
|
||||||
</UPageCTA>
|
</UPageCTA>
|
||||||
|
|
||||||
<UPageSection
|
<UPageSection
|
||||||
v-for="(section, index) in page.sections"
|
v-for="(section, index) in page.sections"
|
||||||
:key="index"
|
:key="index"
|
||||||
v-bind="section"
|
:title="section.title"
|
||||||
|
:description="section.description"
|
||||||
|
:links="section.links"
|
||||||
|
:reverse="section.reverse"
|
||||||
|
:features="section.features"
|
||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
|
:class="{ 'border-b border-(--ui-border)': index === page.sections.length - 1 }"
|
||||||
|
:ui="{
|
||||||
|
container: index === 0 ? 'pb-0 sm:pb-0 lg:pb-0 py-16 sm:py-16 lg:py-16' : ''
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<MDC :value="section.code" />
|
<MDC :value="section.code" />
|
||||||
</UPageSection>
|
</UPageSection>
|
||||||
@@ -66,16 +114,24 @@ defineOgImageComponent('Docs', {
|
|||||||
<UPageSection
|
<UPageSection
|
||||||
id="templates"
|
id="templates"
|
||||||
v-bind="page.templates"
|
v-bind="page.templates"
|
||||||
class="overflow-hidden"
|
class="overflow-hidden border-x border-(--ui-border)"
|
||||||
|
:ui="{ container: 'relative' }"
|
||||||
>
|
>
|
||||||
|
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
||||||
<UCarousel
|
<UCarousel
|
||||||
v-slot="{ item }"
|
v-slot="{ item }"
|
||||||
loop
|
loop
|
||||||
arrows
|
arrows
|
||||||
dots
|
dots
|
||||||
|
wheel-gestures
|
||||||
:autoplay="{ delay: 3000 }"
|
:autoplay="{ delay: 3000 }"
|
||||||
:items="(templatesPage.templates as any[])"
|
:items="(templatesPage.templates as any[])"
|
||||||
:ui="{ item: 'basis-1/2', container: 'py-2' }"
|
:ui="{
|
||||||
|
item: 'basis-1/2',
|
||||||
|
container: 'py-2',
|
||||||
|
viewport: 'border-x border-(--ui-border)',
|
||||||
|
arrows: 'hidden 2xl:block'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<UPageCard
|
<UPageCard
|
||||||
:to="item.links[0].to"
|
:to="item.links[0].to"
|
||||||
@@ -94,7 +150,8 @@ defineOgImageComponent('Docs', {
|
|||||||
:light="item.thumbnail.light"
|
:light="item.thumbnail.light"
|
||||||
:dark="item.thumbnail.dark"
|
:dark="item.thumbnail.dark"
|
||||||
:alt="item.title"
|
:alt="item.title"
|
||||||
class="rounded-lg w-full border border-(--ui-border)"
|
class="rounded-lg w-full border border-(--ui-border) aspect-video"
|
||||||
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
</UPageCard>
|
</UPageCard>
|
||||||
</UCarousel>
|
</UCarousel>
|
||||||
@@ -104,12 +161,30 @@ defineOgImageComponent('Docs', {
|
|||||||
|
|
||||||
<UPageCTA
|
<UPageCTA
|
||||||
v-bind="page.cta"
|
v-bind="page.cta"
|
||||||
variant="naked"
|
variant="subtle"
|
||||||
class="overflow-hidden"
|
class="overflow-hidden"
|
||||||
|
orientation="horizontal"
|
||||||
>
|
>
|
||||||
<div class="absolute rounded-full dark:bg-(--ui-primary) blur-[250px] size-40 sm:size-50 transform -translate-x-1/2 left-1/2 -translate-y-80" />
|
|
||||||
|
|
||||||
<StarsBg />
|
<StarsBg />
|
||||||
|
<video
|
||||||
|
class="rounded-[var(--ui-radius)] z-10"
|
||||||
|
preload="none"
|
||||||
|
poster="https://res.cloudinary.com/nuxt/video/upload/so_3.3/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.jpg"
|
||||||
|
:controls="true"
|
||||||
|
>
|
||||||
|
<source
|
||||||
|
src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.webm"
|
||||||
|
type="video/webm"
|
||||||
|
>
|
||||||
|
<source
|
||||||
|
src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.mp4"
|
||||||
|
type="video/mp4"
|
||||||
|
>
|
||||||
|
<source
|
||||||
|
src="https://res.cloudinary.com/nuxt/video/upload/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.ogg"
|
||||||
|
type="video/ogg"
|
||||||
|
>
|
||||||
|
</video>
|
||||||
</UPageCTA>
|
</UPageCTA>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { joinURL } from 'ufo'
|
||||||
// @ts-expect-error yaml is not typed
|
// @ts-expect-error yaml is not typed
|
||||||
import page from '.content/pricing.yml'
|
import page from '.content/pricing.yml'
|
||||||
|
|
||||||
|
const { url } = useSiteConfig()
|
||||||
|
|
||||||
useSeoMeta({
|
useSeoMeta({
|
||||||
title: page.title,
|
title: page.title,
|
||||||
ogTitle: page.title,
|
ogTitle: page.title,
|
||||||
description: page.description,
|
description: page.description,
|
||||||
ogDescription: page.description
|
ogDescription: page.description,
|
||||||
})
|
ogImage: joinURL(url, '/pro/og-image.png')
|
||||||
defineOgImageComponent('Docs', {
|
|
||||||
headline: 'Pro'
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -18,23 +19,24 @@ defineOgImageComponent('Docs', {
|
|||||||
<UPageHero
|
<UPageHero
|
||||||
class="relative"
|
class="relative"
|
||||||
:description="page.pricing.description"
|
:description="page.pricing.description"
|
||||||
|
:ui="{
|
||||||
|
container: 'relative lg:!pb-0'
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
<MDC :value="page.pricing.title" unwrap="p" />
|
<MDC :value="page.pricing.title" unwrap="p" />
|
||||||
</template>
|
</template>
|
||||||
<template #top>
|
<template #top>
|
||||||
<div class="absolute z-[-1] rounded-full bg-(--ui-primary) blur-[300px] size-60 sm:size-80 transform -translate-x-1/2 left-1/2 -translate-y-80" />
|
|
||||||
<StarsBg />
|
<StarsBg />
|
||||||
</template>
|
</template>
|
||||||
<UContainer>
|
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
||||||
|
<div class="flex flex-col bg-(--ui-bg) gap-8 lg:gap-0">
|
||||||
<UPricingPlan
|
<UPricingPlan
|
||||||
v-bind="page.pricing.freePlan"
|
v-bind="page.pricing.freePlan"
|
||||||
class="mb-16"
|
variant="naked"
|
||||||
|
class="lg:rounded-none border-x border-(--ui-border) border-t border-b lg:border-b-0"
|
||||||
/>
|
/>
|
||||||
<UPricingPlans
|
<UPricingPlans compact>
|
||||||
class="mb-16"
|
|
||||||
scale
|
|
||||||
>
|
|
||||||
<UPricingPlan
|
<UPricingPlan
|
||||||
v-for="(plan, index) in page.pricing.plans"
|
v-for="(plan, index) in page.pricing.plans"
|
||||||
:key="index"
|
:key="index"
|
||||||
@@ -43,15 +45,16 @@ defineOgImageComponent('Docs', {
|
|||||||
:price="plan.price"
|
:price="plan.price"
|
||||||
:billing-period="plan.billing_period"
|
:billing-period="plan.billing_period"
|
||||||
:billing-cycle="plan.billing_cycle"
|
:billing-cycle="plan.billing_cycle"
|
||||||
:highlight="plan.highlight"
|
:variant="plan.highlight ? 'soft' : 'outline'"
|
||||||
:scale="plan.highlight"
|
:class="['lg:rounded-none', { 'border-2 lg:border lg:border-x-0 border-(--ui-primary) lg:border-(--ui-border)': plan.highlight }]"
|
||||||
variant="soft"
|
|
||||||
:features="plan.features"
|
:features="plan.features"
|
||||||
:button="plan.button"
|
:button="plan.button"
|
||||||
/>
|
/>
|
||||||
</UPricingPlans>
|
</UPricingPlans>
|
||||||
<UPricingPlan
|
<UPricingPlan
|
||||||
v-bind="page.pricing.figma"
|
v-bind="page.pricing.figma"
|
||||||
|
variant="naked"
|
||||||
|
class="lg:rounded-none border lg:border-y-0 border-(--ui-border)"
|
||||||
>
|
>
|
||||||
<template #features>
|
<template #features>
|
||||||
<li v-for="(feature, index) in page.pricing.figma.features" :key="index" class="flex items-center gap-2 min-w-0">
|
<li v-for="(feature, index) in page.pricing.figma.features" :key="index" class="flex items-center gap-2 min-w-0">
|
||||||
@@ -60,12 +63,13 @@ defineOgImageComponent('Docs', {
|
|||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
</UPricingPlan>
|
</UPricingPlan>
|
||||||
</UContainer>
|
</div>
|
||||||
</UPageHero>
|
</UPageHero>
|
||||||
|
|
||||||
<UPageSection
|
<UPageSection
|
||||||
id="testimonials"
|
id="testimonials"
|
||||||
v-bind="page.testimonials"
|
v-bind="page.testimonials"
|
||||||
|
class="border-y border-(--ui-border)"
|
||||||
>
|
>
|
||||||
<UPageMarquee pause-on-hover :ui="{ root: '[--duration:40s]' }">
|
<UPageMarquee pause-on-hover :ui="{ root: '[--duration:40s]' }">
|
||||||
<img
|
<img
|
||||||
@@ -99,7 +103,9 @@ defineOgImageComponent('Docs', {
|
|||||||
id="faq"
|
id="faq"
|
||||||
v-bind="page.faq"
|
v-bind="page.faq"
|
||||||
class="scroll-mt-(--ui-header-height)"
|
class="scroll-mt-(--ui-header-height)"
|
||||||
|
:ui="{ container: 'relative' }"
|
||||||
>
|
>
|
||||||
|
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
||||||
<UPageAccordion
|
<UPageAccordion
|
||||||
multiple
|
multiple
|
||||||
:items="(page.faq.items as any[])"
|
:items="(page.faq.items as any[])"
|
||||||
|
|||||||
@@ -1,67 +1,74 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { joinURL } from 'ufo'
|
||||||
// @ts-expect-error yaml is not typed
|
// @ts-expect-error yaml is not typed
|
||||||
import page from '.content/templates.yml'
|
import page from '.content/templates.yml'
|
||||||
|
|
||||||
|
const { url } = useSiteConfig()
|
||||||
|
|
||||||
useSeoMeta({
|
useSeoMeta({
|
||||||
title: page.title,
|
title: page.title,
|
||||||
description: page.description,
|
description: page.description,
|
||||||
ogTitle: page.title,
|
ogTitle: page.title,
|
||||||
ogDescription: page.description
|
ogDescription: page.description,
|
||||||
})
|
ogImage: joinURL(url, '/pro/templates/og-image.png')
|
||||||
defineOgImageComponent('Docs', {
|
|
||||||
headline: 'Pro'
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- eslint-disable vue/no-v-html -->
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
<template>
|
<template>
|
||||||
<div class="relative">
|
<UPageHero :links="page.links" :ui="{ container: 'relative' }">
|
||||||
<UPageHero :links="page.links">
|
<template #top>
|
||||||
<template #top>
|
<StarsBg />
|
||||||
<div class="absolute z-[-1] rounded-full bg-(--ui-primary) blur-[300px] size-60 sm:size-80 transform -translate-x-1/2 left-1/2 -translate-y-80" />
|
</template>
|
||||||
<StarsBg />
|
<div aria-hidden="true" class="hidden lg:block absolute z-[-1] border-x border-(--ui-border) inset-0 mx-4 sm:mx-6 lg:mx-8" />
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #title>
|
<template #title>
|
||||||
<MDC :value="page.hero.title" unwrap="p" />
|
<MDC :value="page.hero.title" unwrap="p" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #description>
|
<template #description>
|
||||||
<MDC :value="page.hero.description" unwrap="p" />
|
<MDC :value="page.hero.description" unwrap="p" />
|
||||||
</template>
|
</template>
|
||||||
</UPageHero>
|
</UPageHero>
|
||||||
|
|
||||||
<UPageSection
|
<UPageSection
|
||||||
v-for="(template, index) in page.templates"
|
v-for="(template, index) in page.templates"
|
||||||
:key="index"
|
:key="index"
|
||||||
:title="template.title"
|
:title="template.title"
|
||||||
:links="template.links"
|
:links="template.links"
|
||||||
:features="template.features"
|
:features="template.features"
|
||||||
orientation="horizontal"
|
orientation="horizontal"
|
||||||
reverse
|
class="lg:border-t border-(--ui-border)"
|
||||||
class="*:!pt-0"
|
:ui="{
|
||||||
:ui="{ title: 'lg:text-4xl' }"
|
title: 'lg:text-4xl',
|
||||||
>
|
wrapper: 'lg:py-16 lg:border-r border-(--ui-border) order-last',
|
||||||
<template #description>
|
container: 'lg:py-0'
|
||||||
<MDC :value="template.description" unwrap="p" />
|
}"
|
||||||
</template>
|
>
|
||||||
|
<template #description>
|
||||||
|
<MDC :value="template.description" unwrap="p" />
|
||||||
|
</template>
|
||||||
|
|
||||||
<UColorModeImage
|
<div class="lg:border-x border-(--ui-border) h-full flex items-center lg:bg-(--ui-bg-muted)/20">
|
||||||
v-if="template.thumbnail"
|
<Motion as-child :initial="{ opacity: 0, transform: 'translateY(10px)' }" :in-view="{ opacity: 1, transform: 'translateY(0px)' }" :in-view-options="{ once: true }" :transition="{ duration: 0.5, delay: 0.2 }">
|
||||||
v-bind="template.thumbnail"
|
<UColorModeImage
|
||||||
class="w-full h-auto rounded-(--ui-radius) border border-(--ui-border)"
|
v-if="template.thumbnail"
|
||||||
width="656"
|
v-bind="template.thumbnail"
|
||||||
height="369"
|
class="w-full h-auto border lg:border-y lg:border-x-0 border-(--ui-border) rounded-(--ui-radius) lg:rounded-none"
|
||||||
/>
|
width="656"
|
||||||
<UCarousel
|
height="369"
|
||||||
v-else-if="template.images"
|
loading="lazy"
|
||||||
v-slot="{ item }"
|
/>
|
||||||
:items="(template.images as any[])"
|
<UCarousel
|
||||||
dots
|
v-else-if="template.images"
|
||||||
>
|
v-slot="{ item }"
|
||||||
<NuxtImg v-bind="item" class="w-full h-full object-cover" width="576" height="360" />
|
:items="(template.images as any[])"
|
||||||
</UCarousel>
|
dots
|
||||||
<Placeholder v-else class="w-full h-full aspect-video" />
|
>
|
||||||
</UPageSection>
|
<NuxtImg v-bind="item" class="w-full h-full object-cover" width="576" height="360" />
|
||||||
</div>
|
</UCarousel>
|
||||||
|
<Placeholder v-else class="w-full h-full aspect-video" />
|
||||||
|
</Motion>
|
||||||
|
</div>
|
||||||
|
</UPageSection>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,20 +1,21 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { joinURL } from 'ufo'
|
||||||
|
|
||||||
const { data: page } = await useAsyncData('terms', () => queryCollection('content').path('/pro/terms').first())
|
const { data: page } = await useAsyncData('terms', () => queryCollection('content').path('/pro/terms').first())
|
||||||
if (!page.value) {
|
if (!page.value) {
|
||||||
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
|
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { url } = useSiteConfig()
|
||||||
|
|
||||||
const title = page.value.title
|
const title = page.value.title
|
||||||
const description = page.value.description
|
const description = page.value.description
|
||||||
useSeoMeta({
|
useSeoMeta({
|
||||||
title,
|
title,
|
||||||
description,
|
description,
|
||||||
ogTitle: `${title} - Nuxt UI Pro`,
|
ogTitle: `${title} - Nuxt UI Pro`,
|
||||||
ogDescription: description
|
ogDescription: description,
|
||||||
})
|
ogImage: joinURL(url, '/pro/og-image.png')
|
||||||
|
|
||||||
defineOgImageComponent('Docs', {
|
|
||||||
headline: 'Pro'
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ Le paiement pour l'acquisition d'une licence Nuxt UI Pro est unique et doit êtr
|
|||||||
|
|
||||||
## 5. Droit de rétractation et remboursement
|
## 5. Droit de rétractation et remboursement
|
||||||
|
|
||||||
Le Client dispose d'un droit de rétractation de 14 jours à compter de la date d'achat. Passé ce délai, aucun remboursement ne sera effectué.
|
Le Client dispose d'un droit de rétractation de 14 jours concernant la licence Nuxt UI Pro à compter de la date d'achat. Passé ce délai, aucun remboursement ne sera effectué.
|
||||||
|
|
||||||
|
Le Figma Pro Kit étant un produit numérique fourni sous forme de fichier ZIP, aucun remboursement ne pourra être effectué après l'achat.
|
||||||
|
|
||||||
## 6. Propriété intellectuelle
|
## 6. Propriété intellectuelle
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export default defineNuxtConfig({
|
|||||||
'@vueuse/nuxt',
|
'@vueuse/nuxt',
|
||||||
'nuxt-component-meta',
|
'nuxt-component-meta',
|
||||||
'nuxt-og-image',
|
'nuxt-og-image',
|
||||||
|
'motion-v/nuxt',
|
||||||
(_, nuxt) => {
|
(_, nuxt) => {
|
||||||
nuxt.hook('components:dirs', (dirs) => {
|
nuxt.hook('components:dirs', (dirs) => {
|
||||||
dirs.unshift({ path: resolve('./app/components/content/examples'), pathPrefix: false, prefix: '', global: true })
|
dirs.unshift({ path: resolve('./app/components/content/examples'), pathPrefix: false, prefix: '', global: true })
|
||||||
@@ -26,6 +27,18 @@ export default defineNuxtConfig({
|
|||||||
},
|
},
|
||||||
'nuxt-llms'
|
'nuxt-llms'
|
||||||
],
|
],
|
||||||
|
$development: {
|
||||||
|
site: {
|
||||||
|
url: 'http://localhost:3000'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
$production: {
|
||||||
|
site: {
|
||||||
|
url: 'https://ui3.nuxt.dev'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
devtools: { enabled: true },
|
||||||
|
|
||||||
app: {
|
app: {
|
||||||
head: {
|
head: {
|
||||||
@@ -47,10 +60,6 @@ export default defineNuxtConfig({
|
|||||||
|
|
||||||
css: ['~/assets/css/main.css'],
|
css: ['~/assets/css/main.css'],
|
||||||
|
|
||||||
site: {
|
|
||||||
url: 'https://ui3.nuxt.dev'
|
|
||||||
},
|
|
||||||
|
|
||||||
content: {
|
content: {
|
||||||
build: {
|
build: {
|
||||||
markdown: {
|
markdown: {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
"@vueuse/nuxt": "^12.7.0",
|
"@vueuse/nuxt": "^12.7.0",
|
||||||
"joi": "^17.13.3",
|
"joi": "^17.13.3",
|
||||||
"motion": "^12.4.7",
|
"motion": "^12.4.7",
|
||||||
|
"motion-v": "0.11.0-beta.4",
|
||||||
"nuxt": "^3.15.4",
|
"nuxt": "^3.15.4",
|
||||||
"nuxt-component-meta": "^0.10.0",
|
"nuxt-component-meta": "^0.10.0",
|
||||||
"nuxt-llms": "^0.1.0",
|
"nuxt-llms": "^0.1.0",
|
||||||
|
|||||||
BIN
docs/public/og-image.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
docs/public/pro/hero.png
Normal file
|
After Width: | Height: | Size: 491 KiB |
BIN
docs/public/pro/og-image.png
Normal file
|
After Width: | Height: | Size: 266 KiB |
|
Before Width: | Height: | Size: 452 KiB |
|
Before Width: | Height: | Size: 599 KiB |
|
Before Width: | Height: | Size: 370 KiB |
BIN
docs/public/pro/templates/og-image.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 384 KiB |
|
Before Width: | Height: | Size: 311 KiB |
58
pnpm-lock.yaml
generated
@@ -291,6 +291,9 @@ importers:
|
|||||||
motion:
|
motion:
|
||||||
specifier: ^12.4.7
|
specifier: ^12.4.7
|
||||||
version: 12.4.7
|
version: 12.4.7
|
||||||
|
motion-v:
|
||||||
|
specifier: 0.11.0-beta.4
|
||||||
|
version: 0.11.0-beta.4(vue@3.5.13(typescript@5.6.3))
|
||||||
nuxt:
|
nuxt:
|
||||||
specifier: ^3.15.4
|
specifier: ^3.15.4
|
||||||
version: 3.15.4(@parcel/watcher@2.5.1)(@types/node@22.13.5)(better-sqlite3@11.8.1)(db0@0.2.4(better-sqlite3@11.8.1))(eslint@9.21.0(jiti@2.4.2))(ioredis@5.5.0)(lightningcss@1.29.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.32.1)(terser@5.39.0)(typescript@5.6.3)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(yaml@2.7.0))(vue-tsc@2.2.0(typescript@5.6.3))(yaml@2.7.0)
|
version: 3.15.4(@parcel/watcher@2.5.1)(@types/node@22.13.5)(better-sqlite3@11.8.1)(db0@0.2.4(better-sqlite3@11.8.1))(eslint@9.21.0(jiti@2.4.2))(ioredis@5.5.0)(lightningcss@1.29.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.32.1)(terser@5.39.0)(typescript@5.6.3)(vite@6.2.0(@types/node@22.13.5)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.39.0)(yaml@2.7.0))(vue-tsc@2.2.0(typescript@5.6.3))(yaml@2.7.0)
|
||||||
@@ -4014,6 +4017,20 @@ packages:
|
|||||||
fraction.js@4.3.7:
|
fraction.js@4.3.7:
|
||||||
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
|
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
|
||||||
|
|
||||||
|
framer-motion@11.16.6:
|
||||||
|
resolution: {integrity: sha512-iaCa44d9ngnIyj7K3PdTl6Q2lrG8l2Ioh+Em8l1335VqksB6i1VAOo+fdcF5qTcwzSoMgr15tSLgdYFbWQ31sQ==}
|
||||||
|
peerDependencies:
|
||||||
|
'@emotion/is-prop-valid': '*'
|
||||||
|
react: ^18.0.0 || ^19.0.0
|
||||||
|
react-dom: ^18.0.0 || ^19.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@emotion/is-prop-valid':
|
||||||
|
optional: true
|
||||||
|
react:
|
||||||
|
optional: true
|
||||||
|
react-dom:
|
||||||
|
optional: true
|
||||||
|
|
||||||
framer-motion@12.4.7:
|
framer-motion@12.4.7:
|
||||||
resolution: {integrity: sha512-VhrcbtcAMXfxlrjeHPpWVu2+mkcoR31e02aNSR7OUS/hZAciKa8q6o3YN2mA1h+jjscRsSyKvX6E1CiY/7OLMw==}
|
resolution: {integrity: sha512-VhrcbtcAMXfxlrjeHPpWVu2+mkcoR31e02aNSR7OUS/hZAciKa8q6o3YN2mA1h+jjscRsSyKvX6E1CiY/7OLMw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -4279,6 +4296,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw==}
|
resolution: {integrity: sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
hey-listen@1.0.8:
|
||||||
|
resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==}
|
||||||
|
|
||||||
hookable@5.5.3:
|
hookable@5.5.3:
|
||||||
resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
|
resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==}
|
||||||
|
|
||||||
@@ -5106,12 +5126,23 @@ packages:
|
|||||||
mlly@1.7.4:
|
mlly@1.7.4:
|
||||||
resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==}
|
resolution: {integrity: sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw==}
|
||||||
|
|
||||||
|
motion-dom@11.18.1:
|
||||||
|
resolution: {integrity: sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw==}
|
||||||
|
|
||||||
motion-dom@12.4.5:
|
motion-dom@12.4.5:
|
||||||
resolution: {integrity: sha512-Q2xmhuyYug1CGTo0jdsL05EQ4RhIYXlggFS/yPhQQRNzbrhjKQ1tbjThx5Plv68aX31LsUQRq4uIkuDxdO5vRQ==}
|
resolution: {integrity: sha512-Q2xmhuyYug1CGTo0jdsL05EQ4RhIYXlggFS/yPhQQRNzbrhjKQ1tbjThx5Plv68aX31LsUQRq4uIkuDxdO5vRQ==}
|
||||||
|
|
||||||
|
motion-utils@11.18.1:
|
||||||
|
resolution: {integrity: sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==}
|
||||||
|
|
||||||
motion-utils@12.0.0:
|
motion-utils@12.0.0:
|
||||||
resolution: {integrity: sha512-MNFiBKbbqnmvOjkPyOKgHUp3Q6oiokLkI1bEwm5QA28cxMZrv0CbbBGDNmhF6DIXsi1pCQBSs0dX8xjeER1tmA==}
|
resolution: {integrity: sha512-MNFiBKbbqnmvOjkPyOKgHUp3Q6oiokLkI1bEwm5QA28cxMZrv0CbbBGDNmhF6DIXsi1pCQBSs0dX8xjeER1tmA==}
|
||||||
|
|
||||||
|
motion-v@0.11.0-beta.4:
|
||||||
|
resolution: {integrity: sha512-FN/vh2XSzpBDpCM5oA8guX0G6gkikYbCr2gRBesMkrA4iEeHslwQiA6IFcPExFuSn1j2kgfB8vXaejZ8Xxn2NQ==}
|
||||||
|
peerDependencies:
|
||||||
|
vue: 3.5.13
|
||||||
|
|
||||||
motion@12.4.7:
|
motion@12.4.7:
|
||||||
resolution: {integrity: sha512-mhegHAbf1r80fr+ytC6OkjKvIUegRNXKLWNPrCN2+GnixlNSPwT03FtKqp9oDny1kNcLWZvwbmEr+JqVryFrcg==}
|
resolution: {integrity: sha512-mhegHAbf1r80fr+ytC6OkjKvIUegRNXKLWNPrCN2+GnixlNSPwT03FtKqp9oDny1kNcLWZvwbmEr+JqVryFrcg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -11327,6 +11358,12 @@ snapshots:
|
|||||||
|
|
||||||
fraction.js@4.3.7: {}
|
fraction.js@4.3.7: {}
|
||||||
|
|
||||||
|
framer-motion@11.16.6:
|
||||||
|
dependencies:
|
||||||
|
motion-dom: 11.18.1
|
||||||
|
motion-utils: 11.18.1
|
||||||
|
tslib: 2.8.1
|
||||||
|
|
||||||
framer-motion@12.4.7:
|
framer-motion@12.4.7:
|
||||||
dependencies:
|
dependencies:
|
||||||
motion-dom: 12.4.5
|
motion-dom: 12.4.5
|
||||||
@@ -11699,6 +11736,8 @@ snapshots:
|
|||||||
|
|
||||||
hex-rgb@4.3.0: {}
|
hex-rgb@4.3.0: {}
|
||||||
|
|
||||||
|
hey-listen@1.0.8: {}
|
||||||
|
|
||||||
hookable@5.5.3: {}
|
hookable@5.5.3: {}
|
||||||
|
|
||||||
hosted-git-info@7.0.2:
|
hosted-git-info@7.0.2:
|
||||||
@@ -12674,12 +12713,31 @@ snapshots:
|
|||||||
pkg-types: 1.3.1
|
pkg-types: 1.3.1
|
||||||
ufo: 1.5.4
|
ufo: 1.5.4
|
||||||
|
|
||||||
|
motion-dom@11.18.1:
|
||||||
|
dependencies:
|
||||||
|
motion-utils: 11.18.1
|
||||||
|
|
||||||
motion-dom@12.4.5:
|
motion-dom@12.4.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
motion-utils: 12.0.0
|
motion-utils: 12.0.0
|
||||||
|
|
||||||
|
motion-utils@11.18.1: {}
|
||||||
|
|
||||||
motion-utils@12.0.0: {}
|
motion-utils@12.0.0: {}
|
||||||
|
|
||||||
|
motion-v@0.11.0-beta.4(vue@3.5.13(typescript@5.6.3)):
|
||||||
|
dependencies:
|
||||||
|
'@vueuse/core': 10.11.1(vue@3.5.13(typescript@5.6.3))
|
||||||
|
framer-motion: 11.16.6
|
||||||
|
hey-listen: 1.0.8
|
||||||
|
motion-dom: 11.18.1
|
||||||
|
vue: 3.5.13(typescript@5.6.3)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@emotion/is-prop-valid'
|
||||||
|
- '@vue/composition-api'
|
||||||
|
- react
|
||||||
|
- react-dom
|
||||||
|
|
||||||
motion@12.4.7:
|
motion@12.4.7:
|
||||||
dependencies:
|
dependencies:
|
||||||
framer-motion: 12.4.7
|
framer-motion: 12.4.7
|
||||||
|
|||||||