Basic Card
This is a standard elevated card
Cards contain content and actions about a single subject. They are surface containers that hold content and actions.
A flexible container component for grouping related content and actions.
Cards contain content and actions about a single subject. They are surface containers that hold content and actions.
"use client";
import { Button, Card, CardBody, CardFooter, CardHeader, Text } from '@photonix/ultimate';
import { MoreHorizontalOutline } from '@photonix/icons';
export default function CardBasicExample() {
return (
<Card w={350} maxW="100%">
<CardHeader
title="Basic Card"
subtitle="This is a standard elevated card"
action={<Button variant="tertiary" leadingIcon={<MoreHorizontalOutline />} />}
/>
<CardBody>
<Text variant="body-md" color="secondary">
Cards contain content and actions about a single subject. They are surface containers that hold content and actions.
</Text>
</CardBody>
<CardFooter>
<Button variant="secondary">Cancel</Button>
<Button>Submit</Button>
</CardFooter>
</Card>
);
}Prop | Type | Default | Description |
|---|---|---|---|
variant | CardVariant | 'elevated' | Card variant style |
orientation | "horizontal" | "vertical" | 'vertical' | Card orientation |
isHoverable | boolean | false | Whether the card is interactive (hover states) |
isClickable | boolean | false | Whether the card is clickable (cursor pointer) |
children | React.ReactNode | - | Children elements |
p | ResponsiveValue<SpacingToken> | - | Padding on all sides |
px | ResponsiveValue<SpacingToken> | - | Padding inline (left/right) |
py | ResponsiveValue<SpacingToken> | - | Padding block (top/bottom) |
pt | ResponsiveValue<SpacingToken> | - | Padding block start (top) |
pb | ResponsiveValue<SpacingToken> | - | Padding block end (bottom) |
pl | ResponsiveValue<SpacingToken> | - | Padding inline start (left) |
pr | ResponsiveValue<SpacingToken> | - | Padding inline end (right) |
m | ResponsiveValue<SpacingToken | "auto"> | - | Margin on all sides |
mx | ResponsiveValue<SpacingToken | "auto"> | - | Margin inline (left/right) |
my | ResponsiveValue<SpacingToken | "auto"> | - | Margin block (top/bottom) |
mt | ResponsiveValue<SpacingToken | "auto"> | - | Margin block start (top) |
mb | ResponsiveValue<SpacingToken | "auto"> | - | Margin block end (bottom) |
ml | ResponsiveValue<SpacingToken | "auto"> | - | Margin inline start (left) |
mr | ResponsiveValue<SpacingToken | "auto"> | - | Margin inline end (right) |
display | ResponsiveValue<DisplayValue> | - | CSS display property |
aspectRatio | ResponsiveValue<string | number> | - | Aspect Ratio |
flexDirection | ResponsiveValue<FlexDirection> | - | Flex direction |
flexWrap | ResponsiveValue<boolean | FlexWrap> | - | Flex wrap behavior |
flex | ResponsiveValue<string | number> | - | Shorthand for flex-grow, flex-shrink, flex-basis |
flexGrow | ResponsiveValue<number> | - | Flex grow factor |
flexShrink | ResponsiveValue<number> | - | Flex shrink factor |
flexBasis | ResponsiveValue<string | number> | - | Flex basis |
order | ResponsiveValue<number> | - | Order |
gap | ResponsiveValue<SpacingToken> | - | Gap between items |
columnGap | ResponsiveValue<SpacingToken> | - | Column gap |
rowGap | ResponsiveValue<SpacingToken> | - | Row gap |
alignItems | ResponsiveValue<AlignItems> | - | Align items (cross axis) |
alignContent | ResponsiveValue<string> | - | Align content (multiline) |
alignSelf | ResponsiveValue<AlignSelf> | - | Align self |
justifyContent | ResponsiveValue<JustifyContent> | - | Justify content (main axis) |
justifyItems | ResponsiveValue<string> | - | Justify items (grid) |
placeItems | ResponsiveValue<string> | - | Place items (align-items + justify-items) |
placeContent | ResponsiveValue<string> | - | Place content (align-content + justify-content) |
bg | ResponsiveValue<BackgroundToken> | - | Background color using public background tokens mapped to canonical surface vars |
pageBg | ResponsiveValue<PageBackgroundToken> | - | Page background using canonical background-* vars for page/root containers |
borderRadius | ResponsiveValue<RadiusToken> | - | Border radius using border-radius-* tokens |
shadow | ResponsiveValue<ShadowToken> | - | Box shadow using shadow-* tokens |
opacity | ResponsiveValue<number> | - | Opacity |
border | ResponsiveValue<string> | - | |
borderWidth | ResponsiveValue<number | BorderWidthToken> | - | |
borderStyle | ResponsiveValue<string> | - | |
borderColor | ResponsiveValue<string> | - | |
textAlign | ResponsiveValue<TextAlign> | - | |
fontSize | ResponsiveValue<string | number> | - | |
fontWeight | ResponsiveValue<string | number> | - | |
lineHeight | ResponsiveValue<string | number> | - | |
color | ResponsiveValue<string> | - | |
w | ResponsiveValue<string | number> | - | Width - accepts CSS value |
h | ResponsiveValue<string | number> | - | Height - accepts CSS value |
minW | ResponsiveValue<string | number> | - | Min width - accepts CSS value |
minH | ResponsiveValue<string | number> | - | Min height - accepts CSS value |
maxW | ResponsiveValue<string | number> | - | Max width - accepts CSS value |
maxH | ResponsiveValue<string | number> | - | Max height - accepts CSS value |
position | ResponsiveValue<Position> | - | CSS position property |
top | ResponsiveValue<string | number> | - | Top position |
right | ResponsiveValue<string | number> | - | Right position |
bottom | ResponsiveValue<string | number> | - | Bottom position |
left | ResponsiveValue<string | number> | - | Left position |
inset | ResponsiveValue<string | number> | - | Inset shortcut |
zIndex | ResponsiveValue<number> | - | Z-index |
overflow | ResponsiveValue<Overflow> | - | CSS overflow property |
overflowX | ResponsiveValue<Overflow> | - | CSS overflow-x property |
overflowY | ResponsiveValue<Overflow> | - | CSS overflow-y property |
cursor | ResponsiveValue<string> | - | |
pointerEvents | ResponsiveValue<string> | - | |
userSelect | ResponsiveValue<string> | - | |
transform | ResponsiveValue<string> | - | |
transition | ResponsiveValue<string> | - |
Prop | Type | Default | Description |
|---|---|---|---|
title | React.ReactNode | - | Card title |
subtitle | React.ReactNode | - | Card subtitle |
isVerified | boolean | - | Whether the entity is verified (shows a checkmark icon) |
action | React.ReactNode | - | Action element (e.g., menu button) |
avatar | React.ReactNode | - | Avatar or icon to display |
children | React.ReactNode | - | Children elements |
Prop | Type | Default | Description |
|---|---|---|---|
justify | "center" | "start" | "end" | "between" | 'end' | Justify content alignment |
children | React.ReactNode | - | Children elements |
Prop | Type | Default | Description |
|---|---|---|---|
position | "top" | "bottom" | "left" | "fill" | 'top' | Image position |
rounded | boolean | false | Whether to apply border radius to all corners |
Cards come in three main visual styles: elevated (default), outlined, and filled.
Elevated
Has shadow
Outlined
Has border
Filled
Has background
"use client";
import { Card, CardBody, Flex, Text } from '@photonix/ultimate';
export default function CardVisualStylesExample() {
return (
<Flex gap="md" wrap="wrap">
<Card variant="elevated" w={200}>
<CardBody>
<Text variant="title-sm">Elevated</Text>
<Text variant="body-sm" color="secondary">Has shadow</Text>
</CardBody>
</Card>
<Card variant="outlined" w={200}>
<CardBody>
<Text variant="title-sm">Outlined</Text>
<Text variant="body-sm" color="secondary">Has border</Text>
</CardBody>
</Card>
<Card variant="filled" w={200}>
<CardBody>
<Text variant="title-sm">Filled</Text>
<Text variant="body-sm" color="secondary">Has background</Text>
</CardBody>
</Card>
</Flex>
);
}Use the overlay variant for cards with a background image. The card adapts text color for readability.

