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.
import { Card, CardHeader, CardBody, CardFooter, Button, Text } from '@photonix/ultimate';
<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
import { Card, CardBody, Text, Flex } from '@photonix/ultimate';
<Flex gap="md" wrap="wrap">
{/* Elevated (Default) */}
<Card variant="elevated" w={200}>
<CardBody>
<Text variant="title-sm">Elevated</Text>
<Text variant="body-sm" color="secondary">Has shadow</Text>
</CardBody>
</Card>
{/* Outlined */}
<Card variant="outlined" w={200}>
<CardBody>
<Text variant="title-sm">Outlined</Text>
<Text variant="body-sm" color="secondary">Has border</Text>
</CardBody>
</Card>
{/* Filled */}
<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 automatically analyzes the image brightness and adapts the text color for readability — no manual configuration needed.

1.2k

320
26
<Flex gap="md" wrap="wrap">
{/* Dark Image — text auto-switches to white */}
<Card variant="overlay" w={300} h={400}>
<CardImage position="fill" src={DARK_IMAGE} alt="Architecture" />
<Box style={{ 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="The intersection of architecture and the city."
/>
<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="secondary" leadingIcon={<AddOutline size={16} />}>Follow</Button>
</CardFooter>
</Card>
{/* Light Image — text stays dark automatically */}
<Card variant="overlay" w={300} h={400}>
<CardImage position="fill" src={LIGHT_IMAGE} alt="Light Demo" />
{/* ... contents ... */}
</Card>
</Flex>Cards can be hoverable and clickable.
Hover me
I lift up on hover
Click me
I'm clickable too
<Flex gap="md">
<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'm clickable too</Text>
</CardBody>
</Card>
</Flex>In this variant, the image is inset with a small padding (2xs) and rounded corners, creating a modern, framed look.

1.2k
<Card w={360}>
<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>A card where the image covers the top area completely without any padding, bleeding to the edges.

842
<Card w={360}>
<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>E-commerce style card with badges, ratings, and pricing displays.

Electronics
SALE
Studio Headphones Gen 3
$299.00
$350.00
<Card isHoverable w={300}>
<CardImage src="/card_architecture.png" style={{ aspectRatio: '1/1' }} />
{/* ... contents ... */}
</Card>Cards can be laid out horizontally, which is ideal for lists and search results.


4.8
<Card orientation="horizontal" h={160} w="100%">
<CardImage position="left" src="/path/to/image.jpg" style={{ width: 160 }} />
<VStack flexGrow={1} flexShrink={1} flexBasis="0%" align="stretch" minW={0}>
<CardHeader title="Card Title" subtitle="Description content..." />
<div style={{ flex: 1 }} />
<CardFooter justify="end">
<Button variant="secondary">Action</Button>
</CardFooter>
</VStack>
</Card>
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. 🚀