Card

The Card component is a versatile container for displaying content in a structured manner. It can include headers, bodies, footers, and supports various visual styles like shadows, radii, and blur effects.

Installation

$ cbui-cli install card

Import

index.tsx
1import { Card, CardHeader, CardBody, CardFooter, CardContext, useCardContext } from '@/crossbuildui/card'; 2// Ensure 'expo-blur' is installed and configured. 3// import { View, Text, Image } from 'react-native'; // For content 4// import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; // For icons

Basic Usage

Compose a card using CardHeader, CardBody, and CardFooter as children of the main Card component.

index.tsx
1<Card> 2 <CardHeader> 3 <Text style={{ fontSize: 18, fontWeight: 'bold' }}>Card Title</Text> 4 </CardHeader> 5 <CardBody> 6 <Text>This is the main content of the card. It can contain text, images, or any other components.</Text> 7 </CardBody> 8 <CardFooter> 9 <Button size="sm">Learn More</Button> 10 </CardFooter> 11</Card>

Shadows & Radius

Control the card's elevation and corner rounding with the shadow and radius props.

index.tsx
1<View style={{ flexDirection: 'row', justifyContent: 'space-around', flexWrap: 'wrap' }}> 2 <Card shadow="sm" radius="sm" style={{ width: 150, margin: 10 }}> 3 <CardBody><Text>Small Shadow, Small Radius</Text></CardBody> 4 </Card> 5 <Card shadow="md" radius="md" style={{ width: 150, margin: 10 }}> 6 <CardBody><Text>Medium Shadow (Default), Medium Radius (Default)</Text></CardBody> 7 </Card> 8 <Card shadow="lg" radius="lg" style={{ width: 150, margin: 10 }}> 9 <CardBody><Text>Large Shadow, Large Radius</Text></CardBody> 10 </Card> 11 <Card shadow="none" radius="none" style={{ width: 150, margin: 10 }}> 12 <CardBody><Text>No Shadow, No Radius</Text></CardBody> 13 </Card> 14</View>

Pressable Card

Make the card interactive by setting isPressable to true. You can handle press events with onPress and control background changes with changeBgOnPress.

index.tsx
1const [count, setCount] = useState(0); 2 3<Card 4 isPressable 5 onPress={() => setCount(count + 1)} 6 style={{ alignItems: 'center', padding: 20 }} 7> 8 <Text>Press me!</Text> 9 <Text>Pressed: {count} times</Text> 10</Card> 11 12// Without background change on press 13<Card isPressable changeBgOnPress={false} onPress={() => console.log('Pressed!')}> 14 <CardBody><Text>Pressable, no BG change</Text></CardBody> 15</Card>

Blurred Card

Apply a blur effect to the entire card using isBlurred and adjust its intensity with blurIntensity. You can also specifically blur the footer using isFooterBlurred on the Card component.

index.tsx
1// Whole card blurred 2<Card isBlurred blurIntensity={20} style={{ width: 200 }}> 3 <CardHeader><Text style={{color: 'white', fontWeight: 'bold'}}>Blurred Card</Text></CardHeader> 4 <CardBody><Text style={{color: 'white'}}>Content inside a blurred card.</Text></CardBody> 5</Card> 6 7// Card with blurred footer (controlled by Card prop) 8<Card isFooterBlurred blurIntensity={30} style={{ width: 200, marginTop: 10 }}> 9 <CardHeader><Text>Normal Header</Text></CardHeader> 10 <CardBody><Text>Normal Body</Text></CardBody> 11 <CardFooter> 12 <Text style={{color: 'white'}}>Blurred Footer Content</Text> 13 </CardFooter> 14</Card>

Blurred Sections

Apply blur effects to individual sections (CardHeader, CardBody, CardFooter) by setting the isBlurred prop directly on them. Note: If the entire Card has isBlurred=, the footer will also blur unless isBlurred= is explicitly set on the CardFooter itself.

index.tsx
1// Card with only header blurred 2<Card style={{ width: 250, marginVertical: 10 }}> 3 <CardHeader isBlurred blurIntensity={25}> 4 <Text style={{ fontWeight: 'bold', color: 'white' }}>Blurred Header</Text> 5 </CardHeader> 6 <CardBody> 7 <Text>This body is not blurred.</Text> 8 </CardBody> 9</Card> 10 11// Card with only body blurred 12<Card style={{ width: 250, marginVertical: 10 }}> 13 <CardHeader> 14 <Text style={{ fontWeight: 'bold' }}>Normal Header</Text> 15 </CardHeader> 16 <CardBody isBlurred blurIntensity={25}> 17 <Text style={{ color: 'white' }}>This body is blurred.</Text> 18 <Text style={{ color: 'white', marginTop: 5 }}>More blurred content.</Text> 19 </CardBody> 20 <CardFooter> 21 <Text>Normal Footer</Text> 22 </CardFooter> 23</Card> 24 25// Card with only footer blurred (controlled by CardFooter prop) 26<Card style={{ width: 250, marginVertical: 10 }}> 27 <CardHeader><Text style={{ fontWeight: 'bold' }}>Normal Header</Text></CardHeader> 28 <CardBody><Text>Normal Body</Text></CardBody> 29 <CardFooter isBlurred blurIntensity={25}> 30 <Text style={{ color: 'white' }}>This footer is blurred.</Text> 31 </CardFooter> 32</Card>

