Introduction
Components
- Accordion
- Action Sheet
- Alert
- Audio Player
- Audio Recorder
- Audio Waveform
- Avatar
- Badge
- BottomSheet
- Button
- Camera
- Camera Preview
- Card
- Carousel
- Checkbox
- Collapsible
- Color Picker
- Combobox
- Date Picker
- File Picker
- Gallery
- Hello Wave
- Icon
- Image
- Input
- Input OTP
- Link
- MediaPicker
- Mode Toggle
- Onboarding
- ParallaxScrollView
- Picker
- Popover
- Progress
- Radio
- ScrollView
- SearchBar
- Separator
- Share
- Sheet
- Skeleton
- Spinner
- Switch
- Table
- Tabs
- Text
- Toast
- Toggle
- Video
- View
Charts
import { Button } from '@/components/ui/button';
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { Text } from '@/components/ui/text';
import React from 'react';
export function CardDemo() {
return (
<Card>
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>
This is a description of the card content. It provides additional
context about what this card contains.
</CardDescription>
</CardHeader>
<CardContent>
<Text>
This is the main content area of the card. You can put any content
here including text, images, forms, or other components.
</Text>
</CardContent>
<CardFooter>
<Button variant='outline'>Cancel</Button>
<Button style={{ flex: 1 }}>Confirm</Button>
</CardFooter>
</Card>
);
}
Installation
pnpm dlx bna-ui add card
Usage
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card';
<Card>
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card Description</CardDescription>
</CardHeader>
<CardContent>
<p>Card Content</p>
</CardContent>
<CardFooter>
<p>Card Footer</p>
</CardFooter>
</Card>
Examples
Default
import { Button } from '@/components/ui/button';
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { Text } from '@/components/ui/text';
import React from 'react';
export function CardDemo() {
return (
<Card>
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>
This is a description of the card content. It provides additional
context about what this card contains.
</CardDescription>
</CardHeader>
<CardContent>
<Text>
This is the main content area of the card. You can put any content
here including text, images, forms, or other components.
</Text>
</CardContent>
<CardFooter>
<Button variant='outline'>Cancel</Button>
<Button style={{ flex: 1 }}>Confirm</Button>
</CardFooter>
</Card>
);
}
Simple
import { Card, CardContent } from '@/components/ui/card';
import { Text } from '@/components/ui/text';
import React from 'react';
export function CardSimple() {
return (
<Card>
<CardContent>
<Text>
A simple card with just content. Perfect for displaying basic
information or messages.
</Text>
</CardContent>
</Card>
);
}
With Image
import { Button } from '@/components/ui/button';
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
import React from 'react';
import { Image } from 'react-native';
export function CardWithImage() {
return (
<Card>
<View style={{ borderRadius: 26, overflow: 'hidden', marginBottom: 16 }}>
<Image
source={{ uri: 'https://picsum.photos/350/200' }}
style={{ width: '100%', height: 300 }}
resizeMode='cover'
/>
</View>
<CardHeader>
<CardTitle>Beautiful Landscape</CardTitle>
<CardDescription>
A stunning view captured in the mountains during golden hour.
</CardDescription>
</CardHeader>
<CardContent>
<Text>
This image showcases the beauty of nature with its vibrant colors and
serene atmosphere.
</Text>
</CardContent>
<CardFooter>
<Button variant='outline'>Share</Button>
<Button>Download</Button>
</CardFooter>
</Card>
);
}
With Form
import { Button } from '@/components/ui/button';
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
import { useThemeColor } from '@/hooks/useThemeColor';
import React, { useState } from 'react';
import { TextInput } from 'react-native';
export function CardWithForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const borderColor = useThemeColor({}, 'border');
const backgroundColor = useThemeColor({}, 'background');
const textColor = useThemeColor({}, 'text');
return (
<Card>
<CardHeader>
<CardTitle>Sign In</CardTitle>
<CardDescription>
Enter your credentials to access your account.
</CardDescription>
</CardHeader>
<CardContent>
<View style={{ gap: 16 }}>
<View>
<Text style={{ marginBottom: 8, fontWeight: '500' }}>Email</Text>
<TextInput
value={email}
onChangeText={setEmail}
placeholder='Enter your email'
style={{
borderWidth: 1,
borderColor,
borderRadius: 999,
padding: 12,
backgroundColor,
color: textColor,
}}
keyboardType='email-address'
autoCapitalize='none'
/>
</View>
<View>
<Text style={{ marginBottom: 8, fontWeight: '500' }}>Password</Text>
<TextInput
value={password}
onChangeText={setPassword}
placeholder='Enter your password'
secureTextEntry
style={{
borderWidth: 1,
borderColor,
borderRadius: 999,
padding: 12,
backgroundColor,
color: textColor,
}}
/>
</View>
</View>
</CardContent>
<CardFooter>
<Button variant='outline'>Cancel</Button>
<Button>Sign In</Button>
</CardFooter>
</Card>
);
}
Statistics
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
import React from 'react';
export function CardStats() {
const stats = [
{ title: 'Total Users', value: '12,543', change: '+12%' },
{ title: 'Revenue', value: '$45,231', change: '+8%' },
{ title: 'Orders', value: '1,234', change: '+23%' },
{ title: 'Growth', value: '15.3%', change: '+4%' },
];
return (
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 16 }}>
{stats.map((stat, index) => (
<Card key={index} style={{ flex: 1, minWidth: 150 }}>
<CardHeader>
<CardTitle style={{ fontSize: 16 }}>{stat.title}</CardTitle>
</CardHeader>
<CardContent>
<Text style={{ fontSize: 24, fontWeight: 'bold', marginBottom: 4 }}>
{stat.value}
</Text>
<Text style={{ color: '#22c55e', fontSize: 14 }}>
{stat.change} from last month
</Text>
</CardContent>
</Card>
))}
</View>
);
}
Notification
import { Button } from '@/components/ui/button';
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { Icon } from '@/components/ui/icon';
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
import { Bell } from 'lucide-react-native';
import React from 'react';
export function CardNotification() {
return (
<Card style={{ maxWidth: 400 }}>
<CardHeader>
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 12 }}>
<View
style={{
width: 40,
height: 40,
borderRadius: 20,
backgroundColor: '#3b82f6',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Icon name={Bell} color='white' size={20} />
</View>
<View style={{ flex: 1 }}>
<CardTitle>New Notification</CardTitle>
<CardDescription>2 minutes ago</CardDescription>
</View>
</View>
</CardHeader>
<CardContent>
<Text>
You have a new message from John Doe. Click to view the full
conversation and respond.
</Text>
</CardContent>
<CardFooter>
<Button variant='outline'>Dismiss</Button>
<Button>View Message</Button>
</CardFooter>
</Card>
);
}
Pricing
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { Icon } from '@/components/ui/icon';
import { Text } from '@/components/ui/text';
import { View } from '@/components/ui/view';
import { Check } from 'lucide-react-native';
import React from 'react';
export function CardPricing() {
const plans = [
{
name: 'Basic',
price: '$9',
description: 'Perfect for individuals',
features: ['1 Project', '5GB Storage', 'Email Support'],
popular: false,
},
{
name: 'Pro',
price: '$29',
description: 'Best for small teams',
features: [
'10 Projects',
'100GB Storage',
// 'Priority Support',
// 'Advanced Analytics',
],
popular: true,
},
{
name: 'Enterprise',
price: '$99',
description: 'For large organizations',
features: [
'Unlimited Projects',
'1TB Storage',
// '24/7 Support',
// 'Custom Integrations',
],
popular: false,
},
];
return (
<View style={{ flexDirection: 'row', gap: 16, flexWrap: 'wrap' }}>
{plans.map((plan, index) => (
<Card
key={index}
style={{
flex: 1,
minWidth: 250,
borderWidth: plan.popular ? 2 : 1,
borderColor: plan.popular ? '#3b82f6' : undefined,
}}
>
<CardHeader>
<View style={{ alignItems: 'center' }}>
{plan.popular && (
<View
style={{
backgroundColor: '#3b82f6',
paddingHorizontal: 12,
paddingVertical: 4,
borderRadius: 12,
marginBottom: 8,
}}
>
<Text
style={{ color: 'white', fontSize: 12, fontWeight: '600' }}
>
POPULAR
</Text>
</View>
)}
<CardTitle>{plan.name}</CardTitle>
<CardDescription>{plan.description}</CardDescription>
<Text style={{ fontSize: 32, fontWeight: 'bold', marginTop: 8 }}>
{plan.price}
<Text style={{ fontSize: 16, fontWeight: 'normal' }}>
/month
</Text>
</Text>
</View>
</CardHeader>
<CardContent>
<View style={{ gap: 8 }}>
{plan.features.map((feature, featureIndex) => (
<View
key={featureIndex}
style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}
>
<Icon name={Check} color='#22c55e' size={16} />
<Text>{feature}</Text>
</View>
))}
</View>
</CardContent>
{/* <CardFooter>
<Button
variant={plan.popular ? 'default' : 'outline'}
style={{ width: '100%' }}
>
Get Started
</Button>
</CardFooter> */}
</Card>
))}
</View>
);
}
API Reference
Card
The main container component that wraps all card content.
Prop | Type | Default | Description |
---|---|---|---|
children | ReactNode | - | The card content (typically header/content/footer). |
style | ViewStyle | - | Additional styles to apply to the card container. |
CardHeader
Container for the card's header content, typically containing title and description.
Prop | Type | Default | Description |
---|---|---|---|
children | ReactNode | - | The header content (typically CardTitle/CardDescription). |
style | ViewStyle | - | Additional styles to apply to the header container. |
CardTitle
The main title text of the card.
Prop | Type | Default | Description |
---|---|---|---|
children | ReactNode | - | The title text content. |
style | TextStyle | - | Additional styles to apply to the title text. |
CardDescription
Subtitle or description text for the card.
Prop | Type | Default | Description |
---|---|---|---|
children | ReactNode | - | The description text content. |
style | TextStyle | - | Additional styles to apply to the description text. |
CardContent
Container for the main content of the card.
Prop | Type | Default | Description |
---|---|---|---|
children | ReactNode | - | The main content of the card. |
style | ViewStyle | - | Additional styles to apply to the content container. |
CardFooter
Container for the card's footer content, typically containing actions or additional info.
Prop | Type | Default | Description |
---|---|---|---|
children | ReactNode | - | The footer content (typically buttons or actions). |
style | ViewStyle | - | Additional styles to apply to the footer container. |
Design Guidelines
Visual Hierarchy
Cards help establish clear visual hierarchy in your interface:
- Use CardTitle for the primary heading (larger, bolder text)
- Use CardDescription for supporting information (smaller, muted text)
- Organize content logically from header to content to footer
Layout Patterns
Cards work well in various layout patterns:
- Single cards for focused content or forms
- Card grids for displaying multiple related items
- Card lists for sequential content like notifications
- Dashboard cards for metrics and statistics
Content Guidelines
- Keep titles concise and descriptive
- Use descriptions to provide context without overwhelming
- Place primary actions in the footer
- Ensure adequate spacing between sections
Accessibility
The Card component follows accessibility best practices:
- Semantic structure for screen readers
- Proper text hierarchy with heading roles
- Adequate contrast ratios for all text
- Touch-friendly interactive elements
- Keyboard navigation support
Responsive Design
Cards automatically adapt to different screen sizes:
- Flexible width that responds to container constraints
- Proper text scaling on different devices
- Consistent spacing across all screen sizes
- Touch-optimized interactive elements