Marigold
v18.0.0-beta.3
Marigold
v18.0.0-beta.3

Application

MarigoldProvider
RouterProvider

Layout

AppShellbeta
Aside
Aspect
Center
Columns
Container
Grid
Inline
Inset
Pagebeta
Panelbeta
Scrollable
Split
Stack
Tiles

Actions

Buttonupdated
ButtonGroupbeta
Link
LinkButton
ToggleButtonbeta

Form

Autocomplete
Calendar
Checkbox
ComboBox
DateField
DatePicker
DateRangePickerbeta
FileField
Form
NumberField
Radio
RangeCalendaralpha
SearchField
SegmentedControlbeta
Select
SelectListupdated
Slider
Switchupdated
TagFieldbeta
TextArea
TextField
TimeField

Collection

Cardupdated
Table
Tag
ActionBaralpha

Navigation

Accordion
Breadcrumbs
Pagination
Sidebarbeta
Tabs
TopNavigationbeta

Overlay

ActionMenualpha
ContextualHelp
Dialog
Drawer
Menuupdated
Toastbeta
Tooltip

Content

Badge
Descriptionalpha
Divider
EmptyStatebeta
Headline
Keyboardbeta
List
Loader
SectionMessage
SVG
Text
TextValuealpha
Titlealpha

Formatters

DateFormat
NumericFormat

Hooks and Utils

cn
cva
extendTheme
parseFormData
useAsyncListData
useLandmark
useListData
useResponsiveValueupdated
useTheme
VisuallyHidden
Components

Card

Represents one item in a collection.

A <Card> represents one item in a collection, such as an event preview, a venue tile, or a product summary, that repeats next to similar siblings in a grid or list. Each card groups related content (image, title, content, actions) into a single, self-contained unit and sets it apart from the page through fill or tinting: a white card sits on the gray page background with a quiet rim, not a drop shadow.

<Card> renders an <article> landmark, labelled by its <Title> so the card stays identifiable to assistive tech.

Anatomy

The card component is a compound component made up of several sub-components that map to distinct visual areas of the card.

Card.MediaTitleDescriptionCard.ContentCardCard.HeaderCard.Footer
  • Card.Media: Optional full-bleed area at the top, typically used for images or media.
  • Card.Header: Houses a <Title> and an optional <Description>.
  • Card.Content: Main content area for descriptive text or form elements.
  • Card.Footer: Bottom area for actions such as buttons or metadata.

Appearance

The appearance of a component can be customized using the variant and size props. These props adjust the visual style and dimensions of the component, available values are based on the active theme.

The selected theme does not has any options for"size".

Grand Avenue Ballroom

Shakytown, United States

Formal Venue
Capacity: 800
An elegant ballroom with crystal chandeliers and a full proscenium stage, ideal for gala dinners, award nights, and concerts.
$3,000– $10,000
PropertyTypeDescription
variantdefault | master | adminThe available variants of this component.
size-The available sizes of this component.

The card component supports variants for general content grouping as well as access-level marking.

VariantDescriptionWhen to use
defaultStandard card — set off from the gray page by its lighter fill and a subtle rim rather than a drop shadow. This is the default variant.General-purpose content grouping like articles, profiles, or summaries.
adminCard with admin-specific border and background tint.Grouping content visible only to admin users. Learn more.
masterCard with master-specific border and background tint.Grouping content visible only to master users. Learn more.

Usage

A <Card> displays one item in a repeating set, such as an event, a product, a venue, or a team member, where each entry has its own visual identity and links to its own detail view. Repetition is the core case. If the element doesn't repeat, a card is probably the wrong tool.

<Card> is one of Marigold's Collection components, alongside <Table>. The rest of this section helps you decide when a card is the right choice, when another Collection component or a Layout primitive fits better, and how to build and lay out cards once you've settled on one.

Do

Use a Layout primitive for content that doesn't repeat: <Panel> for a named region like "Billing", <Stack> for topic-grouped content, <Tiles> for a reflowing grid of blocks.

Don't

Don't reach for <Card> when the content isn't a collection. A single, non-repeating region isn't a card.

Panel covers the reverse in its Panel vs Card section.

