Skip to content

Card ​

A card groups content that belongs together and gives it a surface of its own. It is also a surface in the technical sense: anything inside it that picks its colours from what it sits on reads the card rather than the page.

ts
import { Card } from "ropav";

Weekly report

Sent every Monday at 9am.

Open rate held steady across the last four sends.
variant
template
<Card class="w-80">
  <CardHeader>
    <CardTitle>Weekly report</CardTitle>
    <CardDescription>Sent every Monday at 9am.</CardDescription>
  </CardHeader>
  <CardContent>Open rate held steady across the last four sends.</CardContent>
</Card>

Composition ​

The parts are optional and unordered — a card is whatever you put in it. CardHeader groups a title with its description; CardFooter is where actions go.

Weekly report

Sent every Monday at 9am.

Open rate held steady across the last four sends.
card-composition.vue
vue
<script setup lang="ts">
import {
  Button,
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "ropav";
</script>

<template>
  <Card class="card">
    <CardHeader>
      <CardTitle>Weekly report</CardTitle>
      <CardDescription>Sent every Monday at 9am.</CardDescription>
    </CardHeader>

    <CardContent>Open rate held steady across the last four sends.</CardContent>

    <CardFooter>
      <Button size="sm">View</Button>
      <Button size="sm" variant="tertiary">Pause</Button>
    </CardFooter>
  </Card>
</template>

<style scoped>
.card {
  width: calc(var(--rp-spacing) * 80);
}
</style>

Variants ​

default, secondary and tertiary step back one surface at a time. Which one to use depends on what the card is sitting on: a card on the page body wants default, a card inside another card wants the next one along.

default

Sits one step further back than the one before it.

secondary

Sits one step further back than the one before it.

tertiary

Sits one step further back than the one before it.
card-variants.vue
vue
<script setup lang="ts">
import { Card, CardContent, CardTitle } from "ropav";
</script>

<template>
  <Card
    v-for="variant in ['default', 'secondary', 'tertiary'] as const"
    :key="variant"
    class="card"
  >
    <CardTitle>{{ variant }}</CardTitle>
    <CardContent>Sits one step further back than the one before it.</CardContent>
  </Card>
</template>

<style scoped>
.card {
  width: calc(var(--rp-spacing) * 52);
}
</style>

transparent is the fourth, and it is different in kind: it paints no fill of its own, so it shows whatever is behind it and passes that surface on to its descendants rather than claiming one. Reach for it when the card is only there for its spacing.

TIP

Anything sitting on a surface that may be see-through has to be built from tokens that hold their contrast against an unknown fill — see Translucent surfaces.

API ​

Card

PropTypeDefaultDescription
variant"default" | "secondary" | "tertiary" | "transparent""default"Visual variant.

Slots: default.

CardContent

Slots: default.

CardDescription

Slots: default.

CardFooter

Slots: default.

CardHeader

Slots: default.

CardTitle

Slots: default.