1.2k

320
26
"use client";
import { Box, Button, Card, CardFooter, CardHeader, CardImage, Flex, HStack, IconButton, Text } from '@photonix/ultimate';
import { AddOutline, DownloadOutline, MoreVerticalOutline, UserOutline } from '@photonix/icons';
const LIGHT_IMAGE = '/card_nature.png';
const DARK_IMAGE = '/card_architecture.png';
export default function CardOverlayExample() {
return (
<Flex gap="md" wrap="wrap">
<Box w={300}>
<Card variant="overlay" h={400}>
<CardImage position="fill" src={DARK_IMAGE} alt="Architecture" />
<Box position="absolute" top={8} right={8} zIndex={2}>
<IconButton variant="tertiary" size="small" icon={<MoreVerticalOutline />} aria-label="More" />
</Box>
<div style={{ flex: 1 }} />
<CardHeader
title="Urban Architecture"
subtitle="Modern aesthetic for the urban explorer."
/>
<CardFooter justify="between">
<HStack gap="sm">
<HStack gap="4xs" align="center">
<UserOutline size={24} />
<Text variant="title-md">1.2k</Text>
</HStack>
</HStack>
<Button size="small" variant="primary" leadingIcon={<AddOutline />}>Follow</Button>
</CardFooter>
</Card>
</Box>
<Box w={300}>
<Card variant="overlay" h={400}>
<CardImage position="fill" src={LIGHT_IMAGE} alt="Light Demo" />
<Box position="absolute" top={8} right={8} zIndex={2}>
<IconButton variant="tertiary" size="small" icon={<MoreVerticalOutline />} aria-label="More" />
</Box>
<div style={{ flex: 1 }} />
<CardHeader
title="Nature Escape"
subtitle="Find peace in the quiet mountains."
/>
<CardFooter justify="between">
<HStack gap="sm">
<HStack gap="4xs" align="center">
<UserOutline size={24} />
<Text variant="title-md">320</Text>
</HStack>
<HStack gap="4xs" align="center">
<DownloadOutline size={24} />
<Text variant="title-md">26</Text>
</HStack>
</HStack>
<Button size="small" variant="primary" leadingIcon={<AddOutline />}>Follow</Button>
</CardFooter>
</Card>
</Box>
</Flex>
);
}Cards can be hoverable and clickable.
Hover me
I lift up on hover
Click me
I am clickable too
"use client";
import { Card, CardBody, Flex, Text } from '@photonix/ultimate';
export default function CardInteractiveExample() {
return (
<Flex gap="md" wrap="wrap">
<Card isHoverable w={200}>
<CardBody>
<Text variant="title-sm">Hover me</Text>
<Text variant="body-sm" color="secondary">I lift up on hover</Text>
</CardBody>
</Card>
<Card isHoverable isClickable w={200}>
<CardBody>
<Text variant="title-sm">Click me</Text>
<Text variant="body-sm" color="secondary">I am clickable too</Text>
</CardBody>
</Card>
</Flex>
);
}Inset the image with small padding and rounded corners for a framed look.

