Skip to content

Card

  • A grid or list of items, each a unit: products, projects, articles
  • A clickable tile that opens something — with lift
  • A panel that groups related content on a page

Not for rows of data compared across columns — use a Table.

Choosing between organising content:

ComponentUse it forFor example
AccordionSections stacked on one page, of which people read one or a fewFAQ, settings groups, order details
TabsViews of the same thing at the same level, one at a timeAccount / Billing / Security
CardA self-contained group of content, shown as one unit, often in a grid or listA product tile, a project summary
TableRows of records compared across the same columnsInvoices, users, order lines
SeparatorA line that divides sections, with no content of its ownBetween menu groups or toolbar groups

Default

Stays still under the pointer: it isn't clickable.

lift — hover me

Rises with a deeper shadow, so it reads as clickable.

import { Card } from '@arun-dev/ui';
const box = { padding: 'var(--space-sm)', borderRadius: 'var(--radius-lg)' };
export default function CardBasics() {
return (
<>
<Card style={box}>
<p className="font-weight-semibold">Default</p>
<p className="text-size-sm text-color-secondary">
Stays still under the pointer: it isn&apos;t clickable.
</p>
</Card>
{/* A card that opens something: hover it to see it rise. */}
<Card
lift
render={
<a href="#card">
<p className="font-weight-semibold">lift — hover me</p>
<p className="text-size-sm text-color-secondary">
Rises with a deeper shadow, so it reads as clickable.
</p>
</a>
}
style={box}
/>
{/* `as` changes the element, not the look: this one is a labelled landmark. */}
<Card as="nav" aria-label="Example navigation" style={box}>
<p className="font-weight-semibold">as=&quot;nav&quot;</p>
<p className="text-size-sm text-color-secondary">
Looks like Default. It is a &lt;nav&gt; landmark, which screen readers list.
</p>
</Card>
</>
);
}

Two props change a card, in different ways:

PropChangesWhat you seeUse it for
none—a still surface; hovering does nothingcontent that isn’t clickable
lifthow it looksrises 2px with a deeper shadow on hovera card that opens something: a link, a button
aswhich element it isnothing — it looks like the defaultmeaning: nav, article, section, aside

as is for screen readers and the page’s outline, not for looks: as="nav" makes the card a navigation landmark that assistive technology lists, and as="article" marks it as a self-contained item. A card that is a link renders one with render={<a href="…">…</a>}, its content inside the link, as the example’s lift card does.

Card content
<Card as="div">Card content</Card>
Card props
PropTypeDefaultDescription
askeyof JSX.IntrinsicElements'div'Tag to render. Use render when you need a component rather than a tag name.
liftbooleanfalseRaises the card on hover. For cards that are themselves interactive.
classNamestringConcatenated with the component's own classes, never replacing them.
renderReactElementElement or component to render instead of the default. Props, className, event handlers and ref are merged onto it.
refRef<HTMLElement>Ref to the rendered element. Merged with any ref on the render element.
…restHTMLAttributesAnything else is spread onto the rendered element, so id, aria-*, data-* and event handlers all reach the DOM.
  • as takes a tag name. For a component — a router link, say — use render.
  • Unrecognised props reach the DOM, so <Card as="nav" aria-label="…"> produces a properly labelled landmark. Before 0.3.0 that aria-label was silently dropped.
  • Card supplies background, border and shadow but no padding, so it composes with whatever spacing the surrounding layout uses.