Skip to main content

Card

Card is a surface for grouping related content, like a project summary or a settings option. It can act as a link or button and show a selected state.

Import

import { Card } from '@vortexlabs/vortex';
import type { CardProps } from '@vortexlabs/vortex';

Display

<Card>{children}</Card>

Other links

Team workspace
Manage projects, members, and shared resources.
<Card
  padding="lg"
  borderRadius="md"
  width="320px"
  selected={false}
>
  <Stack gap={2}>
  <Text weight="medium">Team workspace</Text>
  <Text color="subtle">Manage projects, members, and shared resources.</Text>
</Stack>
</Card>

Features

  • Groups related content on a bordered surface.
  • Supports responsive size, padding, and corner radius.
  • Acts as a link or button with href or onClick.
  • Shows a selected state you control.

Content

Put content inside the card and arrange it with a layout primitive such as Stack. Use as to render a semantic element like article.

Team workspace

Manage projects, members, and shared resources.
import { Card, Stack, Text } from "@vortexlabs/vortex";

<Card as="article" width="100%">
  <Stack gap={2}>
    <Text as="h3" size="heading-sm-desktop">Team workspace</Text>
    <Text>Manage projects, members, and shared resources.</Text>
  </Stack>
</Card>

Padding

Use padding to set the space between the content and the border. The default is lg.

Compact content
Standard content
Spacious content
<Card padding="xs">Compact content</Card>
<Card padding="md">Standard content</Card>
<Card padding="lg">Spacious content</Card>

Responsive Sizing

Combine a fluid width with maxWidth to constrain a card. Dimensions and padding also accept breakpoint objects.

Project activity
A fluid card with a maximum width and responsive padding.
<Card width="100%" maxWidth="28rem" padding={{ xs: "sm", md: "lg" }}>
  <Stack gap={2}>
    <Text weight="medium">Project activity</Text>
    <Text color="subtle">A fluid card with a maximum width and responsive padding.</Text>
  </Stack>
</Card>

Border Radius

Set borderRadius to a radius token or none. The default is md.

No radius
Medium radius
Extra-large radius
<Card borderRadius="none">No radius</Card>
<Card borderRadius="md">Medium radius</Card>
<Card borderRadius="xl">Extra-large radius</Card>

Pass href to make the whole card a link. Keep its contents non-interactive so the card has a single destination.

<Card href="/docs/quick-start" width="100%">
  <Stack gap={2}>
    <Text as="span" weight="medium">Quick Start</Text>
    <Text as="span" color="subtle">Install Vortex and render your first component.</Text>
  </Stack>
</Card>

Visual Buttons

To show a button inside a link card, render it with as="span" and no onClick. It looks like a button, but the card stays the only link.

<Card href="/docs/quick-start" width="100%">
  <Stack direction="row" justify="space-between" align="center" gap={3}>
    <Text as="span" weight="medium">Quick Start</Text>
    <Button as="span" variant="secondary" size="sm">Start building</Button>
  </Stack>
</Card>

Selected Cards

With onClick, the card renders as a button. selected only changes its appearance, so keep the state yourself and set aria-pressed for a toggle.

"use client";

import { useState } from "react";
import { Card, Stack, Text } from "@vortexlabs/vortex";

export const SelectableCard = () => {
  const [selected, setSelected] = useState(false);

  return (
    <Card
      selected={selected}
      onClick={() => setSelected(!selected)}
      attributes={{ "aria-pressed": selected }}
      width="100%"
    >
      <Stack gap={2}>
        <Text as="span" weight="medium">
          Weekly digest
        </Text>
        <Text as="span" color="subtle">
          {selected
            ? "Included in your notifications"
            : "Include in your notifications"}
        </Text>
      </Stack>
    </Card>
  );
};

Accessibility

Key
Description
Enter
Pressing Enter while a card with href is focused follows the link.
EnterSpace
Pressing Enter or Space while a card with onClick is focused activates it.
A static card adds no role; use as and headings inside it for structure.
Nested buttons in a card with href or onClick must be visual only (as="span", no onClick).
When a card with onClick uses selected, set a state attribute such as aria-pressed.