Card
Generic container for grouping related components together.
#
Documentation
#
#
Usage
#

The majestic world of turtles
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
EllipsisMenuButton,
} from "@optiaxiom/react";
import {
Card,
CardHeader,
CardImage,
CardLink,
CardPreview,
} from "@optiaxiom/react/unstable";
import { IconLogout, IconPencil } from "@tabler/icons-react";
import Image from "next/image";
import beach from "@/demos/beach.jpg";
export function App() {
return (
<Card maxW="xs">
<CardPreview>
<CardImage asChild>
<Image
alt="brown glass bottle beside white book on blue and white textile"
priority
src={beach}
/>
</CardImage>
</CardPreview>
<CardHeader
addonAfter={
<DropdownMenu>
<DropdownMenuTrigger asChild>
<EllipsisMenuButton
appearance="subtle"
aria-label="actions"
size="sm"
/>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem icon={<IconPencil />}>Edit</DropdownMenuItem>
<DropdownMenuItem icon={<IconLogout />} intent="danger">
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
}
description="Unveiling the secrets."
>
<CardLink href="../">The majestic world of turtles</CardLink>
</CardHeader>
</Card>
);
}
#
Anatomy
#
import {
Card,
CardAction,
CardCheckbox,
CardFooter,
CardHeader,
CardImage,
CardLink,
CardPreview,
} from "@optiaxiom/react/unstable";
export default () => (
<Card>
<CardPreview>
<CardImage />
<CardCheckbox />
<CardAction />
</CardPreview>
<CardHeader>
<CardLink />
</CardHeader>
<CardFooter />
</Card>
);
#
Structure
#
Card has a basic structure containing the following parts:
CardPreview
: An optional media/thumbnail preview.CardHeader
: Contains the title and an optional short description along with slots for icons, actions, etc. on left/right side of the title.CardFooter
: Contains secondary information and sticks to the bottom of the card.
CardHeader
is the only required element - and all other elements are optional.
Preview
children
Header
#
Header
#
Use the CardHeader
component to add a title to cards.
The majestic world of turtles
import { Box } from "@optiaxiom/react";
import { Card, CardHeader } from "@optiaxiom/react/unstable";
export function App() {
return (
<Box maxW="sm" w="full">
<Card>
<CardHeader>The majestic world of turtles</CardHeader>
</Card>
</Box>
);
}
#
Description
#
Use the description
prop on CardHeader
to add short descriptions to cards.
The majestic world of turtles
import { Box } from "@optiaxiom/react";
import { Card, CardHeader } from "@optiaxiom/react/unstable";
export function App() {
return (
<Box maxW="sm" w="full">
<Card>
<CardHeader description="Unveiling the secrets.">
The majestic world of turtles
</CardHeader>
</Card>
</Box>
);
}
#
Addons
#
Use the addonAfter
prop on CardHeader
to add menus and other secondary actions after the title.
The majestic world of turtles
import {
Badge,
Box,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
EllipsisMenuButton,
} from "@optiaxiom/react";
import { Card, CardHeader } from "@optiaxiom/react/unstable";
import { IconLogout, IconPencil } from "@tabler/icons-react";
export function App() {
return (
<Box maxW="sm" w="full">
<Card>
<CardHeader
addonAfter={
<>
<Badge>On</Badge>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<EllipsisMenuButton
appearance="subtle"
aria-label="actions"
size="sm"
/>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem icon={<IconPencil />}>
Edit
</DropdownMenuItem>
<DropdownMenuItem icon={<IconLogout />} intent="danger">
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</>
}
>
The majestic world of turtles
</CardHeader>
</Card>
</Box>
);
}
Use the addonBefore
prop on CardHeader
to add icons or other visuals before the title.
The majestic world of turtles
import { Box } from "@optiaxiom/react";
import { Card, CardHeader } from "@optiaxiom/react/unstable";
import { IconFolder } from "@tabler/icons-react";
export function App() {
return (
<Box maxW="sm" w="full">
<Card>
<CardHeader addonBefore={<IconFolder />}>
The majestic world of turtles
</CardHeader>
</Card>
</Box>
);
}
#
Truncate
#
We can use the Text component to truncate header titles.
Step by step: How to brainstorm a creative marketing campaign (+ free template)
import { Box, Text } from "@optiaxiom/react";
import { Card, CardHeader } from "@optiaxiom/react/unstable";
export function App() {
return (
<Box maxW="xs" w="full">
<Card>
<CardHeader>
<Text lineClamp="1">
Step by step: How to brainstorm a creative marketing campaign (+
free template)
</Text>
</CardHeader>
</Card>
</Box>
);
}
#
Links
#
Use the CardLink
component to render links and make the whole card clickable.
import {
Box,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
EllipsisMenuButton,
} from "@optiaxiom/react";
import { Card, CardHeader, CardLink } from "@optiaxiom/react/unstable";
import { IconLogout, IconPencil } from "@tabler/icons-react";
export function App() {
return (
<Box maxW="sm" w="full">
<Card>
<CardHeader
addonAfter={
<DropdownMenu>
<DropdownMenuTrigger asChild>
<EllipsisMenuButton
appearance="subtle"
aria-label="actions"
size="sm"
/>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem icon={<IconPencil />}>Edit</DropdownMenuItem>
<DropdownMenuItem icon={<IconLogout />} intent="danger">
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
}
>
<CardLink href="../">The majestic world of turtles</CardLink>
</CardHeader>
</Card>
</Box>
);
}
#
Tooltip
#
We can combine this with the Text and Tooltip component to truncate header titles while also showing the full title in a tooltip.
Use the auto
prop on Tooltip
to only show a tooltip if the text is actually clipped.
import { Box, Text, Tooltip } from "@optiaxiom/react";
import { Card, CardHeader, CardLink } from "@optiaxiom/react/unstable";
export function App() {
return (
<Box maxW="xs" w="full">
<Card>
<CardHeader>
<Tooltip
auto
content="Step by step: How to brainstorm a creative marketing campaign (+ free template)"
>
<CardLink href="../">
<Text lineClamp="1">
Step by step: How to brainstorm a creative marketing campaign (+
free template)
</Text>
</CardLink>
</Tooltip>
</CardHeader>
</Card>
</Box>
);
}
#
Preview
#
Use the CardPreview
component to add a preview section for cards.
The majestic world of turtles
import { Card, CardHeader, CardPreview } from "@optiaxiom/react/unstable";
import { IconMusic } from "@tabler/icons-react";
export function App() {
return (
<Card size="224">
<CardPreview bg="bg.success" color="fg.default.inverse" flex="1">
<IconMusic size="32" />
</CardPreview>
<CardHeader>The majestic world of turtles</CardHeader>
</Card>
);
}
We can also use the CardImage
component to add thumbnail images for cards.