Full Width

Make the card span the full width of its parent container by setting fullWidth=.

index.tsx
1<Card fullWidth> 2 <CardHeader><Text style={{fontWeight: 'bold'}}>Full Width Card</Text></CardHeader> 3 <CardBody><Text>This card spans the entire width of its parent.</Text></CardBody> 4</Card>

Disabled State

Disable the card, affecting its appearance and interactivity if pressable, using the disabled prop.

index.tsx
1<Card isPressable disabled onPress={() => console.log('Should not log')}> 2 <CardHeader><Text>Disabled Pressable Card</Text></CardHeader> 3 <CardBody><Text>This card looks and acts disabled.</Text></CardBody> 4</Card> 5 6<Card disabled style={{marginTop: 10}}> 7 <CardHeader><Text>Disabled Non-Pressable Card</Text></CardHeader> 8 <CardBody><Text>Content is visually dimmed.</Text></CardBody> 9</Card>

Complex Layout Example

Cards can be used to build more complex UI elements by combining them with other components and custom styling.

index.tsx
1<Card shadow="lg" radius="lg" style={{ marginVertical: 10 }}> 2 <CardHeader style={{ flexDirection: 'row', alignItems: 'center', borderBottomWidth: 1, borderBottomColor: '#eee' }}> 3 <Image source={{ uri: 'https://i.pravatar.cc/40?u=a042581f4e29026024d' }} style={{ width: 40, height: 40, borderRadius: 20, marginRight: 10 }} /> 4 <View> 5 <Text style={{ fontWeight: 'bold' }}>User Name</Text> 6 <Text style={{ fontSize: 12, color: 'gray' }}>Posted 2 hours ago</Text> 7 </View> 8 </CardHeader> 9 <CardBody> 10 <Image source={{ uri: 'https://picsum.photos/seed/picsum/400/200' }} style={{ width: '100%', height: 150, borderRadius: 8, marginBottom: 10 }} resizeMode="cover" /> 11 <Text>This is a more complex card layout with an image and structured content.</Text> 12 </CardBody> 13 <CardFooter style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}> 14 <View style={{ flexDirection: 'row', alignItems: 'center' }}> 15 {/* <Icon name="heart-outline" size={20} color="red" /> */} 16 <Text style={{ marginLeft: 4 }}>12 Likes</Text> 17 </View> 18 <Button size="sm" variant="flat">Comment</Button> 19 </CardFooter> 20</Card>

Using Card Context

For advanced use cases or creating deeply integrated custom child components, you can access the Card's properties using the useCardContext hook. This hook consumes CardContext and provides access to props like shadow, radius, isPressable, isBlurred, fullWidth, disabled, and more, directly from within any descendant of the Card component.

This is useful if you are building custom components that need to react to the Card's state or configuration without explicit prop drilling.

MyCustomCardComponent.tsx
1import { Card, CardBody, useCardContext } from '@/crossbuildui/card'; 2import { Text, View } from 'react-native'; 3 4const CardInfoDisplay = () => { 5 const context = useCardContext(); 6 7 if (!context) { 8 return <Text>This component must be used within a Card.</Text>; 9 } 10 11 const { shadow, radius, isPressable, isBlurred, fullWidth } = context; 12 13 return ( 14 <View style={{ marginTop: 8, padding: 8, backgroundColor: '#f0f0f0', borderRadius: 4 }}> 15 <Text>Card Context Info:</Text> 16 <Text>- Shadow: {shadow}, Radius: {radius}</Text> 17 <Text>- Pressable: {isPressable ? 'Yes' : 'No'}, Blurred: {isBlurred ? 'Yes' : 'No'}</Text> 18 <Text>- Full Width: {fullWidth ? 'Yes' : 'No'}</Text> 19 </View> 20 ); 21}; 22 23<Card shadow="sm" radius="lg" isPressable><CardBody><Text>Card Content</Text><CardInfoDisplay /></CardBody></Card>

Props Overview

Card Props

