Skip to content

Surfaces

Card

A Surface with a header, padding and an optional link: the default container for content sections.

<script>
  import { Card } from "@codeatlasdev/ui";
</script>

<Card title="Team" headingLevel={2} tone="brand">…</Card>

Card is a Surface with a header (title, headerActions), padding from --ca-card-padding and an optional link. Every Surface prop passes through (elevation, material, tone, variant, radius, glow, interactive), and material="auto" follows the theme: opaque under the default solid style, glass under liquid. The demos below set material="glass" so they look the same under any style. Use flush for content that touches the edges, such as tables, images and code.

The content is already padded. Card pads its children with --ca-card-padding (20px). A wrapper that adds its own padding (<Card><div class="box">…</div></Card> with .box { padding: 1.25rem }) doubles it to 40px, the usual cause of an oversized card. Remove the wrapper padding, pick a density with padding ('none', 'sm', 'md', 'lg', a CSS length or a number of pixels), or use flush when you bring your own layout. In development a [ca-ui] warning names the mistake when the first child is padded. To change the default for the whole app, override --ca-card-padding on :root.

title is a paragraph unless you pass headingLevel, so adding a Card never changes a page outline by accident. Pass headingLevel to make the card a section under the page heading (a PageShell title is the <h1>, so cards start at 2). Only the tag changes, never the look.

With href the card is a single <a> and is interactive. The link name comes from the content, so give the card a title.

#069

Content card

Text-heavy card with eyebrow, title, body and a link.

Featured

Liquid Glass materials

Depth and clarity for UI surfaces through real-time backdrop blur and optical refraction.

Explore materials →

Reference #069 · Pick in the gallery

Code
svelte
<script lang="ts">
  import { Card } from '@codeatlasdev/ui';
</script>

<Card material="glass" class="content-card">
  <div class="body">
    <p class="eyebrow">Featured</p>
    <h3>Liquid Glass materials</h3>
    <p class="text">
      Depth and clarity for UI surfaces through real-time backdrop blur and optical refraction.
    </p>
    <a href="/docs/foundation/materials/">Explore materials →</a>
  </div>
</Card>

<style>
  :global(.content-card) { max-width: 360px; width: 100%; }
  .body { display: flex; flex-direction: column; gap: var(--ca-space-2); }
  .eyebrow {
    margin: 0;
    font-size: var(--ca-font-size-caption);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ca-brand-text);
  }
  h3 { margin: 0; font-size: var(--ca-font-size-h5); font-weight: 600; color: var(--ca-text-primary); }
  .text { margin: 0; font-size: var(--ca-font-size-body2); color: var(--ca-text-secondary); line-height: 1.5; }
  a { font-size: var(--ca-font-size-body2); font-weight: 500; color: var(--ca-brand-text); text-decoration: none; }
  a:hover { text-decoration: underline; }
</style>
#072

Stat cards

Compact metric display.

Components

70+

Svelte 5

Presets

8

Amber, Ocean, Crimson and more

Tokens

80+

CSS custom properties

Reference #072 · Pick in the gallery

Code
svelte
<script lang="ts">
  import { Card } from '@codeatlasdev/ui';

  const stats = [
    { label: 'Components', value: '70+', delta: 'Svelte 5' },
    { label: 'Presets', value: '8', delta: 'Amber, Ocean, Crimson and more' },
    { label: 'Tokens', value: '80+', delta: 'CSS custom properties' },
  ];
</script>

<div class="grid">
  {#each stats as s}
    <Card material="glass" class="stat">
      <p class="label">{s.label}</p>
      <p class="value">{s.value}</p>
      <p class="delta">{s.delta}</p>
    </Card>
  {/each}
</div>

<style>
  .grid { display: flex; flex-wrap: wrap; gap: var(--ca-space-3); width: 100%; }
  :global(.stat) { flex: 1; min-width: 140px; }
  .label {
    margin: 0 0 4px;
    font-size: var(--ca-font-size-caption);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ca-text-secondary);
  }
  .value { margin: 0 0 4px; font-size: var(--ca-font-size-h3); font-weight: 700; line-height: 1.1; color: var(--ca-text-primary); }
  .delta { margin: 0; font-size: var(--ca-font-size-caption); color: var(--ca-brand-text); }
</style>
#068

Tone and glow

`tone="brand"` tints the fill. `glow` adds a halo that only shows under styles that keep one, such as `glass`.

Tinted

Brand tint over the fill.

Glowing

Brand halo behind the surface.

Reference #068 · Pick in the gallery

Code
svelte
<script lang="ts">
  import { Card } from '@codeatlasdev/ui';
</script>

<div class="row">
  <Card material="glass" tone="brand" class="accent">
    <p class="title">Tinted</p>
    <p class="text">Brand tint over the fill.</p>
  </Card>
  <Card material="glass" glow class="accent">
    <p class="title">Glowing</p>
    <p class="text">Brand halo behind the surface.</p>
  </Card>
</div>

<style>
  .row { display: flex; flex-wrap: wrap; gap: var(--ca-space-3); width: 100%; }
  :global(.accent) { flex: 1; min-width: 200px; }
  .title { margin: 0 0 4px; font-size: var(--ca-font-size-h5); font-weight: 600; color: var(--ca-text-primary); }
  .text { margin: 0; font-size: var(--ca-font-size-body2); color: var(--ca-text-secondary); }
</style>
#070

Header and actions

`title` and `headerActions` render a built-in header row.

Team members

Use title and headerActions for a built-in card header.

Reference #070 · Pick in the gallery

Code
svelte
<script lang="ts">
  import { Card, Button } from '@codeatlasdev/ui';
</script>

<Card material="glass" title="Team members" class="titled">
  {#snippet headerActions()}<Button size="sm" variant="outlined">Invite</Button>{/snippet}
  <p>Use <code>title</code> and <code>headerActions</code> for a built-in card header.</p>
</Card>

<style>
  :global(.titled) { max-width: 420px; width: 100%; }
  p { margin: 0; font-size: var(--ca-font-size-body2); color: var(--ca-text-secondary); }
</style>
#071

`href` renders the whole card as a link.

Reference #071 · Pick in the gallery

Code
svelte
<script lang="ts">
  import { Card } from '@codeatlasdev/ui';
</script>

<Card href="/docs/surfaces/surface/" title="Surface" headingLevel={3} material="solid" elevation={2}>
  The one painted container every card is built on. The whole card is the link.
</Card>

Props

PropTypeDefaultDescription
titlestringundefinedHeader title.
headingLevel2 | 3 | 4 | 5 | 6undefinedRenders `title` as `<h2>`–`<h6>` so the card is a section in the page outline. Omit for a plain paragraph.
headerActionsSnippetundefinedActions aligned to the end of the header.
hrefstringundefinedRenders the card as a link (`<a>`, interactive).
targetstringundefinedLink target. `_blank` also sets `rel="noopener noreferrer"`.
padding'none' | 'sm' | 'md' | 'lg' | string | number'md'Content padding: 0, 12px, 20px, 32px, or a CSS length / number of pixels. Sets `--ca-card-padding` on this card only.
flushbooleanfalseRemoves all padding. Alias of `padding="none"`, and wins over `padding`.
fullbooleanfalseSets `width: 100%`.
elevation, material, tone, variant, radius, glow, interactiveSurface propssee SurfacePassed to the underlying [Surface](/docs/surfaces/surface/).
skeletonbooleanfalseLoading placeholder: content keeps its layout but is hidden, so the card has the exact loaded size. See Skeleton.
classstring''Extra class names.
childrenSnippetundefinedCard content.