Skip to content

Card

Compound surface for grouping related content into a bounded panel. Six parts — <VCCard> outer + optional <VCCardHeader> / <VCCardTitle> / <VCCardDescription> / <VCCardBody> / <VCCardFooter>. Pure-CSS surface; each part wraps reka-ui's Primitive so :as-child works on every part for render-as-link cases.

Padding lives on the outer <VCCard> and propagates to every band via card context — set padding="compact" once, every part resizes consistently. Variants (outline / soft / elevated) cover the typical visual ladder.

bash
npm install @vuecs/elements @vuecs/button
vue
<script setup lang="ts">
import {
    VCCard,
    VCCardBody,
    VCCardDescription,
    VCCardFooter,
    VCCardHeader,
    VCCardTitle,
} from '@vuecs/elements';
import { VCButton } from '@vuecs/button';
</script>

<template>
    <VCCard variant="outline" padding="normal">
        <VCCardHeader>
            <VCCardTitle>User profile</VCCardTitle>
            <VCCardDescription>Manage your account settings.</VCCardDescription>
        </VCCardHeader>
        <VCCardBody>
            <!-- content -->
        </VCCardBody>
        <VCCardFooter>
            <VCButton variant="ghost">Cancel</VCButton>
            <VCButton color="primary">Save</VCButton>
        </VCCardFooter>
    </VCCard>
</template>
css
@import "tailwindcss";
@import "@vuecs/design";
@import "@vuecs/elements";

@custom-variant dark (&:where(.dark, .dark *));

Use :as-child to render <VCCard> (or any part) as a passed slot child. Combined with interactive, the whole card becomes a focusable link with hover + focus rings.

vue
<VCCard as-child interactive>
    <NuxtLink :to="`/users/${user.id}`">
        <VCCardBody>
            <VCCardTitle>{{ user.name }}</VCCardTitle>
            <VCCardDescription>{{ user.email }}</VCCardDescription>
        </VCCardBody>
    </NuxtLink>
</VCCard>

<VCCard> props

PropTypeDefaultDescription
variant'outline' | 'soft' | 'elevated''outline' (theme default)Visual treatment — border vs tinted fill vs shadow.
padding'compact' | 'normal' | 'spacious''normal'Inner padding scale; propagates to every band via context.
interactivebooleanfalseAdds hover + focus-within rings, suitable for link-cards.
asstring'div'HTML tag to render.
asChildbooleanfalseRender the consumer's slot child as the root (Reka asChild pattern).
themeClassPartial<CardThemeClasses>undefinedPer-instance theme override.
themeVariantRecord<string, string | boolean>undefinedPer-instance variant values.

Child-part props

<VCCardHeader> / <VCCardTitle> / <VCCardDescription> / <VCCardBody> / <VCCardFooter> all share the same prop surface:

PropTypeDefaultDescription
asstringvaries — header, h3, p, div, footerHTML tag to render.
asChildbooleanfalseRender the consumer's slot child as the root.
themeClassPartial<*ThemeClasses>undefinedPer-instance theme override.
themeVariantRecord<string, string | boolean>undefinedPer-instance variant values; merged onto card context.

Card-placeholder skeleton

<VCCardPlaceholder> is the card-shaped loading skeleton — image + header line + body lines + footer block. Each section is independently togglable via :no-* props. Composes <VCPlaceholder> from @vuecs/placeholder per section, so the :animation prop flows through and reduced-motion handling at the bar level applies here too.

vue
<script setup>
import { VCCardPlaceholder } from '@vuecs/elements';
</script>

<template>
    <VCCardPlaceholder :body-lines="3" animation="wave" />

    <!-- Skip cover + footer; show only header + body. -->
    <VCCardPlaceholder no-img no-footer />
</template>
PropTypeDefaultDescription
noImgbooleanfalseSkip the cover-image placeholder.
noHeaderbooleanfalseSkip the header line.
noFooterbooleanfalseSkip the footer block.
imgHeightstring'180px'Cover-image placeholder height.
bodyLinesnumber3Number of body lines below the header.
animation'wave' | 'glow' | 'none''wave'Forwarded to every inner bar.

Theme keys

ComponentKeyDefault class
cardrootvc-card
cardHeaderrootvc-card-header
cardTitlerootvc-card-title
cardDescriptionrootvc-card-description
cardBodyrootvc-card-body
cardFooterrootvc-card-footer
cardPlaceholderroot / image / header / body / footervc-card-placeholder-*

Variants opted-into per shipping theme

ComponentAxisValues
cardvariantoutline / soft / elevated
cardinteractivetrue / false
cardHeaderpaddingcompact / normal / spacious
cardBodypaddingcompact / normal / spacious
cardFooterpaddingcompact / normal / spacious

Released under the Apache 2.0 License.