Card vs Table

<Card> and <Table> are both Collection components. They both display one item in a repeating set, so the choice between them is about display shape, not category.

CardTable

Reach for <Table> when items share the same fields and the user's task is comparison, sorting, filtering, or bulk action. Reach for <Card> when each item is recognized by its own visuals and links to a detail view, not by its position in a row.

Selectable cards

Reach for selectable cards when the user has to pick from a set of card-shaped options and that choice becomes part of a form. A checkout choosing between Standard, VIP, and Student tickets, a billing page swapping between saved payment methods, a shipping step picking Express over Standard. What sets these apart from a plain card grid is that each card carries a value the form has to submit, exactly one (or a bounded set) can be active at a time, and the selection has to survive keyboard and screen-reader use.

<Card> cannot do any of that. It renders a non-interactive <article> meant for grouping content, so making it selectable means rebuilding the whole selection layer by hand: tracking which card is active, wiring a hidden radio or checkbox so the value posts with the form, adding roving arrow-key focus across the grid, and setting the ARIA roles a screen reader needs to announce a card as "selected." That is a lot of accessibility-critical behaviour to reinvent, and it is easy to get subtly wrong.

<SelectList> with variant="bordered" is exactly that machinery, already built and tested. Each option renders as its own outlined card, so you keep the card look while the component owns selection state, form integration, keyboard navigation, and the "selected" announcements. Use selectionMode="single" for a plan or payment-method picker where one card wins, or selectionMode="multiple" when several cards can be active at once, such as add-ons or notification channels.

Header

Card.Header is slot-aware: drop a <Title> and an optional <Description> directly inside it. The header wires up the heading level, id, and accessible name automatically.

Sommernachts-Konzert 2026

Elbphilharmonie Hamburg · June 14, 2026

An open-air evening with the Hamburg Symphony Orchestra. Doors open at 7pm, performance starts at 8pm.
import { Card, Description, Text, Title } from '@marigold/components';export default () => (  <Card>    <Card.Header>      <Title>Sommernachts-Konzert 2026</Title>      <Description>Elbphilharmonie Hamburg · June 14, 2026</Description>    </Card.Header>    <Card.Content>      <Text>        An open-air evening with the Hamburg Symphony Orchestra. Doors open at        7pm, performance starts at 8pm.      </Text>    </Card.Content>  </Card>);

The Title inside Card.Header renders at the card's headingLevel (default 3). Override per-card with <Card headingLevel={2}> when the card lives at a higher position in the document outline.

Card grids

The canonical card layout is a responsive grid of items, each with its own visual identity. Use <Tiles> for a grid that reflows automatically, <Stack> for a vertical list, or <Inline> for a horizontal row.

Main Street Park Amphitheater

Main Street Park Amphitheater

Laughville, United States

Outdoor Venue
Up to 500 guests
$1,000
Shakytown Comedy Club

Shakytown Comedy Club

Shakytown, United States

Club or Lounge
Up to 300 guests
$750
Oak Ridge Barn

Oak Ridge Barn

Hee-Haw City, Canada

Rustic or Alternative Venue
Up to 150 guests
$500
import { venueTypes, venues } from '@/lib/data/venues';import {  Badge,  Card,  Description,  Inline,  Stack,  Text,  Tiles,  Title,} from '@marigold/components';const featured = venues.slice(0, 3);export default () => (  <Tiles space="regular" tilesWidth="240px" stretch>    {featured.map(venue => (      <Card key={venue.id}>        <Card.Media>          <img            src={venue.image}            alt={venue.name}            className="h-40 w-full object-cover"          />        </Card.Media>        <Card.Header>          <Title>{venue.name}</Title>          <Description>            {venue.city}, {venue.country}          </Description>        </Card.Header>        <Card.Content>          <Stack space="tight">            <Inline space="related">              <Badge variant="info">{venueTypes[venue.type]}</Badge>            </Inline>            <Text variant="muted">              Up to {venue.capacity.toLocaleString()} guests            </Text>          </Stack>        </Card.Content>        <Card.Footer>          <Inline space="related" alignY="center">            <Text size="sm" weight="bold">              ${venue.price.from.toLocaleString()}            </Text>          </Inline>        </Card.Footer>      </Card>    ))}  </Tiles>);

