EmCard
A surface for grouping related content — header, title, subtitle, body and footer, in two variants, with an optional hover elevation. It is entirely presentational: the card owns no state and no behavior.
Usage
EmCard is a compound of six parts, and only the root takes props. The parts are slot-through containers that carry the card’s spacing and type scale — EmCardHeader stacks a title over a subtitle, EmCardBody fills the remaining height, and EmCardFooter right-aligns whatever actions you put in it. Use the parts you need in the order you need them; nothing is required except the root.
variant picks the surface treatment — complete is the padded, elevated default — and hoverable adds an elevation response on pointer hover.
Anatomy
<script setup lang="ts">
import {
EmCard,
EmCardBody,
EmCardFooter,
EmCardHeader,
EmCardSubtitle,
EmCardTitle,
} from '@paper/emerald'
</script>
<template>
<EmCard>
<EmCardHeader>
<EmCardTitle />
<EmCardSubtitle />
</EmCardHeader>
<EmCardBody />
<EmCardFooter />
</EmCard>
</template>Composed on v0
EmCard renders v0’s Atom — the polymorphic primitive every v0 component is built on, whose as prop picks the rendered element and whose renderless mode removes the element entirely. Emerald uses the narrowest slice of that: it pins as to div and exposes neither prop, because a card is a styled box and nothing about it varies structurally.
The five parts do not even need Atom. They are plain divs with a class each, because there is no behavior to share between them — no context, no namespace, no state flowing from root to part. The compound shape exists purely so the stylesheet can give each region its spacing and type scale.
That also makes EmCard the inverse of EmButton on one point worth noticing. On the button, v0 publishes state attributes (data-loading, data-disabled) and Emerald styles them; the card has no state, so the data-variant and data-hoverable attributes on its root are Emerald’s own props reflected to the DOM. The convention is the same — the stylesheet targets data attributes, never state classes — but here Emerald is both the writer and the reader.
Examples
Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'complete' | 'simple' | 'complete' | Surface treatment. complete is padded and elevated; simple is a flat, near-flush shell |
hoverable | boolean | false | Deepens the shadow and tints the border on pointer hover. Purely visual |
The root reflects both props to the DOM — data-variant always, data-hoverable only when true — which is where to hang any style overrides. Its only slot is the default slot, where the parts go. There are no models and no emits anywhere in the compound.
Parts
EmCardHeader, EmCardTitle, EmCardSubtitle, EmCardBody and EmCardFooter take no props at all. Each renders a single div with its region’s class and a default slot.
Accessibility
Every element in the compound is a plain div — no roles, no ARIA attributes, no keyboard behavior. A card is announced as nothing and read straight through, which is correct for what it is: a visual grouping. Content order in the template is reading order.
Headings
EmCardTitle is a styled div, not a heading. That is deliberate — a card cannot know what level it sits at in your document — but it means a page of cards contributes nothing to the heading outline by default. When the card’s title should be navigable, put a real heading element inside EmCardTitle and flatten its user-agent styles (font: inherit; margin: 0) so the visual scale stays the card’s while the semantics become yours.
Hover is not interaction
hoverable responds only to :hover, so the elevation feedback exists exclusively for pointer users — keyboard and screen-reader users never encounter it, and the card ships no focus treatment because the card itself is never focusable. Any action a card offers must be a real link or button inside it; give that control the focus treatment, and keep the whole-card hover as a pointer-only echo of it. Avoid making the card div itself clickable — a click handler on a div is invisible to the accessibility tree.