Back to catalog
Component detail entry
Data Display
@vean/ui
SCard

Card

Card belongs to the Data Display category. Start with demos and usage, then use the API tables to finish integration and styling decisions.

Use the quick jump panel to reach overview, usage, demos, and API first, then continue through the full page.

Quick jump

Related components

If you are composing interactions in the same family, these components usually pair well together.

Card

Overview

A container that groups related content and actions into a bordered, shadowed surface. SCard is a UI-only component: it composes the admitted Aria collapsible primitives (CollapsibleRoot / CollapsibleContent / CollapsibleTrigger) for the only real behavior a card has — collapsing — and owns its own header/title/description/footer chrome, styled by the cardVariants recipe (8 slots, 6 sizes, scrollable/split flags).

Use it for dashboards, profile blocks, settings panels, or any content that benefits from a titled, sectioned container. Prefer list or table for repetitive data rows, and popover/dialog for floating or modal surfaces.

The card is collapsible by default — the content area animates open/closed and can be driven with v-model:open. There is no Aria card family: the chrome nodes are presentation-only, so they live in the UI layer and keep data-vean-card-* attributes for styling and tests.

Usage

Features

  • 🧩 UI-only over admitted primitives — the collapsible behavior comes from the Aria collapsible family; SCard owns the chrome and injects the cardVariants classes through provideCollapsibleUi
  • 🧱 Composite structure — header/title/description/content/footer plus title-leading/title-trailing/extra slots
  • 🔽 Collapsible — the content animates open/closed (CollapsibleRoot/CollapsibleContent), controlled with v-model:open/defaultOpen
  • ➗ Split sections — split adds divide-y dividers between title/content/footer
  • 📜 Scrollable content — scrollable makes the content area scroll when it exceeds the card height
  • 🎨 6 sizes — xs–2xl size matching ThemeSize
  • 🎛️ Per-part control — title/description as props or slots; headerProps/contentProps/footerProps/titleProps forwarded to each part
  • ♿ Accessible by default — title renders as a real <h3>, the collapsible trigger exposes aria-expanded, and axe-core reports zero violations

Component family

  • SCard — the entry component; renders CollapsibleRoot (defaultOpen: true) plus the header / title-root / title / description / content / footer nodes, and feeds the cardVariants recipe to provideCollapsibleUi
  • SCardCollapsibleTrigger — the collapsible trigger bound to the card state; renders a chevron SButtonIcon by default and exposes the open state through its slot props

Demos

Basic

Title

extra slot

Card description

Card content
Footer slot

Title Slot

Title

Trailing
Card content

Only Content

Card content

Collapsible

Title

Card content

API

Aria Layer

9

Card

20 Props1 Emits8 Slots
Props
PropTypeDefaultDescription
class
ClassValue
—
Additional class names applied to the root element.
size
ThemeSize
—
Visual size of the component.
ui
Partial<CardUi>
—
Per-slot class overrides for the component.
scrollable
boolean
false
If true, the content will be scrollable when the root has height and content is taller than the root
split
boolean
false
If true, the card will add divider between title and content and footer
title
string
—
Title text rendered by the component.
titleAs
AsTag
'h3'
Heading element the title renders as. A card is embedded at many depths, so the heading level cannot be a constant: the default `h3` lands right under the page `<h1>` on surfaces whose card holds the first heading, which is an invalid heading order. Pass the level that matches the surrounding outline.
description
string
—
Description text rendered by the component.
headerProps
CardHeaderProps
—
Properties forwarded to the header element.
contentProps
CardContentProps
—
Properties forwarded to the content element.
footerProps
CardFooterProps
—
Properties forwarded to the footer element.
titleRootProps
CardTitleRootProps
—
Properties forwarded to the title root element.
titleProps
CardTitleProps
—
Properties forwarded to the title element.
descriptionProps
CardDescriptionProps
—
Properties forwarded to the description element.
defaultOpen
boolean
—
The open state of the collapsible when it is initially rendered. Use when you do not need to control its open state.
open
boolean
—
The controlled open state of the collapsible. Can be bound with `v-model`.
disabled
boolean
—
When `true`, prevents the user from interacting with the collapsible.
unmountOnHide
boolean
—
When `true`, the element will be unmounted on closed state.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
update:open
boolean
Event handler called when the open state of the collapsible changes.
Slots
Slot NameParametersDescription
default
—
Custom content for the default slot.
header
—
Custom content for the header slot.
title
—
Custom content for the title slot.
title-leading
—
Custom content for the title leading slot.
title-trailing
—
Custom content for the title trailing slot.
extra
—
Custom content for the extra slot.
footer
—
Custom content for the footer slot.
description
—
Custom content for the description slot.

