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 @crossbuildui/card

Import

index.tsx
1import { Card, CardHeader, CardBody, CardFooter } 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>

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 3 style={{ marginVertical: 10, borderColor: 'blue', borderWidth: 1 }} // Styles the outermost Card container 4 styles={{ 5 base: { backgroundColor: 'lightyellow' }, // Styles the inner content holder (View/Pressable) 6 header: { borderBottomColor: 'red', borderBottomWidth: 2 }, 7 body: { paddingVertical: 20 }, 8 footer: { backgroundColor: 'lightcyan' }, 9 // blurredView: { opacity: 0.9 } // If Card isBlurred 10 }} 11 radius="none" 12> 13 <CardHeader style={{ backgroundColor: 'rgba(0,0,255,0.1)' }}>{/* Individual style for header */} 14 <Text>Styled Header</Text> 15 </CardHeader> 16 <CardBody> 17 <Text>Content with custom slot styling.</Text> 18 </CardBody> 19 <CardFooter> 20 <Text>Styled Footer</Text> 21 </CardFooter> 22</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.