Skip to content

Card

A surface that groups related content and actions.

Preview

Family Floater Plan

Renews on 1 April 2027

Active
Sum insured₹10,00,000
Members4
Claims this year2

Installation

pnpm add @syntara/react @syntara/tokens
import { Card, CardMedia, CardHeader, CardTitle, CardDescription, CardAction, CardContent, CardFooter } from '@syntara/react';

Usage

import { Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@syntara/react';

export function PlanCard() {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Family plan</CardTitle>
        <CardDescription>Renews on 1 April</CardDescription>
      </CardHeader>
      <CardContent>4 members covered</CardContent>
      <CardFooter>
        <Button size="sm">Manage plan</Button>
      </CardFooter>
    </Card>
  );
}

Examples

Feature

A promo card: brand glow from the top-start corner, rim light, star field, and a primary and secondary action.

Your whole portfolio, in one place

Track savings, cards and investments together, and move money between them in seconds.

₹4,82,150.00

Showcase

A case-study card: media on a brand glow, a title and body, three editorial figures, a footnote and a footer rail with the year and a link.

Claims · Member app

A claim form that fills itself in from the receipt

Members retyped every bill by hand and gave up halfway. Now a photo of the receipt fills the form, and they only check it.

time to file
−42%
median claim
3 min
filed online
+11%

Measured in production, first quarter after launch

Showcase grid

Three interactive showcase cards in a row, one per glow (brand, accent, none). The rails line up at the bottom.

Renewals in one tap

A reminder that opens straight on the renewal, already filled in.

One wallet for the family

Shared limits that every member can see, with nobody asking who spent what.

Answers before a ticket

Search that reads the policy, so most questions end on the first screen.

With a form

Fields in CardContent and submit/cancel in CardFooter.

Add a bank account

Approved claims are paid into this account.

11 characters, printed on your cheque book.

Variants

default (raised), outline and ghost.

Default

Raised surface with a border and shadow.

variant="default"

Outline

Border only, for dense layouts.

variant="outline"

Ghost

No chrome, keeps the spacing.

variant="ghost"

Interactive

Cards that open something: one link in the title covers the card, which lifts under the pointer.

Health cover

Hospital stays, day care and check-ups for the family.

Popular

Travel cover

Medical emergencies, lost bags and trip delays abroad.

New

Inset content

A pale inner surface with a concentric corner, and a meta line with an icon.

Order summary refactor

feature/summary · 3 files

  • src/checkout/summary.tsx+42 −8
  • src/checkout/totals.ts+11 −3
  • src/checkout/summary.test.tsx+27

Rim light

Rim light: the edge catches light at the top-left and fades. Built into default cards in dark; the rim prop adds it in light.

Default

A hairline edge in light; in dark the rim is built in.

With rim

The edge catches light at the top-left, in light too.

Accessibility

No keyboard interaction of its own.

  • A card is a plain div; CardTitle is a real heading (h3 by default).
  • If the whole card is a link, put the link on the title and extend its hit area with CSS rather than wrapping the card in <a>.
  • Give a card role="region" and aria-labelledby only when it is a major page landmark.
  • Interactive cards: the title link is the only tab stop for the card and names it; its focus ring is drawn round the whole card. Keep other controls inside few — they stay separately focusable above the stretched link.
  • Feature cards: the glow strength (16% light, 30% dark) and star alpha are capped so text.default, text.subtle and text.brand reach 4.5:1 on the worst pixel for every tenant; test/card.test.tsx re-proves it from the CSS. Buttons on it keep their own solved fills.
  • Showcase cards: text sits only on the solid face (surface.raised light, surface.sunken dark), never on the glow. CardMedia's glow is a pseudo-element, so assistive tech never meets it; what's inside CardMedia needs its own text alternative (img alt, or role="img" + aria-label on a mock).
  • Editorial figures inside a showcase card (StatTile variant="editorial" in a StatTileGroup) are one <dl>: each label is read before its value, although the value is drawn first.

Guidelines

Do

  • Keep one primary action per card, in the footer or CardAction.
  • Let parts that must bleed (tables, images) drop their inline padding.
  • Use CardContent variant="inset" when the content is one object (a table, a diff, a list) that should read as a unit inside the card.
  • Use variant="feature" for one promo or hero card per view, with one primary and one secondary action.
  • Use variant="showcase" for case studies and galleries: CardMedia first, then the header, the figures, a footnote and a CardFooter divider rail with meta text and one Link (standalone, trailing IconArrowUpRight).