PROPTYPEDEFAULTDESCRIPTION
childrenReactNode-Content, typically CardHeader, CardBody, CardFooter.
shadow'none' | 'sm' | 'md' | 'lg''md'Shadow depth.
radius'none' | 'sm' | 'md' | 'lg''md'Border radius.
fullWidthbooleanfalseIf true, card takes full parent width.
isPressablebooleanfalseMakes the card pressable.
changeBgOnPressbooleantrueChange background on press if pressable.
isBlurredbooleanfalseApply blur effect to the entire card.
blurIntensitynumber10Blur intensity (1-100).
isFooterBlurredbooleanfalseApply blur effect specifically to the footer.
disabledbooleanfalseDisable the card.
disableAnimationbooleanfalseDisable press animations.
disableRipplebooleanfalseDisable Android ripple effect.
allowTextSelectionOnPressbooleanfalseAllow text selection during press.
stylesCardSlotsStyles-Custom styles for card slots (base, header, body, footer, blurredView, footerBlurredView).
styleStyleProp<ViewStyle>-Style for the card's outermost container.
onPress(event) => void-Callback for press events if isPressable.
...PressablePropsvarious-Other props from React Native's Pressable.

CardHeader Props

PROPTYPEDEFAULTDESCRIPTION
childrenReactNode-Content of the header.
styleStyleProp<ViewStyle>-Style for the header container.
isBlurredbooleanfalseApply blur effect to the header.
blurIntensitynumber50Blur intensity (1-100).

CardBody Props

PROPTYPEDEFAULTDESCRIPTION
childrenReactNode-Content of the body.
styleStyleProp<ViewStyle>-Style for the body container.
isBlurredbooleanfalseApply blur effect to the body.
blurIntensitynumber50Blur intensity (1-100).

CardFooter Props

PROPTYPEDEFAULTDESCRIPTION
childrenReactNode-Content of the footer.
styleStyleProp<ViewStyle>-Style for the footer container.
isBlurredbooleanfalseApply blur effect to the footer (behavior also influenced by Card's isBlurred and isFooterBlurred props).
blurIntensitynumber50Blur intensity (1-100).

Styling

Customize the appearance of the Card and its sections:

  • Card Component:
    • style: Applied to the outermost container of the Card (which could be a View, Pressable, or BlurView). Use for margins, width, etc.
    • styles (slot styles): An object to style specific internal parts of the Card:
      • base: Styles the direct content holder view within the Card (the one that gets the main background color and border radius if not blurred, or the content wrapper inside BlurView).
      • header: (Not directly used by Card, but defined in types. Styling for header is via CardHeader's own style prop or by targeting it through children).
      • body: (Similar to header).
      • footer: (Similar to header).
      • blurredView: Styles applied to the BlurView component when isBlurred is true on the Card.
      • footerBlurredView: (Not directly used by Card, footer blur is handled by cloning CardFooter with blur props).
  • CardHeader, CardBody, CardFooter Components:
    • style: Applied to the root container of each sub-component. Use for padding, background color (if not blurred), borders, etc.

The Card component intelligently handles background colors. If you provide a backgroundColor in the Card's main style prop, it will be used as the card's background. If the card is isBlurred, this background color will be applied to the content *inside* the blur, allowing the blur effect to tint it.

index.tsx
1// Styling the Card container and its slots 2// Card.styles.base is applied to the inner content holder. 3// Card.styles.blurredView is applied to the BlurView if Card isBlurred. 4// Note: Card.styles.header, .body, .footer are defined in types but not directly applied by Card to its children. 5// Style CardHeader, CardBody, CardFooter via their own 'style' prop. 6<Card 7 isBlurred // Example to show blurredView styling 8 blurIntensity={5} 9 style={{ marginVertical: 10 }} // Styles the outermost Card container (BlurView in this case) 10 styles={{ 11 base: { backgroundColor: 'rgba(255, 255, 0, 0.3)' }, // Content holder inside BlurView 12 blurredView: { borderColor: 'purple', borderWidth: 1 } // Styles the BlurView itself 13 }} 14 radius="none" 15> 16 <CardHeader> 17 <Text style={{color: 'black'}}>Styled Header (text color for contrast)</Text> 18 </CardHeader> 19 <CardBody> 20 <Text style={{color: 'black'}}>Content with custom slot styling.</Text> 21 </CardBody> 22 <CardFooter> 23 <Text style={{color: 'black'}}>Styled Footer</Text> 24 </CardFooter> 25</Card>

Accessibility

The Card component itself is a container. Accessibility largely depends on its content and usage:

  • If the card is isPressable, it behaves like a Pressable and will have accessibilityRole="button" by default. Ensure meaningful content or an accessibilityLabel is provided for screen readers.
  • Content within CardHeader, CardBody, and CardFooter should follow standard accessibility practices for text, images, and interactive elements.
  • For complex cards, consider using semantic headers (e.g., larger text for titles) to aid navigation.