mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-24 08:50:34 +01:00
docs: start migration
This commit is contained in:
@@ -1,45 +1,8 @@
|
||||
<template>
|
||||
<UPage v-if="page">
|
||||
<UPageHeader :title="page.title" :description="page.description" :links="page.links" :headline="headline" />
|
||||
|
||||
<UPageBody prose>
|
||||
<ContentRenderer v-if="page.body" :value="page" />
|
||||
|
||||
<hr v-if="surround?.length">
|
||||
|
||||
<UContentSurround :surround="surround" />
|
||||
</UPageBody>
|
||||
|
||||
<template v-if="page?.body?.toc?.links?.length" #right>
|
||||
<UContentToc :links="page.body.toc.links">
|
||||
<template #bottom>
|
||||
<div class="hidden lg:block space-y-6 !mt-6">
|
||||
<UDivider v-if="page.body?.toc?.links?.length" type="dashed" />
|
||||
|
||||
<UPageLinks title="Community" :links="communityLinks" />
|
||||
|
||||
<UDivider type="dashed" />
|
||||
|
||||
<UPageLinks title="Resources" :links="resourcesLinks" />
|
||||
|
||||
<UDivider type="dashed" />
|
||||
|
||||
<div class="space-y-3">
|
||||
<AdsPro />
|
||||
<AdsCarbon />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</UContentToc>
|
||||
</template>
|
||||
</UPage>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { withoutTrailingSlash } from 'ufo'
|
||||
|
||||
const route = useRoute()
|
||||
const { branch } = useContentSource()
|
||||
// const { branch } = useContentSource()
|
||||
|
||||
definePageMeta({
|
||||
layout: 'docs'
|
||||
@@ -50,22 +13,22 @@ if (!page.value) {
|
||||
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
|
||||
}
|
||||
|
||||
const { data: surround } = await useAsyncData(`${route.path}-surround`, () => {
|
||||
return queryContent()
|
||||
.where({
|
||||
_extension: 'md',
|
||||
_path: {
|
||||
[branch.value?.name === 'dev' ? '$eq' : '$ne']: new RegExp('^/dev')
|
||||
},
|
||||
navigation: {
|
||||
$ne: false
|
||||
}
|
||||
})
|
||||
.only(['title', 'description', '_path'])
|
||||
.findSurround(withoutTrailingSlash(route.path))
|
||||
})
|
||||
// const { data: surround } = await useAsyncData(`${route.path}-surround`, () => {
|
||||
// return queryContent()
|
||||
// .where({
|
||||
// _extension: 'md',
|
||||
// _path: {
|
||||
// [branch.value?.name === 'dev' ? '$eq' : '$ne']: new RegExp('^/dev')
|
||||
// },
|
||||
// navigation: {
|
||||
// $ne: false
|
||||
// }
|
||||
// })
|
||||
// .only(['title', 'description', '_path'])
|
||||
// .findSurround(withoutTrailingSlash(route.path))
|
||||
// })
|
||||
|
||||
const headline = computed(() => findPageHeadline(page.value))
|
||||
// const headline = computed(() => findPageHeadline(page.value))
|
||||
|
||||
useSeoMeta({
|
||||
titleTemplate: '%s - Nuxt UI',
|
||||
@@ -79,7 +42,7 @@ defineOgImage({
|
||||
component: 'Docs',
|
||||
title: page.value.title,
|
||||
description: page.value.description,
|
||||
headline: headline.value
|
||||
// headline: headline.value
|
||||
})
|
||||
|
||||
const communityLinks = computed(() => [{
|
||||
@@ -119,3 +82,40 @@ const resourcesLinks = [{
|
||||
target: '_blank'
|
||||
}]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UPage>
|
||||
<!-- <UPageHeader :title="page.title" :description="page.description" :links="page.links" :headline="headline" />
|
||||
|
||||
<UPageBody prose>
|
||||
<ContentRenderer v-if="page.body" :value="page" />
|
||||
|
||||
<hr v-if="surround?.length">
|
||||
|
||||
<UContentSurround :surround="surround" />
|
||||
</UPageBody>
|
||||
|
||||
<template v-if="page?.body?.toc?.links?.length" #right>
|
||||
<UContentToc :links="page.body.toc.links">
|
||||
<template #bottom>
|
||||
<div class="hidden lg:block space-y-6 !mt-6">
|
||||
<UDivider v-if="page.body?.toc?.links?.length" type="dashed" />
|
||||
|
||||
<UPageLinks title="Community" :links="communityLinks" />
|
||||
|
||||
<UDivider type="dashed" />
|
||||
|
||||
<UPageLinks title="Resources" :links="resourcesLinks" />
|
||||
|
||||
<UDivider type="dashed" />
|
||||
|
||||
<div class="space-y-3">
|
||||
<AdsPro />
|
||||
<AdsCarbon />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</UContentToc>
|
||||
</template> -->
|
||||
</UPage>
|
||||
</template>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="p-4 flex flex-col justify-center h-screen overflow-auto">
|
||||
<component :is="name" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const route = useRoute()
|
||||
|
||||
const name = route.params.slug[0]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="p-4 flex flex-col justify-center h-screen overflow-auto">
|
||||
<component :is="name" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,410 +1,3 @@
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<template>
|
||||
<div>
|
||||
<ULandingHero :ui="{ base: 'relative z-[1]', container: 'max-w-4xl' }" class="mb-[calc(var(--header-height)*2)]">
|
||||
<template #headline>
|
||||
<UBadge variant="subtle" size="md" class="hover:bg-primary-100 dark:bg-primary-950/100 dark:hover:bg-primary-900 transition-color relative font-medium rounded-full shadow-none">
|
||||
<NuxtLink :to="`https://github.com/nuxt/ui/releases/tag/v${config.version.split('.').slice(0, -1).join('.')}.0`" target="_blank" class="focus:outline-none" aria-label="Go to last relase" tabindex="-1">
|
||||
<span class="absolute inset-0" aria-hidden="true" />
|
||||
</NuxtLink>
|
||||
|
||||
<span class="flex items-center gap-1">
|
||||
Nuxt UI v{{ config.version.split('.').slice(0, -1).join('.') }} is out!
|
||||
</span>
|
||||
</UBadge>
|
||||
</template>
|
||||
|
||||
<template #title>
|
||||
<span v-html="page.hero?.title" />
|
||||
</template>
|
||||
|
||||
<template #description>
|
||||
<span v-html="page.hero?.description" />
|
||||
</template>
|
||||
|
||||
<template #links>
|
||||
<UButton label="Get Started" trailing-icon="i-heroicons-arrow-right-20-solid" size="lg" to="/getting-started/installation" />
|
||||
|
||||
<UInput
|
||||
v-model="source"
|
||||
color="gray"
|
||||
readonly
|
||||
autocomplete="off"
|
||||
icon="i-heroicons-command-line"
|
||||
input-class="select-none"
|
||||
aria-label="Install @nuxt/ui"
|
||||
size="lg"
|
||||
:ui="{ base: 'disabled:cursor-default', icon: { trailing: { pointer: '' } } }"
|
||||
>
|
||||
<template #trailing>
|
||||
<UButton
|
||||
aria-label="Copy Code"
|
||||
:color="copied ? 'primary' : 'gray'"
|
||||
variant="link"
|
||||
size="2xs"
|
||||
:icon="copied ? 'i-heroicons-clipboard-document-check' : 'i-heroicons-clipboard-document'"
|
||||
@click="copy(source)"
|
||||
/>
|
||||
</template>
|
||||
</UInput>
|
||||
</template>
|
||||
|
||||
<ClientOnly>
|
||||
<HomeTetris />
|
||||
</ClientOnly>
|
||||
</ULandingHero>
|
||||
|
||||
<ULandingSection v-for="(section, index) of page.sections" :key="index" v-bind="section">
|
||||
<template v-if="section.title" #title>
|
||||
<span v-html="section?.title" />
|
||||
</template>
|
||||
|
||||
<template v-if="section.description" #description>
|
||||
<span v-html="section.description" />
|
||||
</template>
|
||||
|
||||
<template #demo>
|
||||
<ClientOnly>
|
||||
<HomeDemo v-if="lgAndLarger" />
|
||||
</ClientOnly>
|
||||
</template>
|
||||
|
||||
<template #features>
|
||||
<ULandingGrid class="lg:-mb-20 lg:auto-rows-[3rem]">
|
||||
<ULandingCard
|
||||
v-for="(card, subIndex) of section.cards"
|
||||
:key="subIndex"
|
||||
v-bind="card"
|
||||
:ui="{
|
||||
background: 'dark:bg-gray-900/50 dark:lg:bg-gradient-to-b from-gray-700/50 to-gray-950/50',
|
||||
body: {
|
||||
base: 'flex-1',
|
||||
background: 'dark:bg-gray-800/50 dark:lg:bg-gray-900/50 backdrop-blur-lg'
|
||||
}
|
||||
}"
|
||||
class="flex flex-col"
|
||||
>
|
||||
<UColorModeImage
|
||||
:light="`${card.image.path}-light.svg`"
|
||||
:dark="`${card.image.path}-dark.svg`"
|
||||
:width="card.image.width"
|
||||
:height="card.image.height"
|
||||
:alt="card.title"
|
||||
loading="lazy"
|
||||
class="object-cover w-full"
|
||||
/>
|
||||
</ULandingCard>
|
||||
</ULandingGrid>
|
||||
</template>
|
||||
</ULandingSection>
|
||||
|
||||
<ULandingSection class="!pt-0 dark:bg-gradient-to-b from-gray-950/50 to-gray-900">
|
||||
<ULandingCTA
|
||||
align="left"
|
||||
card
|
||||
:ui="{
|
||||
background: 'dark:bg-gradient-to-b from-gray-800 to-gray-900',
|
||||
shadow: 'dark:shadow-2xl',
|
||||
body: {
|
||||
background: 'bg-gray-50/50 dark:bg-gray-900/50'
|
||||
},
|
||||
title: 'text-center lg:text-left',
|
||||
links: 'justify-center lg:justify-start'
|
||||
}"
|
||||
>
|
||||
<template #title>
|
||||
<span v-html="page.cta.title" />
|
||||
</template>
|
||||
|
||||
<template #links>
|
||||
<ClientOnly>
|
||||
<UAvatarGroup :max="xlAndLarger ? 13 : lgAndLarger ? 10 : mdAndLarger ? 16 : 8" size="md" class="flex-wrap-reverse [&_span:first-child]:text-xs justify-center">
|
||||
<UTooltip
|
||||
v-for="(contributor, index) of module.contributors"
|
||||
:key="index"
|
||||
:text="contributor.username"
|
||||
class="rounded-full"
|
||||
:ui="{ background: 'bg-gray-50 dark:bg-gray-800/50' }"
|
||||
:popper="{ offsetDistance: 16 }"
|
||||
>
|
||||
<UAvatar
|
||||
:alt="contributor.username"
|
||||
:src="`https://ipx.nuxt.com/s_40x40/gh_avatar/${contributor.username}`"
|
||||
:srcset="`https://ipx.nuxt.com/s_80x80/gh_avatar/${contributor.username} 2x`"
|
||||
class="lg:hover:scale-125 lg:hover:ring-2 lg:hover:ring-primary-500 dark:lg:hover:ring-primary-400 transition-transform"
|
||||
width="40"
|
||||
height="40"
|
||||
size="md"
|
||||
loading="lazy"
|
||||
>
|
||||
<NuxtLink :to="`https://github.com/${contributor.username}`" :aria-label="contributor.username" target="_blank" class="focus:outline-none" tabindex="-1">
|
||||
<span class="absolute inset-0" aria-hidden="true" />
|
||||
</NuxtLink>
|
||||
</UAvatar>
|
||||
</UTooltip>
|
||||
</UAvatarGroup>
|
||||
</ClientOnly>
|
||||
</template>
|
||||
|
||||
<div class="flex flex-col sm:flex-row items-center justify-center gap-8 lg:gap-16">
|
||||
<NuxtLink class="text-center group" to="https://npmjs.org/package/@nuxt/ui" target="_blank">
|
||||
<p class="text-6xl font-semibold text-gray-900 dark:text-white group-hover:text-primary-500 dark:group-hover:text-primary-400">
|
||||
{{ format(module.stats.downloads) }}+
|
||||
</p>
|
||||
<p>monthly downloads</p>
|
||||
</NuxtLink>
|
||||
|
||||
<NuxtLink class="text-center group" to="https://github.com/nuxt/ui" target="_blank">
|
||||
<p class="text-6xl font-semibold text-gray-900 dark:text-white group-hover:text-primary-500 dark:group-hover:text-primary-400">
|
||||
{{ format(module.stats.stars) }}+
|
||||
</p>
|
||||
<p>stars</p>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</ULandingCTA>
|
||||
</ULandingSection>
|
||||
|
||||
<template v-if="navigation.find(item => item._path === '/pro')">
|
||||
<div class="relative">
|
||||
<UDivider class="absolute inset-x-0" />
|
||||
|
||||
<div class="w-full relative overflow-hidden h-px bg-gradient-to-r from-gray-800 via-primary-400 to-gray-800 max-w-5xl mx-auto" />
|
||||
</div>
|
||||
|
||||
<ULandingHero id="pro" :links="page.pro.links" :ui="{ title: 'sm:text-6xl' }" class="bg-gradient-to-b from-gray-50 dark:from-gray-950/50 to-white dark:to-gray-900 relative">
|
||||
<template #title>
|
||||
<span v-html="page.pro.title" />
|
||||
</template>
|
||||
|
||||
<template #description>
|
||||
<span v-html="page.pro.description" />
|
||||
</template>
|
||||
|
||||
<div class="bg-gray-900/5 dark:bg-white/5 ring-1 ring-inset ring-gray-900/10 dark:ring-white/10 rounded-xl lg:-m-4 p-4">
|
||||
<video preload="none" poster="https://res.cloudinary.com/nuxt/video/upload/so_3.3/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.jpg" controls class="rounded-lg">
|
||||
<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>
|
||||
</div>
|
||||
</ULandingHero>
|
||||
|
||||
<ULandingSection v-for="(section, index) in page.pro.sections" :key="index" v-bind="section" class="!pt-0">
|
||||
<MDC
|
||||
v-if="section.code"
|
||||
:value="section.code"
|
||||
tag="pre"
|
||||
class="prose prose-primary dark:prose-invert max-w-none"
|
||||
/>
|
||||
</ULandingSection>
|
||||
|
||||
<div ref="sectionRef" :style="{ '--y': `${y}px`, '--inc': `${inc}px` }" class="_screen_xl">
|
||||
<ULandingSection class="sticky h-screen top-0 flex !pb-16" :ui="{ container: 'flex-1 sm:gap-y-12' }">
|
||||
<template #title>
|
||||
<Transition name="fade" mode="out-in">
|
||||
<span v-if="isAfterStep(steps.docs)" v-html="page.pro.docs?.title" />
|
||||
<span v-else v-html="page.pro.landing?.title" />
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<template #description>
|
||||
<Transition name="fade" mode="out-in">
|
||||
<span v-if="isAfterStep(steps.docs)" v-html="page.pro.docs?.description" />
|
||||
<span v-else v-html="page.pro.landing?.description" />
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<HomeProDemo ref="demoRef" :blocks="(blocks as HomeProBlock[])">
|
||||
<template #header-left>
|
||||
<Logo class="w-auto h-6" />
|
||||
</template>
|
||||
|
||||
<template #header-center>
|
||||
<UHeaderLinks :links="headerLinks" />
|
||||
</template>
|
||||
|
||||
<template #header-right>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<UColorModeButton />
|
||||
|
||||
<UButton
|
||||
to="https://github.com/nuxt/ui"
|
||||
target="_blank"
|
||||
icon="i-simple-icons-github"
|
||||
aria-label="GitHub"
|
||||
class="hidden lg:inline-flex"
|
||||
v-bind="($ui.button.secondary as any)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #footer-left>
|
||||
<span class="text-sm text-gray-500 dark:text-gray-400">
|
||||
Published under <NuxtLink to="https://github.com/nuxt/ui" target="_blank" class="text-gray-900 dark:text-white">
|
||||
MIT License
|
||||
</NuxtLink>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template #footer-right>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<UButton aria-label="Nuxt on X" icon="i-simple-icons-x" to="https://x.com/nuxt_js" target="_blank" v-bind="($ui.button.secondary as any)" />
|
||||
<UButton aria-label="Nuxt UI on Discord" icon="i-simple-icons-discord" to="https://discord.com/channels/473401852243869706/1153996761426300948" target="_blank" v-bind="($ui.button.secondary as any)" />
|
||||
<UButton aria-label="Nuxt UI on GitHub" icon="i-simple-icons-github" to="https://github.com/nuxt/ui" target="_blank" v-bind="($ui.button.secondary as any)" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #aside-top>
|
||||
<UContentSearchButton size="md" class="w-full" />
|
||||
</template>
|
||||
|
||||
<template #aside-default>
|
||||
<UNavigationTree
|
||||
class="w-full h-full [&>div>div>div>nav]:border-gray-800/10 dark:[&>div>div>div>nav]:border-gray-200/10 overflow-y-auto"
|
||||
:links="navigationLinks"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #page-header>
|
||||
<UPageHeader
|
||||
title="Installation"
|
||||
description="Learn how to install and configure the module in your Nuxt app."
|
||||
headline="Getting Started"
|
||||
class="!p-0 !border-0"
|
||||
:ui="{ headline: 'mb-1 text-xs', title: '!text-2xl', description: 'mt-1 text-sm' }"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #page-body>
|
||||
<div class="-mt-8 prose prose-primary prose-sm dark:prose-invert max-w-none">
|
||||
<MDC :value="md" tag="div" />
|
||||
|
||||
<!-- <hr class="border-gray-800/10 dark:border-gray-200/10 !mt-5"> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #content-surround>
|
||||
<UContentSurround
|
||||
:surround="(surround as unknown as ParsedContent[])"
|
||||
class="w-full gap-4"
|
||||
:ui="{
|
||||
link: {
|
||||
wrapper: 'px-4 py-2.5 border-gray-800/10 dark:border-gray-200/10 cursor-pointer',
|
||||
icon: {
|
||||
wrapper: 'mb-2 p-1',
|
||||
base: 'h-4 w-4',
|
||||
},
|
||||
title: 'text-sm',
|
||||
description: 'text-xs'
|
||||
}
|
||||
}"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #content-toc>
|
||||
<div class="absolute top-0 left-0 right-0 space-y-3">
|
||||
<UContentToc :links="toc" class="bg-transparent relative max-h-full overflow-hidden top-0" :ui="({ container: { base: '!pt-0 !pb-4' } } as any)" />
|
||||
|
||||
<UDivider type="dashed" :ui="{ border: { base: 'border-gray-800/10 dark:border-gray-200/10' } }" />
|
||||
|
||||
<UPageLinks title="Community" :links="communityLinks" class="mt-4" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #landing-hero>
|
||||
<ULandingHero class="!p-0" :ui="{ title: '!text-5xl', description: 'text-base' }">
|
||||
<template #title>
|
||||
A <span class="text-primary">UI Library</span> for<br> Modern Web Apps
|
||||
</template>
|
||||
|
||||
<template #description>
|
||||
Nuxt UI simplifies the creation of stunning and responsive web applications with its<br> comprehensive collection of fully styled and customizable UI components designed for Nuxt.
|
||||
</template>
|
||||
|
||||
<template #links>
|
||||
<UButton label="Get Started" icon="i-heroicons-rocket-launch" size="md" />
|
||||
|
||||
<UInput
|
||||
model-value="npm i @nuxt/ui"
|
||||
color="gray"
|
||||
readonly
|
||||
autocomplete="off"
|
||||
icon="i-heroicons-command-line"
|
||||
input-class="select-none"
|
||||
aria-label="Install @nuxt/ui"
|
||||
size="md"
|
||||
:ui="{ base: 'disabled:cursor-default', icon: { trailing: { pointer: '' } } }"
|
||||
/>
|
||||
</template>
|
||||
</ULandingHero>
|
||||
</template>
|
||||
|
||||
<template #landing-section>
|
||||
<ULandingSection :ui="{ title: '!text-3xl', description: 'text-base' }" class="!p-0">
|
||||
<template #title>
|
||||
Everything you expect from a<br> <span class="text-primary">UI component library</span>
|
||||
</template>
|
||||
</ULandingSection>
|
||||
</template>
|
||||
|
||||
<template #landing-card-1>
|
||||
<ULandingCard icon="i-heroicons-swatch" title="Color Palette" description="Choose a primary and a gray color from your Tailwind CSS color palette." />
|
||||
</template>
|
||||
<template #landing-card-2>
|
||||
<ULandingCard icon="i-heroicons-wrench-screwdriver" title="Fully Customizable" description="Change the style of any component in your App Config or with ui prop." />
|
||||
</template>
|
||||
<template #landing-card-3>
|
||||
<ULandingCard icon="i-heroicons-face-smile" title="Icons" description="Choose any of the 100k+ icons from the most popular icon libraries." />
|
||||
</template>
|
||||
<template #landing-card-4>
|
||||
<ULandingCard icon="i-heroicons-computer-desktop" title="Keyboard Shortcuts" description="Nuxt UI comes with a set of Vue composables to easily handle shortcuts." />
|
||||
</template>
|
||||
|
||||
<template #landing-cta>
|
||||
<ULandingCTA card :links="[{ label: 'Get started', color: 'black', size: 'md' }, { label: 'Learn more', color: 'black', variant: 'link', size: 'md', trailingIcon: 'i-heroicons-arrow-right-20-solid' }]" :ui="{ title: '!text-3xl', description: 'text-base' }" class="w-full h-full rounded-md">
|
||||
<template #title>
|
||||
Trusted and supported by our<br> amazing community
|
||||
</template>
|
||||
</ULandingCTA>
|
||||
</template>
|
||||
</HomeProDemo>
|
||||
</ULandingSection>
|
||||
|
||||
<div class="h-[calc(var(--inc)*42)]" />
|
||||
</div>
|
||||
|
||||
<div class="_not_screen_xl">
|
||||
<ULandingSection>
|
||||
<template #title>
|
||||
<span v-html="page.pro.landing?.title" />
|
||||
</template>
|
||||
<template #description>
|
||||
<span v-html="page.pro.landing?.description" />
|
||||
</template>
|
||||
<video preload="none" poster="https://res.cloudinary.com/nuxt/video/upload/so_14.4/v1698923423/ui-pro/nuxt-ui-pro-landing-demo_yrh6nr.jpg" controls>
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923423/ui-pro/nuxt-ui-pro-landing-demo_yrh6nr.webm" type="video/webm">
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923423/ui-pro/nuxt-ui-pro-landing-demo_yrh6nr.mp4" type="video/mp4">
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923423/ui-pro/nuxt-ui-pro-landing-demo_yrh6nr.ogg" type="video/ogg">
|
||||
</video>
|
||||
</ULandingSection>
|
||||
<ULandingSection>
|
||||
<template #title>
|
||||
<span v-html="page.pro.docs?.title" />
|
||||
</template>
|
||||
<template #description>
|
||||
<span v-html="page.pro.docs?.description" />
|
||||
</template>
|
||||
<video preload="none" poster="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.jpg" controls>
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.webm" type="video/webm">
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.mp4" type="video/mp4">
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.ogg" type="video/ogg">
|
||||
</video>
|
||||
</ULandingSection>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { ParsedContent, NavItem } from '@nuxt/content/dist/runtime/types'
|
||||
import { useElementBounding, useWindowScroll, useElementSize, breakpointsTailwind, useBreakpoints } from '@vueuse/core'
|
||||
@@ -812,6 +405,413 @@ const communityLinks = [{
|
||||
}]
|
||||
</script>
|
||||
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<template>
|
||||
<div>
|
||||
<ULandingHero :ui="{ base: 'relative z-[1]', container: 'max-w-4xl' }" class="mb-[calc(var(--header-height)*2)]">
|
||||
<template #headline>
|
||||
<UBadge variant="subtle" size="md" class="hover:bg-primary-100 dark:bg-primary-950/100 dark:hover:bg-primary-900 transition-color relative font-medium rounded-full shadow-none">
|
||||
<NuxtLink :to="`https://github.com/nuxt/ui/releases/tag/v${config.version.split('.').slice(0, -1).join('.')}.0`" target="_blank" class="focus:outline-none" aria-label="Go to last relase" tabindex="-1">
|
||||
<span class="absolute inset-0" aria-hidden="true" />
|
||||
</NuxtLink>
|
||||
|
||||
<span class="flex items-center gap-1">
|
||||
Nuxt UI v{{ config.version.split('.').slice(0, -1).join('.') }} is out!
|
||||
</span>
|
||||
</UBadge>
|
||||
</template>
|
||||
|
||||
<template #title>
|
||||
<span v-html="page.hero?.title" />
|
||||
</template>
|
||||
|
||||
<template #description>
|
||||
<span v-html="page.hero?.description" />
|
||||
</template>
|
||||
|
||||
<template #links>
|
||||
<UButton label="Get Started" trailing-icon="i-heroicons-arrow-right-20-solid" size="lg" to="/getting-started/installation" />
|
||||
|
||||
<UInput
|
||||
v-model="source"
|
||||
color="gray"
|
||||
readonly
|
||||
autocomplete="off"
|
||||
icon="i-heroicons-command-line"
|
||||
input-class="select-none"
|
||||
aria-label="Install @nuxt/ui"
|
||||
size="lg"
|
||||
:ui="{ base: 'disabled:cursor-default', icon: { trailing: { pointer: '' } } }"
|
||||
>
|
||||
<template #trailing>
|
||||
<UButton
|
||||
aria-label="Copy Code"
|
||||
:color="copied ? 'primary' : 'gray'"
|
||||
variant="link"
|
||||
size="2xs"
|
||||
:icon="copied ? 'i-heroicons-clipboard-document-check' : 'i-heroicons-clipboard-document'"
|
||||
@click="copy(source)"
|
||||
/>
|
||||
</template>
|
||||
</UInput>
|
||||
</template>
|
||||
|
||||
<ClientOnly>
|
||||
<HomeTetris />
|
||||
</ClientOnly>
|
||||
</ULandingHero>
|
||||
|
||||
<ULandingSection v-for="(section, index) of page.sections" :key="index" v-bind="section">
|
||||
<template v-if="section.title" #title>
|
||||
<span v-html="section?.title" />
|
||||
</template>
|
||||
|
||||
<template v-if="section.description" #description>
|
||||
<span v-html="section.description" />
|
||||
</template>
|
||||
|
||||
<template #demo>
|
||||
<ClientOnly>
|
||||
<HomeDemo v-if="lgAndLarger" />
|
||||
</ClientOnly>
|
||||
</template>
|
||||
|
||||
<template #features>
|
||||
<ULandingGrid class="lg:-mb-20 lg:auto-rows-[3rem]">
|
||||
<ULandingCard
|
||||
v-for="(card, subIndex) of section.cards"
|
||||
:key="subIndex"
|
||||
v-bind="card"
|
||||
:ui="{
|
||||
background: 'dark:bg-gray-900/50 dark:lg:bg-gradient-to-b from-gray-700/50 to-gray-950/50',
|
||||
body: {
|
||||
base: 'flex-1',
|
||||
background: 'dark:bg-gray-800/50 dark:lg:bg-gray-900/50 backdrop-blur-lg'
|
||||
}
|
||||
}"
|
||||
class="flex flex-col"
|
||||
>
|
||||
<UColorModeImage
|
||||
:light="`${card.image.path}-light.svg`"
|
||||
:dark="`${card.image.path}-dark.svg`"
|
||||
:width="card.image.width"
|
||||
:height="card.image.height"
|
||||
:alt="card.title"
|
||||
loading="lazy"
|
||||
class="object-cover w-full"
|
||||
/>
|
||||
</ULandingCard>
|
||||
</ULandingGrid>
|
||||
</template>
|
||||
</ULandingSection>
|
||||
|
||||
<ULandingSection class="!pt-0 dark:bg-gradient-to-b from-gray-950/50 to-gray-900">
|
||||
<ULandingCTA
|
||||
align="left"
|
||||
card
|
||||
:ui="{
|
||||
background: 'dark:bg-gradient-to-b from-gray-800 to-gray-900',
|
||||
shadow: 'dark:shadow-2xl',
|
||||
body: {
|
||||
background: 'bg-gray-50/50 dark:bg-gray-900/50'
|
||||
},
|
||||
title: 'text-center lg:text-left',
|
||||
links: 'justify-center lg:justify-start'
|
||||
}"
|
||||
>
|
||||
<template #title>
|
||||
<span v-html="page.cta.title" />
|
||||
</template>
|
||||
|
||||
<template #links>
|
||||
<ClientOnly>
|
||||
<UAvatarGroup :max="xlAndLarger ? 13 : lgAndLarger ? 10 : mdAndLarger ? 16 : 8" size="md" class="flex-wrap-reverse [&_span:first-child]:text-xs justify-center">
|
||||
<UTooltip
|
||||
v-for="(contributor, index) of module.contributors"
|
||||
:key="index"
|
||||
:text="contributor.username"
|
||||
class="rounded-full"
|
||||
:ui="{ background: 'bg-gray-50 dark:bg-gray-800/50' }"
|
||||
:popper="{ offsetDistance: 16 }"
|
||||
>
|
||||
<UAvatar
|
||||
:alt="contributor.username"
|
||||
:src="`https://ipx.nuxt.com/s_40x40/gh_avatar/${contributor.username}`"
|
||||
:srcset="`https://ipx.nuxt.com/s_80x80/gh_avatar/${contributor.username} 2x`"
|
||||
class="lg:hover:scale-125 lg:hover:ring-2 lg:hover:ring-primary-500 dark:lg:hover:ring-primary-400 transition-transform"
|
||||
width="40"
|
||||
height="40"
|
||||
size="md"
|
||||
loading="lazy"
|
||||
>
|
||||
<NuxtLink :to="`https://github.com/${contributor.username}`" :aria-label="contributor.username" target="_blank" class="focus:outline-none" tabindex="-1">
|
||||
<span class="absolute inset-0" aria-hidden="true" />
|
||||
</NuxtLink>
|
||||
</UAvatar>
|
||||
</UTooltip>
|
||||
</UAvatarGroup>
|
||||
</ClientOnly>
|
||||
</template>
|
||||
|
||||
<div class="flex flex-col sm:flex-row items-center justify-center gap-8 lg:gap-16">
|
||||
<NuxtLink class="text-center group" to="https://npmjs.org/package/@nuxt/ui" target="_blank">
|
||||
<p class="text-6xl font-semibold text-gray-900 dark:text-white group-hover:text-primary-500 dark:group-hover:text-primary-400">
|
||||
{{ format(module.stats.downloads) }}+
|
||||
</p>
|
||||
<p>monthly downloads</p>
|
||||
</NuxtLink>
|
||||
|
||||
<NuxtLink class="text-center group" to="https://github.com/nuxt/ui" target="_blank">
|
||||
<p class="text-6xl font-semibold text-gray-900 dark:text-white group-hover:text-primary-500 dark:group-hover:text-primary-400">
|
||||
{{ format(module.stats.stars) }}+
|
||||
</p>
|
||||
<p>stars</p>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</ULandingCTA>
|
||||
</ULandingSection>
|
||||
|
||||
<template v-if="navigation.find(item => item._path === '/pro')">
|
||||
<div class="relative">
|
||||
<UDivider class="absolute inset-x-0" />
|
||||
|
||||
<div class="w-full relative overflow-hidden h-px bg-gradient-to-r from-gray-800 via-primary-400 to-gray-800 max-w-5xl mx-auto" />
|
||||
</div>
|
||||
|
||||
<ULandingHero id="pro" :links="page.pro.links" :ui="{ title: 'sm:text-6xl' }" class="bg-gradient-to-b from-gray-50 dark:from-gray-950/50 to-white dark:to-gray-900 relative">
|
||||
<template #title>
|
||||
<span v-html="page.pro.title" />
|
||||
</template>
|
||||
|
||||
<template #description>
|
||||
<span v-html="page.pro.description" />
|
||||
</template>
|
||||
|
||||
<div class="bg-gray-900/5 dark:bg-white/5 ring-1 ring-inset ring-gray-900/10 dark:ring-white/10 rounded-xl lg:-m-4 p-4">
|
||||
<video preload="none" poster="https://res.cloudinary.com/nuxt/video/upload/so_3.3/v1708511800/ui-pro/video-nuxt-ui-pro_kwfbdh.jpg" controls class="rounded-lg">
|
||||
<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>
|
||||
</div>
|
||||
</ULandingHero>
|
||||
|
||||
<ULandingSection v-for="(section, index) in page.pro.sections" :key="index" v-bind="section" class="!pt-0">
|
||||
<MDC
|
||||
v-if="section.code"
|
||||
:value="section.code"
|
||||
tag="pre"
|
||||
class="prose prose-primary dark:prose-invert max-w-none"
|
||||
/>
|
||||
</ULandingSection>
|
||||
|
||||
<div ref="sectionRef" :style="{ '--y': `${y}px`, '--inc': `${inc}px` }" class="_screen_xl">
|
||||
<ULandingSection class="sticky h-screen top-0 flex !pb-16" :ui="{ container: 'flex-1 sm:gap-y-12' }">
|
||||
<template #title>
|
||||
<Transition name="fade" mode="out-in">
|
||||
<span v-if="isAfterStep(steps.docs)" v-html="page.pro.docs?.title" />
|
||||
<span v-else v-html="page.pro.landing?.title" />
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<template #description>
|
||||
<Transition name="fade" mode="out-in">
|
||||
<span v-if="isAfterStep(steps.docs)" v-html="page.pro.docs?.description" />
|
||||
<span v-else v-html="page.pro.landing?.description" />
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<HomeProDemo ref="demoRef" :blocks="(blocks as HomeProBlock[])">
|
||||
<template #header-left>
|
||||
<Logo class="w-auto h-6" />
|
||||
</template>
|
||||
|
||||
<template #header-center>
|
||||
<UHeaderLinks :links="headerLinks" />
|
||||
</template>
|
||||
|
||||
<template #header-right>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<UColorModeButton />
|
||||
|
||||
<UButton
|
||||
to="https://github.com/nuxt/ui"
|
||||
target="_blank"
|
||||
icon="i-simple-icons-github"
|
||||
aria-label="GitHub"
|
||||
class="hidden lg:inline-flex"
|
||||
color="gray" variant="ghost"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #footer-left>
|
||||
<span class="text-sm text-gray-500 dark:text-gray-400">
|
||||
Published under <NuxtLink to="https://github.com/nuxt/ui" target="_blank" class="text-gray-900 dark:text-white">
|
||||
MIT License
|
||||
</NuxtLink>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template #footer-right>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<UButton aria-label="Nuxt on X" icon="i-simple-icons-x" to="https://x.com/nuxt_js" target="_blank" color="gray" variant="ghost" />
|
||||
<UButton aria-label="Nuxt UI on Discord" icon="i-simple-icons-discord" to="https://discord.com/channels/473401852243869706/1153996761426300948" target="_blank" color="gray" variant="ghost" />
|
||||
<UButton aria-label="Nuxt UI on GitHub" icon="i-simple-icons-github" to="https://github.com/nuxt/ui" target="_blank" color="gray" variant="ghost" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #aside-top>
|
||||
<UContentSearchButton size="md" class="w-full" />
|
||||
</template>
|
||||
|
||||
<template #aside-default>
|
||||
<UNavigationTree
|
||||
class="w-full h-full [&>div>div>div>nav]:border-gray-800/10 dark:[&>div>div>div>nav]:border-gray-200/10 overflow-y-auto"
|
||||
:links="navigationLinks"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #page-header>
|
||||
<UPageHeader
|
||||
title="Installation"
|
||||
description="Learn how to install and configure the module in your Nuxt app."
|
||||
headline="Getting Started"
|
||||
class="!p-0 !border-0"
|
||||
:ui="{ headline: 'mb-1 text-xs', title: '!text-2xl', description: 'mt-1 text-sm' }"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #page-body>
|
||||
<div class="-mt-8 prose prose-primary prose-sm dark:prose-invert max-w-none">
|
||||
<MDC :value="md" tag="div" />
|
||||
|
||||
<!-- <hr class="border-gray-800/10 dark:border-gray-200/10 !mt-5"> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #content-surround>
|
||||
<UContentSurround
|
||||
:surround="(surround as unknown as ParsedContent[])"
|
||||
class="w-full gap-4"
|
||||
:ui="{
|
||||
link: {
|
||||
wrapper: 'px-4 py-2.5 border-gray-800/10 dark:border-gray-200/10 cursor-pointer',
|
||||
icon: {
|
||||
wrapper: 'mb-2 p-1',
|
||||
base: 'h-4 w-4',
|
||||
},
|
||||
title: 'text-sm',
|
||||
description: 'text-xs'
|
||||
}
|
||||
}"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<template #content-toc>
|
||||
<div class="absolute top-0 left-0 right-0 space-y-3">
|
||||
<UContentToc :links="toc" class="bg-transparent relative max-h-full overflow-hidden top-0" :ui="({ container: { base: '!pt-0 !pb-4' } } as any)" />
|
||||
|
||||
<UDivider type="dashed" :ui="{ border: { base: 'border-gray-800/10 dark:border-gray-200/10' } }" />
|
||||
|
||||
<UPageLinks title="Community" :links="communityLinks" class="mt-4" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #landing-hero>
|
||||
<ULandingHero class="!p-0" :ui="{ title: '!text-5xl', description: 'text-base' }">
|
||||
<template #title>
|
||||
A <span class="text-primary">UI Library</span> for<br> Modern Web Apps
|
||||
</template>
|
||||
|
||||
<template #description>
|
||||
Nuxt UI simplifies the creation of stunning and responsive web applications with its<br> comprehensive collection of fully styled and customizable UI components designed for Nuxt.
|
||||
</template>
|
||||
|
||||
<template #links>
|
||||
<UButton label="Get Started" icon="i-heroicons-rocket-launch" size="md" />
|
||||
|
||||
<UInput
|
||||
model-value="npm i @nuxt/ui"
|
||||
color="gray"
|
||||
readonly
|
||||
autocomplete="off"
|
||||
icon="i-heroicons-command-line"
|
||||
input-class="select-none"
|
||||
aria-label="Install @nuxt/ui"
|
||||
size="md"
|
||||
:ui="{ base: 'disabled:cursor-default', icon: { trailing: { pointer: '' } } }"
|
||||
/>
|
||||
</template>
|
||||
</ULandingHero>
|
||||
</template>
|
||||
|
||||
<template #landing-section>
|
||||
<ULandingSection :ui="{ title: '!text-3xl', description: 'text-base' }" class="!p-0">
|
||||
<template #title>
|
||||
Everything you expect from a<br> <span class="text-primary">UI component library</span>
|
||||
</template>
|
||||
</ULandingSection>
|
||||
</template>
|
||||
|
||||
<template #landing-card-1>
|
||||
<ULandingCard icon="i-heroicons-swatch" title="Color Palette" description="Choose a primary and a gray color from your Tailwind CSS color palette." />
|
||||
</template>
|
||||
<template #landing-card-2>
|
||||
<ULandingCard icon="i-heroicons-wrench-screwdriver" title="Fully Customizable" description="Change the style of any component in your App Config or with ui prop." />
|
||||
</template>
|
||||
<template #landing-card-3>
|
||||
<ULandingCard icon="i-heroicons-face-smile" title="Icons" description="Choose any of the 100k+ icons from the most popular icon libraries." />
|
||||
</template>
|
||||
<template #landing-card-4>
|
||||
<ULandingCard icon="i-heroicons-computer-desktop" title="Keyboard Shortcuts" description="Nuxt UI comes with a set of Vue composables to easily handle shortcuts." />
|
||||
</template>
|
||||
|
||||
<template #landing-cta>
|
||||
<ULandingCTA card :links="[{ label: 'Get started', color: 'black', size: 'md' }, { label: 'Learn more', color: 'black', variant: 'link', size: 'md', trailingIcon: 'i-heroicons-arrow-right-20-solid' }]" :ui="{ title: '!text-3xl', description: 'text-base' }" class="w-full h-full rounded-md">
|
||||
<template #title>
|
||||
Trusted and supported by our<br> amazing community
|
||||
</template>
|
||||
</ULandingCTA>
|
||||
</template>
|
||||
</HomeProDemo>
|
||||
</ULandingSection>
|
||||
|
||||
<div class="h-[calc(var(--inc)*42)]" />
|
||||
</div>
|
||||
|
||||
<div class="_not_screen_xl">
|
||||
<ULandingSection>
|
||||
<template #title>
|
||||
<span v-html="page.pro.landing?.title" />
|
||||
</template>
|
||||
<template #description>
|
||||
<span v-html="page.pro.landing?.description" />
|
||||
</template>
|
||||
<video preload="none" poster="https://res.cloudinary.com/nuxt/video/upload/so_14.4/v1698923423/ui-pro/nuxt-ui-pro-landing-demo_yrh6nr.jpg" controls>
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923423/ui-pro/nuxt-ui-pro-landing-demo_yrh6nr.webm" type="video/webm">
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923423/ui-pro/nuxt-ui-pro-landing-demo_yrh6nr.mp4" type="video/mp4">
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923423/ui-pro/nuxt-ui-pro-landing-demo_yrh6nr.ogg" type="video/ogg">
|
||||
</video>
|
||||
</ULandingSection>
|
||||
<ULandingSection>
|
||||
<template #title>
|
||||
<span v-html="page.pro.docs?.title" />
|
||||
</template>
|
||||
<template #description>
|
||||
<span v-html="page.pro.docs?.description" />
|
||||
</template>
|
||||
<video preload="none" poster="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.jpg" controls>
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.webm" type="video/webm">
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.mp4" type="video/mp4">
|
||||
<source src="https://res.cloudinary.com/nuxt/video/upload/v1698923398/ui-pro/nuxt-ui-pro-docs-demo_jm6ubr.ogg" type="video/ogg">
|
||||
</video>
|
||||
</ULandingSection>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="postcss">
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
|
||||
@@ -1,38 +1,3 @@
|
||||
<template>
|
||||
<div class="relative px-4 sm:px-6 lg:px-8">
|
||||
<div class="stars w-screen fixed pointer-events-none inset-x-0 -top-[--header-height] bottom-0 opacity-75">
|
||||
<div class="h-px w-px rounded-full bg-transparent" />
|
||||
<div class="h-px w-px rounded-full bg-transparent" />
|
||||
<div class="h-px w-px rounded-full bg-transparent" />
|
||||
</div>
|
||||
|
||||
<ULandingHero :description="page.description" :links="page.links" align="center" :ui="{ title: 'sm:text-6xl' }" class="md:py-32">
|
||||
<template #title>
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<span v-html="page.title" />
|
||||
</template>
|
||||
</ULandingHero>
|
||||
|
||||
<UPageBody>
|
||||
<div class="h-[96px] w-0.5 bg-gray-200 dark:bg-gray-800 mx-auto rounded-t-full" />
|
||||
|
||||
<div v-for="(date, index) in dates" :key="index" class="relative py-3 min-h-[24px] flex items-center justify-center">
|
||||
<div class="h-full w-0.5 bg-gray-200 dark:bg-gray-800 absolute top-0 inset-x-[50%] -ml-[1px] flex-shrink-0" />
|
||||
|
||||
<template v-if="date.release || date.pulls?.length || isToday(date.day)">
|
||||
<div class="flex items-start gap-8 relative w-[50%]" :class="index % 2 === 0 ? 'translate-x-[50%] -ml-2' : '-translate-x-[50%] ml-2 flex-row-reverse'">
|
||||
<div class="h-[8px] w-[8px] bg-gray-400 dark:bg-gray-400 rounded-full z-[1] mt-2 ring-2 ring-gray-300 dark:ring-gray-600 flex-shrink-0" />
|
||||
|
||||
<ReleasesItem :date="date" :class="index % 2 === 0 ? '' : 'text-right'" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="h-[96px] w-0.5 bg-gray-200 dark:bg-gray-800 mx-auto rounded-b-full" />
|
||||
</UPageBody>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { eachDayOfInterval, isSameDay, isToday } from 'date-fns'
|
||||
|
||||
@@ -76,6 +41,41 @@ defineOgImage({
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="relative px-4 sm:px-6 lg:px-8">
|
||||
<div class="stars w-screen fixed pointer-events-none inset-x-0 -top-[--header-height] bottom-0 opacity-75">
|
||||
<div class="h-px w-px rounded-full bg-transparent" />
|
||||
<div class="h-px w-px rounded-full bg-transparent" />
|
||||
<div class="h-px w-px rounded-full bg-transparent" />
|
||||
</div>
|
||||
|
||||
<ULandingHero :description="page.description" :links="page.links" align="center" :ui="{ title: 'sm:text-6xl' }" class="md:py-32">
|
||||
<template #title>
|
||||
<!-- eslint-disable-next-line vue/no-v-html -->
|
||||
<span v-html="page.title" />
|
||||
</template>
|
||||
</ULandingHero>
|
||||
|
||||
<UPageBody>
|
||||
<div class="h-[96px] w-0.5 bg-gray-200 dark:bg-gray-800 mx-auto rounded-t-full" />
|
||||
|
||||
<div v-for="(date, index) in dates" :key="index" class="relative py-3 min-h-[24px] flex items-center justify-center">
|
||||
<div class="h-full w-0.5 bg-gray-200 dark:bg-gray-800 absolute top-0 inset-x-[50%] -ml-[1px] flex-shrink-0" />
|
||||
|
||||
<template v-if="date.release || date.pulls?.length || isToday(date.day)">
|
||||
<div class="flex items-start gap-8 relative w-[50%]" :class="index % 2 === 0 ? 'translate-x-[50%] -ml-2' : '-translate-x-[50%] ml-2 flex-row-reverse'">
|
||||
<div class="h-[8px] w-[8px] bg-gray-400 dark:bg-gray-400 rounded-full z-[1] mt-2 ring-2 ring-gray-300 dark:ring-gray-600 flex-shrink-0" />
|
||||
|
||||
<ReleasesItem :date="date" :class="index % 2 === 0 ? '' : 'text-right'" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div class="h-[96px] w-0.5 bg-gray-200 dark:bg-gray-800 mx-auto rounded-b-full" />
|
||||
</UPageBody>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
/* Credits: https://reflect.app/ */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user