1.2k
"use client";
import { Box, Button, Card, CardFooter, CardHeader, CardImage, HStack, Text } from '@photonix/ultimate';
import { UserOutline } from '@photonix/icons';
export default function CardWithImageExample() {
return (
<Box maxW={360}>
<Card>
<Box p="2xs" pb="none">
<CardImage
rounded
src="/card_architecture.png"
alt="Architecture"
style={{ aspectRatio: '16/9' }}
/>
</Box>
<CardHeader
title="Modern Architecture"
isVerified
subtitle="Clean lines and minimalist design."
/>
<CardFooter justify="between">
<HStack gap="sm">
<HStack gap="4xs" align="center">
<UserOutline size={24} />
<Text variant="title-md">1.2k</Text>
</HStack>
</HStack>
<Button size="small">Read More</Button>
</CardFooter>
</Card>
</Box>
);
}A card where the image covers the top area completely without any padding.

842
"use client";
import { Box, Button, Card, CardFooter, CardHeader, CardImage, HStack, Text } from '@photonix/ultimate';
import { UserOutline } from '@photonix/icons';
export default function CardFullBleedExample() {
return (
<Box maxW={360}>
<Card>
<CardImage src="/card_nature.png" alt="Nature" style={{ aspectRatio: '16/9' }} />
<CardHeader
title="Mountain Serenity"
isVerified
subtitle="Exploring the peaceful peaks."
/>
<CardFooter justify="between">
<HStack gap="sm">
<HStack gap="4xs" align="center">
<UserOutline size={24} />
<Text variant="title-md">842</Text>
</HStack>
</HStack>
<Button size="small" variant="primary">Explore</Button>
</CardFooter>
</Card>
</Box>
);
}E-commerce style card with badges, ratings, and pricing displays.