CardCollapsibleTrigger

5 Props
Props
PropTypeDefaultDescription
disabledCollapsible
boolean
—
When `true`, prevents the user from toggling the collapsible.
type
ButtonType
'button'
The type of the button element. Can be one of 'button', 'submit', or 'reset'.
disabled
boolean
—
Whether the component is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

CardContent

3 Props
Props
PropTypeDefaultDescription
forceMount
boolean
—
Used to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

CardDescription

CardFooter

CardHeader

CardRoot

6 Props1 Emits
Props
PropTypeDefaultDescription
defaultOpen
boolean
—
The open state of the collapsible when it is initially rendered. Use when you do not need to control its open state.
open
boolean
—
The controlled open state of the collapsible. Can be bound with `v-model`.
disabled
boolean
—
When `true`, prevents the user from interacting with the collapsible.
unmountOnHide
boolean
—
When `true`, the element will be unmounted on closed state.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
update:open
boolean
Event handler called when the open state of the collapsible changes.

CardTitle

CardTitleRoot

Notes

Architecture and benchmark differences

Card is the UI-only exemplar of the Aria admission rule: its only real logic is collapsing, which the admitted collapsible family already provides, so no Aria card family exists. SCard owns the structure orchestration (header/footer visibility, default title/description) and hands the recipe’s root / content / trigger slots to provideCollapsibleUi, so CollapsibleRoot / CollapsibleContent / CollapsibleTrigger resolve their own classes from cardVariants. This mirrors shadcn/ui’s composition-first approach, unlike Ant Design, Element Plus, Mantine and Naive UI which ship a single styled card with title/extra/actions props. VeanUI makes the card collapsible by default through the CollapsibleRoot primitive, a deliberate extension most libraries do not offer on a card; split and scrollable are toggled via recipe variants rather than layout props.

CapabilityVeanUIshadcn/uiAnt Design CardElement Plus CardMantine CardNaive UI Card
Aria/styled split✅✅————
Header / title / description✅✅✅✅✅✅
Footer✅✅✅✅✅✅
Extra (actions) slot✅—✅✅✅✅
Collapsible content✅—————
Split / divider✅—✅✅✅—
Scrollable content✅—✅——✅
Size variants (6)✅—✅✅✅✅
Per-part *Props channels✅✅————

— = unsupported or a different interaction model.

Cautions

  • The card is collapsible and defaults to open (defaultOpen: true). When collapsed, the content (and footer) is removed from the flow; footer visibility depends on the open state.
  • The title renders as a fixed <h3>. If your page’s heading hierarchy differs, wrap or restyle the title so it does not skip levels.
  • The content node carries tabindex="-1" so a scrollable body can receive programmatic focus; it is not an interactive control by itself. Override it through contentProps.
  • SCardCollapsibleTrigger renders an icon-only button, so pass aria-label (e.g. aria-label="Toggle card content") to give it an accessible name.
  • split applies divide-y; combine it with a size to control the vertical rhythm. scrollable only takes effect when the card has a constrained height.
  • The content padding adjusts automatically based on data-header-visible/data-footer-visible (and the collapsible data-state) so a bare content-only card still looks balanced.

Roadmap

No blocking gaps identified for the core card API. A card-level interactive action bar / CardActions shortcut and hover-lift style variants are evaluated enhancements tracked in docs/roadmap/README.md.

FAQ

How do I build a card with a title and description?

Pass title/description props (or the matching slots):

<SCard title="Settings" description="Manage your preferences">
  <p>Body content</p>
</SCard>

How do I add actions to the header?

Use the extra slot (or title-leading/title-trailing around the title):

<SCard title="Profile">
  <template #extra><SButton variant="pure">Edit</SButton></template>
  <p>Body content</p>
</SCard>

How do I make a collapsible card?

Bind open with v-model (or set default-open):

<SCard v-model:open="open" title="Collapsible">
  <p>This content can collapse.</p>
</SCard>

How do I make the content scrollable?

