PageCard
Usage
The PageCard component provides a flexible way to display content in a card with an illustration in the default slot.
Title
Use the title prop to set the title of the card.
<template>
<PPageCard title="UnoCSS" />
</template>div by default. Use the as prop with an object to render it as a heading, for example :as="{ title: 'h3' }". You can also set the root element this way: :as="{ root: 'section', title: 'h3' }".Description
Use the description prop to set the description of the card.
<template>
<PPageCard
title="UnoCSS"
description="Pohon UI integrates with latest UnoCSS, bringing significant improvements."
/>
</template>Icon
Use the icon prop to set the icon of the card.
<template>
<PPageCard
title="UnoCSS"
description="Pohon UI integrates with latest UnoCSS, bringing significant improvements."
icon="i-simple-icons-unocss"
/>
</template>Link
You can pass any property from the <NuxtLink> component such as to, target, rel, etc.
<template>
<PPageCard
title="UnoCSS"
description="Pohon UI integrates with latest UnoCSS, bringing significant improvements."
icon="i-simple-icons-unocss"
to="https://unocss.dev/"
target="_blank"
/>
</template>Variant
Use the variant prop to change the style of the card.
<template>
<PPageCard
title="UnoCSS"
description="Pohon UI integrates with latest UnoCSS, bringing significant improvements."
icon="i-simple-icons-unocss"
to="https://unocss.dev/"
target="_blank"
variant="soft"
/>
</template>light or dark class to the links slot when using the solid variant to reverse the colors.Orientation
Use the orientation prop to change the orientation with the default slot. Defaults to vertical.
<template>
<PPageCard
title="UnoCSS"
description="Pohon UI integrates with latest UnoCSS, bringing significant improvements."
icon="i-simple-icons-unocss"
orientation="horizontal"
>
<PIcon name="i-simple-icons-unocss" class="size-24" />
</PPageCard>
</template>Reverse
Use the reverse prop to reverse the orientation of the default slot.
<template>
<PPageCard
title="UnoCSS"
description="Pohon UI integrates with latest UnoCSS, bringing significant improvements."
icon="i-simple-icons-unocss"
orientation="horizontal"
reverse
>
<PIcon name="i-simple-icons-unocss" class="size-24" />
</PPageCard>
</template>Highlight
Use the highlight and highlight-color props to display a highlighted border around the card.
<template>
<PPageCard
title="UnoCSS"
description="Pohon UI integrates with latest UnoCSS, bringing significant improvements."
icon="i-simple-icons-unocss"
orientation="horizontal"
highlight
highlight-color="primary"
>
<PIcon name="i-simple-icons-unocss" class="size-24" />
</PPageCard>
</template>Spotlight
Use the spotlight and spotlight-color props to display a spotlight effect that follows your mouse cursor and highlights borders on hover.
to prop. It's best to use it with the outline variant.<template>
<PPageCard
title="UnoCSS"
description="Pohon UI integrates with latest UnoCSS, bringing significant improvements."
icon="i-simple-icons-unocss"
orientation="horizontal"
spotlight
spotlight-color="primary"
>
<PIcon name="i-simple-icons-unocss" class="size-24" />
</PPageCard>
</template>--spotlight-color and --spotlight-size CSS variables:<template>
<PPageCard
spotlight
class="[--spotlight-color:var(--ui-color-error)] [--spotlight-size:200px]"
/>
</template>
Examples
As a testimonial
Use the User component in the header or footer slot to make the card look like a testimonial.
Evan You
Author of Vue.js and Vite
<script setup lang="ts">
const testimonial = ref({
user: {
name: 'Evan You',
description: 'Author of Vue.js and Vite',
avatar: {
src: 'https://avatars.githubusercontent.com/u/499550?v=4',
alt: 'Evan You',
loading: 'lazy' as const,
},
},
quote: '“Nuxt on Cloudflare infra with minimal effort - this is huge!”',
});
</script>
<template>
<PPageCard
:description="testimonial.quote"
class="w-60"
>
<template #footer>
<PUser v-bind="testimonial.user" />
</template>
</PPageCard>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const testimonial = ref({
user: {
name: 'Evan You',
description: 'Author of Vue.js and Vite',
avatar: {
src: 'https://avatars.githubusercontent.com/u/499550?v=4',
alt: 'Evan You',
loading: 'lazy' as const,
},
},
quote: '“Nuxt on Cloudflare infra with minimal effort - this is huge!”',
});
</script>
<template>
<PPageCard
:description="testimonial.quote"
class="w-60"
>
<template #footer>
<PUser v-bind="testimonial.user" />
</template>
</PPageCard>
</template>
API
Props
| Prop | Default | Type |
|---|---|---|
as | 'div' | anyThe element or component this component should render as. |
icon | anyThe icon displayed above the title. | |
title | string | |
description | string | |
orientation | 'vertical' | "horizontal" | "vertical"The orientation of the page card. |
reverse | false | boolean Reverse the order of the default slot. |
highlight | boolean Display a line around the page card. | |
highlightColor | 'primary' | "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral" |
spotlight | boolean Display a spotlight effect that follows your mouse cursor and highlights borders on hover. | |
spotlightColor | 'primary' | "primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral" |
variant | 'outline' | "solid" | "outline" | "soft" | "subtle" | "ghost" | "naked" |
to | string | et | X | |
target | null | "_blank" | "_parent" | "_self" | "_top" | string | |
ui | { root?: SlotClass; spotlight?: SlotClass; container?: SlotClass; wrapper?: SlotClass; header?: SlotClass; body?: SlotClass; footer?: SlotClass; leading?: SlotClass; leadingIcon?: SlotClass; title?: SlotClass; description?: SlotClass; } |
Slots
| Slot | Type |
|---|---|
header | {} |
body | {} |
leading | { ui: object; } |
title | {} |
description | {} |
footer | {} |
default | {} |
Theme
export default defineAppConfig({
ui: {
pageCard: {
slots: {
root: 'relative flex rounded-lg',
spotlight: 'absolute inset-0 rounded-inherit pointer-events-none bg-background/90',
container: 'relative flex flex-col flex-1 lg:grid gap-x-8 gap-y-4 p-4 sm:p-6',
wrapper: 'flex flex-col flex-1 items-start',
header: 'mb-4',
body: 'flex-1',
footer: 'pt-4 mt-auto',
leading: 'inline-flex items-center mb-2.5',
leadingIcon: 'size-5 shrink-0 color-primary',
title: 'text-base text-pretty font-600 color-text-highlighted',
description: 'text-[15px] text-pretty'
},
variants: {
orientation: {
horizontal: {
container: 'lg:grid-cols-2 lg:items-center'
},
vertical: {
container: ''
}
},
reverse: {
true: {
wrapper: 'order-last'
}
},
variant: {
solid: {
root: 'bg-background-inverted color-text-inverted',
title: 'color-text-inverted',
description: 'color-text-dimmed'
},
outline: {
root: 'bg-background ring ring-border',
description: 'color-text-muted'
},
soft: {
root: 'bg-background-elevated/50',
description: 'color-text-toned'
},
subtle: {
root: 'bg-background-elevated/50 ring ring-border',
description: 'color-text-toned'
},
ghost: {
description: 'color-text-muted'
},
naked: {
container: 'pohon:p-0 pohon:sm:p-0',
description: 'color-text-muted'
}
},
to: {
true: {
root: [
'outline-primary/25 has-[>a:focus-visible]:outline-3',
'transition'
]
}
},
title: {
true: {
description: 'mt-1'
}
},
highlight: {
true: {
root: 'ring-2'
}
},
highlightColor: {
primary: '',
secondary: '',
success: '',
info: '',
warning: '',
error: '',
neutral: ''
},
spotlight: {
true: {
root: '[--spotlight-size:400px] before:rounded-inherit before:bg-[radial-gradient(var(--spotlight-size)_var(--spotlight-size)_at_calc(var(--spotlight-x,0px))_calc(var(--spotlight-y,0px)),var(--spotlight-color),transparent_70%)] before:pointer-events-none before:content-empty before:absolute before:-inset-px'
}
},
spotlightColor: {
primary: '',
secondary: '',
success: '',
info: '',
warning: '',
error: '',
neutral: ''
}
},
compoundVariants: [
{
variant: 'solid',
to: true,
class: {
root: 'hover:bg-background-inverted/90'
}
},
{
variant: 'outline',
to: true,
class: {
root: 'hover:bg-background-elevated/50'
}
},
{
variant: 'soft',
to: true,
class: {
root: 'hover:bg-background-elevated'
}
},
{
variant: 'subtle',
to: true,
class: {
root: 'hover:bg-background-elevated'
}
},
{
variant: 'subtle',
to: true,
highlight: false,
class: {
root: 'hover:ring-border-accented'
}
},
{
variant: [
'outline',
'subtle'
],
to: true,
highlight: false,
class: {
root: 'has-[>a:focus-visible]:ring-primary'
}
},
{
variant: 'ghost',
to: true,
class: {
root: 'hover:bg-background-elevated/50'
}
},
{
highlightColor: 'primary',
highlight: true,
class: {
root: 'pohon:ring-primary'
}
},
{
highlightColor: 'neutral',
highlight: true,
class: {
root: 'ring-border-inverted'
}
},
{
spotlightColor: 'primary',
spotlight: true,
class: {
root: '[--spotlight-color:var(--ui-primary)]'
}
},
{
spotlightColor: 'secondary',
spotlight: true,
class: {
root: '[--spotlight-color:var(--ui-secondary)]'
}
},
{
spotlightColor: 'success',
spotlight: true,
class: {
root: '[--spotlight-color:var(--ui-success)]'
}
},
{
spotlightColor: 'info',
spotlight: true,
class: {
root: '[--spotlight-color:var(--ui-info)]'
}
},
{
spotlightColor: 'warning',
spotlight: true,
class: {
root: '[--spotlight-color:var(--ui-warning)]'
}
},
{
spotlightColor: 'error',
spotlight: true,
class: {
root: '[--spotlight-color:var(--ui-error)]'
}
},
{
spotlightColor: 'neutral',
spotlight: true,
class: {
root: '[--spotlight-color:var(--ui-color-bg-inverted)]'
}
}
],
defaultVariants: {
variant: 'outline',
highlightColor: 'primary',
spotlightColor: 'primary'
}
}
}
})import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from 'pohon-ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
pageCard: {
slots: {
root: 'relative flex rounded-lg',
spotlight: 'absolute inset-0 rounded-inherit pointer-events-none bg-background/90',
container: 'relative flex flex-col flex-1 lg:grid gap-x-8 gap-y-4 p-4 sm:p-6',
wrapper: 'flex flex-col flex-1 items-start',
header: 'mb-4',
body: 'flex-1',
footer: 'pt-4 mt-auto',
leading: 'inline-flex items-center mb-2.5',
leadingIcon: 'size-5 shrink-0 color-primary',
title: 'text-base text-pretty font-600 color-text-highlighted',
description: 'text-[15px] text-pretty'
},
variants: {
orientation: {
horizontal: {
container: 'lg:grid-cols-2 lg:items-center'
},
vertical: {
container: ''
}
},
reverse: {
true: {
wrapper: 'order-last'
}
},
variant: {
solid: {
root: 'bg-background-inverted color-text-inverted',
title: 'color-text-inverted',
description: 'color-text-dimmed'
},
outline: {
root: 'bg-background ring ring-border',
description: 'color-text-muted'
},
soft: {
root: 'bg-background-elevated/50',
description: 'color-text-toned'
},
subtle: {
root: 'bg-background-elevated/50 ring ring-border',
description: 'color-text-toned'
},
ghost: {
description: 'color-text-muted'
},
naked: {
container: 'pohon:p-0 pohon:sm:p-0',
description: 'color-text-muted'
}
},
to: {
true: {
root: [
'outline-primary/25 has-[>a:focus-visible]:outline-3',
'transition'
]
}
},
title: {
true: {
description: 'mt-1'
}
},
highlight: {
true: {
root: 'ring-2'
}
},
highlightColor: {
primary: '',
secondary: '',
success: '',
info: '',
warning: '',
error: '',
neutral: ''
},
spotlight: {
true: {
root: '[--spotlight-size:400px] before:rounded-inherit before:bg-[radial-gradient(var(--spotlight-size)_var(--spotlight-size)_at_calc(var(--spotlight-x,0px))_calc(var(--spotlight-y,0px)),var(--spotlight-color),transparent_70%)] before:pointer-events-none before:content-empty before:absolute before:-inset-px'
}
},
spotlightColor: {
primary: '',
secondary: '',
success: '',
info: '',
warning: '',
error: '',
neutral: ''
}
},
compoundVariants: [
{
variant: 'solid',
to: true,
class: {
root: 'hover:bg-background-inverted/90'
}
},
{
variant: 'outline',
to: true,
class: {
root: 'hover:bg-background-elevated/50'
}
},
{
variant: 'soft',
to: true,
class: {
root: 'hover:bg-background-elevated'
}
},
{
variant: 'subtle',
to: true,
class: {
root: 'hover:bg-background-elevated'
}
},
{
variant: 'subtle',
to: true,
highlight: false,
class: {
root: 'hover:ring-border-accented'
}
},
{
variant: [
'outline',
'subtle'
],
to: true,
highlight: false,
class: {
root: 'has-[>a:focus-visible]:ring-primary'
}
},
{
variant: 'ghost',
to: true,
class: {
root: 'hover:bg-background-elevated/50'
}
},
{
highlightColor: 'primary',
highlight: true,
class: {
root: 'pohon:ring-primary'
}
},
{
highlightColor: 'neutral',
highlight: true,
class: {
root: 'ring-border-inverted'
}
},
{
spotlightColor: 'primary',
spotlight: true,
class: {
root: '[--spotlight-color:var(--ui-primary)]'
}
},
{
spotlightColor: 'secondary',
spotlight: true,
class: {
root: '[--spotlight-color:var(--ui-secondary)]'
}
},
{
spotlightColor: 'success',
spotlight: true,
class: {
root: '[--spotlight-color:var(--ui-success)]'
}
},
{
spotlightColor: 'info',
spotlight: true,
class: {
root: '[--spotlight-color:var(--ui-info)]'
}
},
{
spotlightColor: 'warning',
spotlight: true,
class: {
root: '[--spotlight-color:var(--ui-warning)]'
}
},
{
spotlightColor: 'error',
spotlight: true,
class: {
root: '[--spotlight-color:var(--ui-error)]'
}
},
{
spotlightColor: 'neutral',
spotlight: true,
class: {
root: '[--spotlight-color:var(--ui-color-bg-inverted)]'
}
}
],
defaultVariants: {
variant: 'outline',
highlightColor: 'primary',
spotlightColor: 'primary'
}
}
}
})
]
})