๐ข Card
Basic
NCard
- use to display content in a flexible container component.
Prop | Description |
---|---|
title | Title of the card |
description | Description of the card |
Create account now
Fill in the form below to create an account.
Variants
card="{variant}"
- change the card variant
Variant | Description |
---|---|
outline | The default variant. |
soft | The soft variant. |
~ | The unstyle or base variant |
Outline variant
Lorem ipsum dolor sit amet consectetur adipisicing elit. aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.
Soft variant
Lorem ipsum dolor sit amet consectetur adipisicing elit. aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.
Base variant
Lorem ipsum dolor sit amet consectetur adipisicing elit. aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.
Color
card="{variant}-{color}"
- change the color of the card.
primary
. You can also add your own colors to the palette through the Configuration section.outline-orange
Lorem ipsum dolor sit amet consectetur adipisicing elit. aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.
soft-error
Lorem ipsum dolor sit amet consectetur adipisicing elit. aliquid pariatur, ipsum similique veniam quo totam eius aperiam dolorum.
Slots
You can use the following slots to customize the card.
Name | Description |
---|---|
header | The header slot. |
default | The default slot. |
title | The title slot. |
description | The description slot. |
footer | The footer slot. |
Advanced Card
This example shows how you can use named templates for customization
Props
import type { HTMLAttributes } from 'vue'
interface BaseExtensions {
class?: HTMLAttributes['class']
}
export interface NCardProps extends BaseExtensions {
/**
* Allows you to add `UnaUI` card preset properties,
* Think of it as a shortcut for adding options or variants to the preset if available.
*
* @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/card.ts
* @example
* card="outline-green"
*/
card?: string
/**
* Add a title to the card.
*/
title?: string
/**
* Add a description to the card.
*/
description?: string
// sub-components
_cardContent?: Partial<NCardContentProps>
_cardTitle?: Partial<NCardTitleProps>
_cardDescription?: Partial<NCardDescriptionProps>
_cardHeader?: Partial<NCardHeaderProps>
_cardAbout?: Partial<NCardAboutProps>
_cardFooter?: Partial<NCardFooterProps>
/**
* `UnaUI` preset configuration
*
* @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/card.ts
*/
una?: {
cardDefaultVariant: HTMLAttributes['class']
card?: HTMLAttributes['class']
}
}
export interface NCardContentProps extends BaseExtensions {
una?: {
cardContent?: HTMLAttributes['class']
}
}
export interface NCardTitleProps extends BaseExtensions {
una?: {
cardTitle?: HTMLAttributes['class']
}
}
export interface NCardDescriptionProps extends BaseExtensions {
una?: {
cardSubtitle?: HTMLAttributes['class']
}
}
export interface NCardHeaderProps extends BaseExtensions {
una?: {
cardHeader?: HTMLAttributes['class']
}
}
export interface NCardAboutProps extends BaseExtensions {
una?: {
cardAbout?: HTMLAttributes['class']
}
}
export interface NCardFooterProps extends BaseExtensions {
una?: {
cardFooter?: HTMLAttributes['class']
}
}
Presets
type CardPrefix = 'card'
export const staticCard: Record<`${CardPrefix}-${string}` | CardPrefix, string> = {
// base
'card': 'relative flex flex-col rounded-lg overflow-hidden shadow-sm',
'card-default-variant': 'card-outline-gray',
// components
'card-header': '',
'card-title': 'text-2xl font-semibold leading-none tracking-tight',
'card-description': 'text-sm text-muted',
'card-content': 'px-4 py-5 pt-0 sm:p-6 sm:pt-0',
'card-footer': 'flex items-center p-6 pt-0',
'card-about': 'flex flex-col gap-y-1.5 px-4 py-5 sm:p-6',
// static variants
'card-soft-gray': 'bg-muted border border-base',
'card-outline-gray': 'bg-base border border-base',
}
export const dynamicCard = [
// dynamic variants
[/^card-soft(-(\S+))?$/, ([, , c = 'gray']) => `bg-${c}-50 dark:bg-${c}-900 border-${c}-200 dark:border-${c}-700/58`],
[/^card-outline(-(\S+))?$/, ([, , c = 'gray']) => `border border-${c}-200 dark:border-${c}-700/58`],
]
export const card = [
...dynamicCard,
staticCard,
]
Component
<script setup lang="ts">
import { computed } from 'vue'
import type { NCardProps } from '../../../types/card'
import { cn } from '../../../utils'
import CardContent from './CardContent.vue'
import CardHeader from './CardHeader.vue'
import CardAbout from './CardAbout.vue'
import CardFooter from './CardFooter.vue'
import CardTitle from './CardTitle.vue'
import CardDescription from './CardDescription.vue'
defineOptions({
inheritAttrs: false,
})
const props = withDefaults(defineProps<NCardProps>(), {
una: () => ({
cardDefaultVariant: 'card-default-variant',
}),
})
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props
return delegated
})
const cardVariants = ['soft', 'outline'] as const
const hasVariant = computed(() => cardVariants.some(cardVariant => props.card?.includes(cardVariant)))
const isBaseVariant = computed(() => props.card?.includes('~'))
</script>
<template>
<div
v-bind="{ ...$attrs, delegatedProps }"
:card="card"
:class="cn(
'card',
!hasVariant && !isBaseVariant ? una?.cardDefaultVariant : '',
props.class,
una?.card,
)"
>
<slot name="root">
<CardHeader
v-bind="delegatedProps._cardHeader"
>
<slot name="header" />
</CardHeader>
<CardAbout
v-if="$slots.about || title || description || $slots.title || $slots.description"
v-bind="delegatedProps._cardAbout"
>
<slot name="about">
<CardTitle
v-if="$slots.title || title"
v-bind="delegatedProps._cardTitle"
>
<slot name="title">
{{ title }}
</slot>
</CardTitle>
<CardDescription
v-if="$slots.description || description"
v-bind="delegatedProps._cardDescription"
>
<slot name="description">
{{ description }}
</slot>
</CardDescription>
</slot>
</CardAbout>
<CardContent
v-if="$slots.default"
v-bind="delegatedProps._cardContent"
>
<slot />
</CardContent>
<CardFooter
v-if="$slots.footer"
v-bind="delegatedProps._cardFooter"
>
<slot name="footer" />
</CardFooter>
</slot>
</div>
</template>