Electronics
SALE
Studio Headphones Gen 3
$299.00
$350.00
"use client";
import { Box, Button, Card, CardBody, CardFooter, CardImage, HStack, Text, VStack } from '@photonix/ultimate';
export default function CardProductExample() {
return (
<Box maxW={300}>
<Card isHoverable>
<CardImage src="/card_architecture.png" alt="Headphones" style={{ aspectRatio: '1/1' }} />
<CardBody>
<VStack gap="xs">
<HStack justify="between" align="center">
<Text variant="body-sm" color="secondary">Electronics</Text>
<Box p="4xs" px="md" borderRadius="full" bg="secondary">
<Text variant="label-sm">SALE</Text>
</Box>
</HStack>
<Text variant="title-lg">Studio Headphones Gen 3</Text>
<HStack gap="xs" align="center">
<Text variant="title-lg" color="brand">$299.00</Text>
<Text variant="body-sm" color="secondary" style={{ textDecoration: 'line-through' }}>$350.00</Text>
</HStack>
</VStack>
</CardBody>
<CardFooter>
<Button isFullWidth variant="primary">Add to Bag</Button>
</CardFooter>
</Card>
</Box>
);
}Cards can be laid out horizontally, which is ideal for lists and search results.


4.8
"use client";
import { Box, Button, Card, CardFooter, CardHeader, CardImage, HStack, Text, VStack } from '@photonix/ultimate';
import { UserOutline } from '@photonix/icons';
const LIGHT_IMAGE = '/card_nature.png';
export default function CardHorizontalExample() {
return (
<VStack gap="md" w="100%">
<Card orientation="horizontal" h={180} w="100%">
<CardImage position="left" src={LIGHT_IMAGE} alt="Demo" style={{ width: 180 }} />
<VStack flexGrow={1} flexShrink={1} flexBasis="0%" align="stretch" minW={0}>
<CardHeader
title="Full Bleed Horizontal"
subtitle="Ideal for blog post previews or search results where the image needs to be prominent."
/>
<div style={{ flex: 1 }} />
<CardFooter justify="end">
<Button size="small" variant="secondary">Read Article</Button>
</CardFooter>
</VStack>
</Card>
<Card orientation="horizontal" h={180} w="100%">
<Box p="2xs" w={180} flexShrink={0}>
<CardImage
rounded
src={LIGHT_IMAGE}
alt="Demo"
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
/>
</Box>
<VStack flexGrow={1} flexShrink={1} flexBasis="0%" align="stretch" minW={0}>
<CardHeader
title="Inset Rounded Image"
subtitle="Horizontal layout with a padded and rounded image container."
/>
<div style={{ flex: 1 }} />
<CardFooter justify="between">
<HStack gap="sm" align="center">
<UserOutline size={20} />
<Text variant="body-md">4.8</Text>
</HStack>
<Button size="small" variant="tertiary">Quick View</Button>
</CardFooter>
</VStack>
</Card>
</VStack>
);
}
Social Post
Cards tailored for social feeds, featuring an avatar and multiple action buttons.
AW
Just deployed the new Photonix design system update. The automatic brightness detection for overlay cards is a game changer for UX.