The same shape works for any repeating content, like team directories with avatars, article previews with author metadata, or category pickers with no media at all. The identity-per-card pattern stays the same. Only the contents of each slot change.

Media

<Card.Media> is optional. Whether to include an image depends on whether the visual carries information.

Use an image preview when each item has its own visual identity, like an event poster, a venue photo, or a product hero. The image is part of how users recognize and choose between cards in a grid.

Annual Conference 2025

Annual Conference 2025

Our flagship annual event.

Music
Tickets available
Join us for a day of inspiring talks, workshops, and networking.
import {  Badge,  Button,  Card,  Description,  Inline,  Stack,  Text,  Title,} from '@marigold/components';export default () => (  <Card>    <Card.Media>      <img        src="https://images.pexels.com/photos/8761744/pexels-photo-8761744.jpeg"        alt="Annual Conference 2025"        className="h-60 w-full"      />    </Card.Media>    <Card.Header>      <Title>Annual Conference 2025</Title>      <Description>Our flagship annual event.</Description>    </Card.Header>    <Card.Content>      <Stack space="tight">        <Inline space="related">          <Badge variant="info">Music</Badge>          <Badge variant="success">Tickets available</Badge>        </Inline>        <Text variant="muted">          Join us for a day of inspiring talks, workshops, and networking.        </Text>      </Stack>    </Card.Content>    <Card.Footer>      <Button variant="ghost" size="small">        Get tickets      </Button>    </Card.Footer>  </Card>);

Do

Put images in <Card.Media> so they sit full-bleed at the top of the card.

Don't

Don't nest the card's main visual inside Card.Content. The padding cuts the image off from the card's edges and the framing falls apart.

Drop <Card.Media> when the content is text-driven, like a plan summary, a status block, or a quick stat with actions. A title and short body carry the meaning, and a generic stock image only adds noise without helping users decide.

Pro plan

Renews on June 1, 2026.

Current
Unlimited events, custom branding, and priority support.
import {  Badge,  Button,  Card,  Description,  Inline,  Text,  Title,} from '@marigold/components';export default () => (  <Card>    <Card.Header>      <Title>Pro plan</Title>      <Description>Renews on June 1, 2026.</Description>    </Card.Header>    <Card.Content>      <Inline space="tight" alignY="center">        <Badge variant="success">Current</Badge>        <Text variant="muted">          Unlimited events, custom branding, and priority support.        </Text>      </Inline>    </Card.Content>    <Card.Footer>      <Button variant="ghost" size="small">        Manage plan      </Button>    </Card.Footer>  </Card>);

Footer actions

Put actions in <Card.Footer> when users should be able to act on the item directly from the grid, without opening a detail page.

Use small buttons (<Button size="small" />). Cards sit in tight grid cells, and small buttons match the scale of the surrounding content. Reserve default-size buttons for page-level actions outside of cards.

Nested cards

Cards already sit on a raised surface. Nesting a card inside another card creates double elevation that no longer reads as depth. It's just a frame inside a frame. Restructure the inner content with a layout primitive like <Stack>, a <Divider>, or split the content into sibling sections.

Do

Restructure the inner content with <Stack> and <Divider> so a single card holds the sections.

Don't

Don't nest a card inside another card or sit it on any other raised surface.

Spacing and padding

Card controls two kinds of spacing, the padding applied to its slots, and the gap between slots. The defaults suit most card layouts. Reach for the overrides when a card is unusually dense or unusually roomy.

Padding

Every slot is inset with p="square-regular", mirroring Panel. Use square-loose for cards that hold long prose or stand alone on the page, and px/py to control the axes separately when uniform padding feels off.

<Card p="square-loose">…</Card>
<Card px="padding-relaxed" py="padding-snug">…</Card>

Slot gap

space controls the vertical gap between Media, Header, Content, and Footer. Default regular works almost everywhere. Drop to tight when the slots should read as one dense surface, or step up to group when the card carries several distinct blocks that need more breathing room.