Keep the card height constrained and set scrollable:

<SCard scrollable class="h-80" title="Long list">
  <p v-for="i in 50" :key="i">Row {{ i }}</p>
</SCard>

How do I split the sections with dividers?

Set split to add divide-y dividers between header/content/footer:

<SCard split title="Divided">
  <template #footer><SButton>Save</SButton></template>
  <p>Body content</p>
</SCard>

Changelog

Version history is grouped by release so you can quickly see what changed for this component across published versions.

v0.50.0

2026-10-02

Compare release

Fix

animate the collapsed content padding with the height

Scope: cardAuthors: soybeanjsView commitdb30f

Fix

animate the collapsed content padding with the height

Scope: cardAuthors: soybeanjsView commitdb30f

v0.26.1

2026-05-28

Compare release

Optimization

enhance Card component with header and footer visibility props and optimize style

Scope: cardAuthors: soybeanfeView commit0de1e

v0.16.0

2026-05-01

Compare release

Feature

implement Compact components for Card, Popover, Editable, HoverCard, NavigationMenu, Pagination and Stepper

Scope: componentsAuthors: soybeanjsView commit6cbdc

v0.15.3

2026-04-27

Compare release

Style

update content class for improved accessibility

Scope: cardAuthors: soybeanfeView commit0160d

v0.10.5

2026-03-06

Compare release

Fix

update content styles

Scope: cardAuthors: soybeanjsView commit5a26c

v0.10.1

2026-03-06

Compare release

Feature

add default prop 'asChild' to SCardCollapsibleTrigger

Scope: cardAuthors: soybeanjsView commit3201c

Fix

add 'SCardCollapsibleTrigger' to card components

Scope: cardAuthors: soybeanjsView commitd070a

v0.10.0

2026-03-06

Compare release

Feature

add collapsible functionality and update API props

Scope: cardAuthors: soybeanjsView commite7891

v0.4.5

2026-02-04

Compare release

Fix

wrap header slot content for improved structure and rendering

Scope: cardAuthors: soybeanjsView commitc07bf

v0.0.2

2025-11-18

Compare release

Feature

introduce card component structure with header, footer, content, title, and description components along with context management

Scope: cardAuthors: soybeanjsView commit396aa

Feature

implement Card component with customizable slots, props management, and enhanced styling variants

Scope: cardAuthors: soybeanjsView commitc92bd

Feature

introduce Card component with customizable slots and props, enhancing card functionality and theming support

Scope: cardAuthors: soybeanjsView commitda0c5

Feature

add scrollable prop to Card component for enhanced content management

Scope: cardAuthors: soybeanjsView commitcfc07

Fix

add overflow-auto to content slot for improved layout handling

Scope: cardAuthors: soybeanjsView commit9845e

Fix

correct component name

Scope: cardAuthors: soybeanjsView commit8156c

Refactor

remove size examples from Card component to streamline template and enhance clarity

Scope: cardAuthors: soybeanjsView commitd573d

Refactor

remove flexHeight prop and update cardVariants for cleaner implementation

Scope: cardAuthors: soybeanjsView commit41926

Refactor

remove unused 'flexHeight' prop from CardProps interface

Scope: cardAuthors: soybeanjsView commitae236

Refactor

remove unused 'flexHeight' prop from CardProps interface

Scope: cardAuthors: soybeanjsView commitae236

Feature

introduce card component structure with header, footer, content, title, and description components along with context management

Scope: cardAuthors: soybeanjsView commit396aa

Feature

implement Card component with customizable slots, props management, and enhanced styling variants

Scope: cardAuthors: soybeanjsView commitc92bd

Feature

introduce Card component with customizable slots and props, enhancing card functionality and theming support

Scope: cardAuthors: soybeanjsView commitda0c5

Feature

add scrollable prop to Card component for enhanced content management

Scope: cardAuthors: soybeanjsView commitcfc07

Fix

add overflow-auto to content slot for improved layout handling

Scope: cardAuthors: soybeanjsView commit9845e

Fix

correct component name

Scope: cardAuthors: soybeanjsView commit8156c

Refactor

remove size examples from Card component to streamline template and enhance clarity

Scope: cardAuthors: soybeanjsView commitd573d

Refactor

remove flexHeight prop and update cardVariants for cleaner implementation

Scope: cardAuthors: soybeanjsView commit41926