Card
When to use
Section titled “When to use”- 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:
| Component | Use it for | For example |
|---|---|---|
| Accordion | Sections stacked on one page, of which people read one or a few | FAQ, settings groups, order details |
| Tabs | Views of the same thing at the same level, one at a time | Account / Billing / Security |
| Card | A self-contained group of content, shown as one unit, often in a grid or list | A product tile, a project summary |
| Table | Rows of records compared across the same columns | Invoices, users, order lines |
| Separator | A line that divides sections, with no content of its own | Between 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'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="nav"</p> <p className="text-size-sm text-color-secondary"> Looks like Default. It is a <nav> landmark, which screen readers list. </p> </Card> </> );}Two props change a card, in different ways:
| Prop | Changes | What you see | Use it for |
|---|---|---|---|
| none | — | a still surface; hovering does nothing | content that isn’t clickable |
lift | how it looks | rises 2px with a deeper shadow on hover | a card that opens something: a link, a button |
as | which element it is | nothing — it looks like the default | meaning: 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.
Playground
Section titled “Playground”Card content
<Card as="div">Card content</Card>| Prop | Type | Default | Description |
|---|---|---|---|
as | keyof JSX.IntrinsicElements | 'div' | Tag to render. Use render when you need a component rather than a tag name. |
lift | boolean | false | Raises the card on hover. For cards that are themselves interactive. |
className | string | Concatenated with the component's own classes, never replacing them. | |
render | ReactElement | Element or component to render instead of the default. Props, className, event handlers and ref are merged onto it. | |
ref | Ref<HTMLElement> | Ref to the rendered element. Merged with any ref on the render element. | |
…rest | HTMLAttributes | Anything else is spread onto the rendered element, so id, aria-*, data-* and event handlers all reach the DOM. |
astakes a tag name. For a component — a router link, say — userender.- Unrecognised props reach the DOM, so
<Card as="nav" aria-label="…">produces a properly labelled landmark. Before0.3.0thataria-labelwas silently dropped. Cardsupplies background, border and shadow but no padding, so it composes with whatever spacing the surrounding layout uses.