Don’t

  • Don't nest cards; use a Separator or an outline card inside.
  • Don't put more than one heading level inside a CardHeader.
  • Don't nest inset surfaces, or put an inset surface in an outline or ghost card: the pale fill needs the raised card around it.
  • Don't put text colours other than text.default, text.subtle and text.brand on a feature card; other roles aren't proved on the glow.
  • Don't put text or controls inside CardMedia, or rebuild the glow behind the header: the glow's contrast is not proven for text.

API reference

Card

variant
  • defaultdefault
  • outline
  • ghost
  • feature
  • showcase

default = raised surface, hairline edge and soft shadow, plus the sheen (a diagonal band of light) and the rim light in dark; outline = hairline edge only; ghost = no chrome, same spacing; feature = a promo/hero card with a deep brand glow from the top-start corner, the rim light and the brand halo (one per view). Its glow is capped so text.default, text.subtle and text.brand stay ≥ 4.5:1 (proved in test/card.test.tsx). feature adapts to the scheme: in light it's the raised shadow and a very faint brand gradient; in dark, a deep gradient and the brand halo. showcase = a case-study card: a quiet solid face (surface.raised in light with the raised shadow; surface.sunken in dark), 1.6× the container radius (capped at space-10), a glossy rim brightest along the top, and a CardMedia on top. Its text (text.default, text.subtle, text.brand) is proved on the face and the sheen for tenants and 1,000 fuzz brands (test/card.test.tsx). Parts inside get a concentric radius. With interactive it lifts 2px.

interactive
boolean

For cards that open something. One link in CardTitle stretches over the card; the card lifts on hover, springs back when pressed, and shows the focus ring round the whole card. Other controls inside stay clickable.

Default false

rim
boolean

Rim light: the 1px edge is brighter at the top-left and fades, like light catching glass. Built into default cards in dark (the surface recipe); rim adds it in light and to outline and ghost cards. Always on for variant="feature".

Default false

stars
boolean

A faint decorative star field (CSS dots in a pseudo-element, invisible to assistive tech). Only drawn on variant="feature".

Default false

CardMedia

glow
  • branddefault
  • accent
  • none

The ambient haze behind the media, rising from the bottom centre and fading into the card face: brand = action.primary.bg, accent = accent.bg. Decorative (a pseudo-element), and only ever behind the media: CardMedia is the only part that draws it.

children
ReactNode

An image, video or device mock, centred. Edge to edge at the top of the card and clipped to its top corners; put it first. Give images their own alt text; a mock built from divs needs role="img" and an aria-label. No text content: the glow isn't proven for text.

CardHeader

divider
boolean

Draws a hairline under the header.

Default false

CardTitle

level
1 | 2 | 3 | 4 | 5 | 6

Heading level. Pick the one that fits the page outline.

Default 3

CardAction

children
ReactNode

Placed at the top inline-end of the header, beside the title and description (e.g. a Badge, Link or menu button).

CardFooter

divider
boolean

Draws a hairline above the footer.

Default false

CardContent

variant
  • defaultdefault
  • inset

inset = a pale inner surface (surface.sunken, hairline edge, corner concentric with the card) for a table, list or code block. A table inside fills it edge to edge and loses its own frame; the card inset token is halved inside.

Tokens

The semantic tokens this component reads, grouped by what they control. Swatches show this site’s theme; change a tenant’s brand and the component follows with no code change.

Colour10
border.defaultborder.subtlefocus.ringsurface.raisedtext.defaulttext.subtlesurface.sunkenaction.primary.bgtext.brandaccent.bg
Type14
font.bodyfont.headingfont.size.lgfont.size.mdfont.size.smfont.weight.semiboldline-height.normalline-height.tightfont.tracking.lgfont.tracking.mdfont.tracking.smfont.weight.regularfont.size.xlfont.tracking.xl
Space and size7
space.1space.2space.4card-inseticon-strokespace.3space.10
Shape2
radius.containerradius.badge
Depth3
shadow.overlayshadow.raisedhairline
Motion7
motion.duration.fastmotion.duration.normalmotion.duration.springmotion.easingmotion.springmotion.duration.slowmotion.easingOut
Other3
rimsheenglow