Components

Components

Cards

Fourteen variants on one set of tokens. Any of these will take your palette, corner radius and typeface without being rewritten.

Basic

Card

Card

Title and description. The base every other variant extends.

astro-stone-starter

  • --surface-raised
  • --line
  • --ink
  • --muted
  • --rounding-card
Card with action

Card with action

Adds a single call to action at the foot.

Learn more

astro-stone-starter

  • --accent-deep
  • --rounding-button
Icon card

Icon card

Leads with an icon. For service or capability lists.

sjgwebdev

The icon tile takes accent + accentInk rather than ink, so it stays legible when the card lands on an inverted band.

  • --accent
  • --accent-ink
  • --rounding-card
Outlined card

Outlined card

No fill. Sits directly on the page for lower-emphasis groups.

astro-demo3-starter

  • --line-strong
  • --rounding-card

With media

Media card

Media card

Image above the copy. The default for any listing grid.

perth.local

The image fades in on its own onload, separately from any scroll reveal — the card can be visible while the picture arrives. A cached image fires load before the handler attaches, so also repair `complete && naturalWidth > 0` after hydration.

  • --rounding-card
  • --surface-raised
  • --line

images-and-lcp.md

Media card with meta

Category ·

Media card with meta

Adds a category and a date above the title. For editorial.

perth.local

  • --accent-deep
  • --muted
  • --typeface-mono
Overlay card
Category

Overlay card

Label sits on the image. For dense category grids.

perth.local

The chip takes the theme-INVARIANT panel pair, not ink/surface — it sits on a photograph in both themes, so a theme-following colour would vanish in one of them.

  • --panel
  • --panel-ink
  • --rounding-card
Media card with tags

Media card with tags

Chips under the title for time, diet or difficulty.

20 minsTagTag

astro-demo6-starter

  • --surface-alt
  • --line
  • --muted

Pricing & feature

Pricing card

Pricing card

Price, unit and a feature list.

$00 per unit

  • Feature line one
  • Feature line two
  • Feature line three
Ask about this

astro-demo4-starter

Price is a display STRING, never a number — 'from $80' and 'POA' are real answers a numeric type cannot hold. Sort by an explicit `order` field instead.

  • --ink
  • --muted
  • --line
  • --accent-deep

content-collections.md

Pricing card, featured

astro-demo4-starter

Emphasis is an accent border plus a flag, NOT a dark slab. A black card in the middle of a row reads as a different component rather than the same card emphasised. Two featured cards makes the flag meaningless.

  • --accent
  • --accent-ink
  • --accent-deep
Feature card

Feature card

A capability, with a two-column list of what it includes. Wide enough to carry three lines of description without the columns collapsing.

  • Included item
  • Included item
  • Included item
  • Included item
  • Included item
  • Included item
See examples

sjgwebdev

  • --accent
  • --accent-ink
  • --line
  • --rounding-panel

Rows, people & quotes

Row card

astro-demo2-starter

The trailing value is written LAST in the DOM but placed top-right with grid-template-areas, so reading order stays 'what it is, then what it costs'. Using `order` would move it for keyboard focus too. One <a> with an explicit aria-label, so a screen reader announces one link rather than three.

  • --surface-raised
  • --line
  • --ink
  • --muted
List item

List item

No card at all — a hairline-separated entry with meta and tags.

· 2 min read · #tag#tag

Second entry

Shows how consecutive items separate without a border each.

· 4 min read · #tag

astro-demo7-starter

  • --line
  • --ink
  • --muted
  • --accent-deep
Profile card

Profile card

Role or title

Avatar, name and role. For team and author blocks.

astro-stone-starter

  • --surface-alt
  • --line
  • --muted
Quote card
A testimonial with attribution, about as long as one of these should ever be.
Name
Role, Company

astro-demo4-starter

Real testimonials only. Invented prices read as placeholders; invented testimonials read as testimonials — this is the one piece of demo content that can genuinely mislead someone.

  • --accent
  • --ink
  • --muted

On a dark band

The same components, unchanged. The band reassigns the tokens underneath them — neither of these knows which ground it is on.

Card on panel

Card on panel

Proof the base card needs no dark variant.

Learn more

astro-demo8-starter

THE TRAP: `[data-invert] { --surface: var(--ink); --ink: var(--surface) }` does NOT work. Custom properties resolve after the cascade settles, so both var()s see the NEW values from the same block and the band renders one colour on itself. Emit `--base-*` tokens that nothing reassigns and swap against those.

  • --panel
  • --panel-ink
  • --panel-muted
  • --panel-line

config-contract.md

Stat card
00Label here
00Label here

astro-demo3-starter

  • --typeface-display
  • --panel-ink
  • --panel-muted

Elsewhere

Libraries worth a look when none of the above is the right shape. Nothing from these is copied in — anything worth having gets rebuilt against our own tokens.