The majestic world of turtles
import { Box } from "@optiaxiom/react";
import {
Card,
CardHeader,
CardImage,
CardPreview,
} from "@optiaxiom/react/unstable";
import Image from "next/image";
import beach from "@/demos/beach.jpg";
export function App() {
return (
<Box maxW="xs" w="full">
<Card>
<CardPreview>
<CardImage asChild>
<Image
alt="brown glass bottle beside white book on blue and white textile"
priority
src={beach}
/>
</CardImage>
</CardPreview>
<CardHeader>The majestic world of turtles</CardHeader>
</Card>
</Box>
);
}
#
Overlay
#
Use the addonTopLeft
/addonTopRight
/addonBottomRight
/addonBottomLeft
props on CardPreview
to add checkbox and other tertiary actions to cards.
Checkbox
Checkbox and star button
import { Badge, Box, Button, Flex } from "@optiaxiom/react";
import {
Card,
CardCheckbox,
CardHeader,
CardPreview,
} from "@optiaxiom/react/unstable";
import { IconMusic, IconStar } from "@tabler/icons-react";
export function App() {
return (
<Flex flexDirection={["column", "row"]}>
<Card size="224">
<CardPreview addonTopLeft={<CardCheckbox />} bg="bg.page" flex="1">
<Box
bg="bg.default"
color="fg.success"
p="16"
rounded="md"
shadow="sm"
>
<IconMusic size="32" />
</Box>
</CardPreview>
<CardHeader>Checkbox</CardHeader>
</Card>
<Card size="224">
<CardPreview
addonBottomLeft={<Badge intent="warning">Duplicate</Badge>}
addonTopLeft={<CardCheckbox />}
addonTopRight={
<Button aria-label="Add to favorites" icon={<IconStar />} />
}
bg="bg.page"
flex="1"
>
<Box
bg="bg.default"
color="fg.success"
p="16"
rounded="md"
shadow="sm"
>
<IconMusic size="32" />
</Box>
</CardPreview>
<CardHeader>Checkbox and star button</CardHeader>
</Card>
</Flex>
);
}
Include the CardAction
component if you’d like the checkbox to be hidden until hovered or interacted with.
Hover over the card to see the checkbox:
Checkbox
Checkbox and star button
import { Badge, Box, Button, Flex } from "@optiaxiom/react";
import {
Card,
CardAction,
CardCheckbox,
CardHeader,
CardPreview,
} from "@optiaxiom/react/unstable";
import { IconMusic, IconStar } from "@tabler/icons-react";
export function App() {
return (
<Flex flexDirection={["column", "row"]}>
<Card size="224">
<CardPreview
addonTopLeft={
<CardAction>
<CardCheckbox />
</CardAction>
}
bg="bg.page"
flex="1"
>
<Box
bg="bg.default"
color="fg.success"
p="16"
rounded="md"
shadow="sm"
>
<IconMusic size="32" />
</Box>
</CardPreview>
<CardHeader>Checkbox</CardHeader>
</Card>
<Card size="224">
<CardPreview
addonBottomLeft={<Badge intent="warning">Duplicate</Badge>}
addonTopLeft={
<CardAction>
<CardCheckbox />
</CardAction>
}
addonTopRight={
<CardAction>
<Button aria-label="Add to favorites" icon={<IconStar />} />
</CardAction>
}
bg="bg.page"
flex="1"
>
<Box
bg="bg.default"
color="fg.success"
p="16"
rounded="md"
shadow="sm"
>
<IconMusic size="32" />
</Box>
</CardPreview>
<CardHeader>Checkbox and star button</CardHeader>
</Card>
</Flex>
);
}
#
Sortable
#
We can combine cards with the Sortable component to build a sortable list of cards.
1
Launch Scooter Beta Sign Up
2
Age Experiment
3
Multi-Armed Bandit for Images
App.tsx
"use client";
import { Button, EllipsisMenuButton, Flex, Text } from "@optiaxiom/react";
import {
Card,
CardHeader,
CardLink,
Menu,
MenuContent,
MenuTrigger,
Sortable,
SortableHandle,
SortableItem,
} from "@optiaxiom/react/unstable";
import { IconGripVertical } from "@tabler/icons-react";
import { useState } from "react";
import { data } from "./data";
export function App() {
const [items, setItems] = useState(() => Object.keys(data));
return (
<Sortable items={items} onItemsChange={setItems}>
{(items) =>
items.map((item, index) => (
<Flex flexDirection="row" key={item}>
<Text color="fg.secondary" fontSize="md" w="20">
{index + 1}
</Text>
<SortableItem asChild index={index} item={item}>
<Card flex="1">
<CardHeader
addonAfter={
<Menu options={[{ label: "Edit" }]}>
<MenuTrigger asChild>
<EllipsisMenuButton
appearance="subtle"
aria-label="actions"
ml="auto"
/>
</MenuTrigger>
<MenuContent />
</Menu>
}
addonBefore={
<SortableHandle
asChild
color="fg.tertiary"
transition="colors"
>
<Button appearance="subtle" icon={<IconGripVertical />} />
</SortableHandle>
}
description={data[item].description}
>
<CardLink href="data:,">{data[item].title}</CardLink>
</CardHeader>
</Card>
</SortableItem>
</Flex>
))
}
</Sortable>
);
}
#
Props
#
#
Card
#
Supports all Box props in addition to its own. Renders a <div>
element.
Prop |
---|
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details.
|
className
|
#
CardAction
#
Supports all Box props in addition to its own. Renders a <div>
element.
Prop |
---|
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details.
|
className
|
visible Control whether to always show the contents or only when user is hovering or interacting with them.
|
#
CardCheckbox
#
Supports all Checkbox props in addition to its own. Renders a <div>
element but forwards all props to a hidden <input>
element.
Prop |
---|
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details.
|
className
|
indeterminate Display a partially checked icon instead of the regular checkmark.
|
onCheckedChange Handler that is called when the checked state changes.
|
#
CardFooter
#
Supports all Box props in addition to its own. Renders a <div>
element.
Prop |
---|
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details.
|
className
|
#
CardHeader
#
Supports all Box props in addition to its own. Renders a <div>
element.
Prop |
---|
addonAfter Display content inside the header after
|
addonBefore Display content inside the header before
|
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details.
|
className
|
description Add secondary text after the primary title.
|
#
CardImage
#
Supports all Box props in addition to its own. Renders an <img>
element.
Prop |
---|
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details.
|
className
|
#
CardLink
#
Supports all Link props in addition to its own. Renders an <a>
element.
Prop |
---|
appearance Control the appearance by selecting between the different link types.
|
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details.
|
className
|
cover Whether to expand and fill up the whole area of the parent which has
|
disabled Whether to show disabled state and disable interactions.
|
external Show an external link icon and sets the correct rel/target attributes.
|
#
CardPreview
#
Supports all Box props in addition to its own. Renders a <div>
element.
Prop |
---|
addonBottomLeft Display content in the bottom-left corner of the preview panel.
|
addonBottomRight Display content in the bottom-right corner of the preview panel.
|
addonTopLeft Display content in the top-left corner of the preview panel.
|
addonTopRight Display content in the top-right corner of the preview panel.
|
asChild Change the default rendered element for the one passed as a child, merging their props and behavior. Read the Composition guide for more details.
|
className
|
#
Changelog
#
#
1.5.0
#
-
Renamed
CardOverflow
component toCardPreview
:// Before <Card> <CardOverflow /> </Card> // After <Card> <CardPreview /> </Card>
-
Removed
CardContent
component -
Combined
CardTitle
andCardDescription
into oneCardHeader
component:// Before <Card> <CardTitle>Sample Title</CardTitle> <CardDescription>Sample Description</CardDescription> </Card> // After <Card> <CardHeader description="Sample Description"> Sample Title </CardHeader> </Card>
#
0.12.1
#
- Added component