<Card space="tight">…</Card>
<Card space="group">…</Card>

Bleed

<Card.Content> and <Card.Footer> accept a bleed prop that skips the card's horizontal padding for that slot. Use it for tables, media, or full-width action bars that should reach the card's edges.

<Card>
  <Card.Header>
    <Title>Pricing</Title>
  </Card.Header>
  <Card.Content bleed>
    <Table>…</Table>
  </Card.Content>
</Card>

Accessibility

Card renders an <article> and wires up its accessible name and heading level, so most of the work is handled for you. Give every card a name, pick the heading level that fits the page, and add list semantics when cards repeat in a grid.

Labeling

<Card> renders an <article> landmark. When a <Title> is present, the article is automatically labelled by it (aria-labelledby). Otherwise pass aria-label on the <Card> to give it an accessible name.

Always give a card a name. A <Card> with neither a <Title> nor an aria-label produces an unnamed article landmark, which screen reader users cannot identify. In development, Card logs a console.warn when both are missing.

Heading levels

The card's heading level comes from the headingLevel prop on <Card> (default 3). The default assumes a card grid living under a section-level <h2>, so a card title at <h3> keeps the document outline clean: page heading, then section heading, then card title.

If the grid sits deeper in the page, inside a <Tabs> panel or a <Panel headingLevel={3}>, step the card title down with <Card headingLevel={4}> so the outline still nests correctly.

Collection semantics

A card rarely appears alone. The canonical use is a grid of cards, and a repeating collection is semantically a list. Because <Tiles> accepts a role and an aria-label, mark the grid as a list and wrap each card in an element with role="listitem". Assistive technology then announces the item count and lets the user step through the set:

<Tiles
  role="list"
  aria-label="Venues"
  space="regular"
  tilesWidth="240px"
  stretch
>
  {venues.map(venue => (
    <div role="listitem" key={venue.id}>
      <Card>…</Card>
    </div>
  ))}
</Tiles>

The roles are set explicitly rather than on native <ul> and <li> tags. A <ul> styled as a grid usually carries list-style: none, and in Safari that removes the list's semantics. An explicit role="list" on the <Tiles> grid is not affected, so the list markup holds. Since <Card> is not polymorphic today, the list structure lives on the wrapper, not on the card. The card grid demo earlier on this page shows the per-card composition. Wrap that grid as shown here to add the collection semantics.

Props

Did you know? You can explore, test, and customize props live in Marigold's storybook. Watch the effects they have in real-time!
View Card stories

Card

Prop

Type

Accessibility props (54)

Prop

Type

DOM event handlers (164)

Prop

Type

Card.Media

Prop

Type

Card.Header

Prop

Type

Card.Content

Prop

Type

Card.Footer

Prop

Type

Alternative components

When your content isn't a good fit for a card, one of these is usually the right answer.

Another Collection component

  • <Table>: The other Collection component. Reach for it when items share the same fields and the task is comparison, sorting, or bulk action.

When the content isn't a collection

  • <Panel>: A unique, named page region like "Billing" or "Team members".

  • <Stack>: Content that shares a topic but has no per-item identity.

  • <Tiles>: A reflowing grid of layout blocks rather than collection items.

  • <List>: A simple ordered or unordered list of items.

When cards are selectable options

  • <SelectList>: Card-shaped options the user selects in a form, with selection state and keyboard support built in.

Related

SelectList

The selectable-card pattern. Use SelectList with variant="bordered" when each card is an option the user picks from.

Panel

The page-region counterpart to card. Use Panel for named, non-repeating sections like "Billing" or "Team members".

Elevation

This page should introduce you on how to use elevation with Marigold.

Admin- & master mark

Used for marking internal-only features.
Last update: 8 days ago

TimeField

Component for entering time in forms.

Table

Display and interact with structured data in rows and columns.

On this page

AnatomyAppearanceUsageCard vs TableSelectable cardsHeaderCard gridsMediaFooter actionsNested cardsSpacing and paddingAccessibilityLabelingHeading levelsCollection semanticsPropsCardCard.MediaCard.HeaderCard.ContentCard.FooterAlternative componentsRelated