Skip to content

VStack

VStack arranges child components vertically in a column, providing flexible spacing, alignment, and wrapping options. It’s ideal for creating forms, lists, card layouts, and any vertical content organization.

import { VStack } from 'rnc-theme';
<VStack spacing="md">
<Text>First Item</Text>
<Text>Second Item</Text>
<Text>Third Item</Text>
</VStack>
PropTypeDefaultDescription
spacingkeyof Theme['spacing']0Gap between child components
wrapbooleanfalseAllow items to wrap (creates rows)

VStack inherits all BaseLayoutProps for consistent styling and behavior.

PropTypeDefaultDescription
alignViewStyle['alignItems']'stretch'Cross-axis alignment (horizontal)
justifyViewStyle['justifyContent']'flex-start'Main-axis alignment (vertical)
PropTypeDefaultDescription
childrenReact.ReactNode-Child components to render
styleStyleProp<ViewStyle>-Additional style properties
paddingkeyof Theme['spacing']-Padding around content
marginkeyof Theme['spacing']-Margin around component
backgroundColorViewStyle['backgroundColor']-Background color
borderRadiuskeyof Theme['components']['borderRadius']-Border radius value
flexnumber-Flex grow/shrink value
widthDimensionValue-Component width
heightDimensionValue-Component height
themedbooleanfalseEnable theme styles
alignViewStyle['alignItems']-Cross-axis alignment
justifyViewStyle['justifyContent']-Main-axis alignment
<VStack
spacing="lg"
padding="xl"
align="stretch"
backgroundColor="#fff"
>
<VStack spacing="xs" align="center">
<Avatar size={80} />
<Text style={{ fontSize: 18, fontWeight: 'bold' }}>John Doe</Text>
<Text style={{ color: '#666' }}>Software Developer</Text>
</VStack>
<VStack spacing="md">
<TextInput
label="Full Name"
placeholder="Enter your name"
/>
<TextInput
label="Email"
placeholder="Enter your email"
keyboardType="email-address"
/>
<TextInput
label="Bio"
placeholder="Tell us about yourself"
multiline
numberOfLines={4}
/>
</VStack>
<HStack spacing="md">
<Button title="Cancel" variant="outline" flex={1} />
<Button title="Save Changes" flex={1} />
</HStack>
</VStack>
<VStack spacing="xs" padding="md">
{settingsItems.map((item, index) => (
<HStack
key={item.id}
justify="space-between"
align="center"
padding="md"
style={{
borderBottomWidth: index < settingsItems.length - 1 ? 1 : 0,
borderBottomColor: '#e0e0e0'
}}
>
<HStack spacing="md" align="center">
<Icon name={item.icon} size={20} />
<VStack spacing="xs">
<Text style={{ fontWeight: '500' }}>{item.title}</Text>
{item.subtitle && (
<Text style={{ fontSize: 12, color: '#666' }}>
{item.subtitle}
</Text>
)}
</VStack>
</HStack>
<Switch value={item.enabled} onValueChange={item.onToggle} />
</HStack>
))}
</VStack>
<VStack spacing="lg" padding="lg">
<VStack spacing="sm">
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>
Article Title
</Text>
<HStack spacing="md" align="center">
<Avatar size={24} />
<Text style={{ fontSize: 14, color: '#666' }}>
By Author Name • 5 min read
</Text>
</HStack>
</VStack>
<Image
source={{ uri: 'article-image.jpg' }}
style={{ width: '100%', height: 200, borderRadius: 8 }}
/>
<VStack spacing="md">
<Text style={{ lineHeight: 24 }}>
Article content paragraph 1...
</Text>
<Text style={{ lineHeight: 24 }}>
Article content paragraph 2...
</Text>
</VStack>
<HStack spacing="md" justify="space-between">
<Button title="👍 Like" variant="outline" />
<Button title="💬 Comment" variant="outline" />
<Button title="📤 Share" variant="outline" />
</HStack>
</VStack>
<VStack spacing="lg" padding="lg">
<Text style={{ fontSize: 20, fontWeight: 'bold' }}>Dashboard</Text>
<VStack spacing="md">
{dashboardCards.map(card => (
<Box
key={card.id}
variant="card"
padding="lg"
>
<VStack spacing="sm">
<HStack justify="space-between" align="center">
<Text style={{ fontSize: 16, fontWeight: '600' }}>
{card.title}
</Text>
<Icon name={card.icon} color={card.color} />
</HStack>
<Text style={{ fontSize: 24, fontWeight: 'bold', color: card.color }}>
{card.value}
</Text>
<Text style={{ fontSize: 12, color: '#666' }}>
{card.description}
</Text>
</VStack>
</Box>
))}
</VStack>
</VStack>
<VStack align="stretch" spacing="md" padding="md">
<Button title="Full Width Button 1" />
<Button title="Full Width Button 2" />
<Button title="Full Width Button 3" />
</VStack>
<VStack
justify="space-between"
padding="md"
style={{ height: 300 }}
>
<Text>Top Item</Text>
<Text>Middle Item</Text>
<Text>Bottom Item</Text>
</VStack>
<VStack flex={1} justify="space-between">
<VStack spacing="lg" padding="lg">
<Text style={{ fontSize: 20, fontWeight: 'bold' }}>
Main Content
</Text>
<Text>Your scrollable content goes here...</Text>
</VStack>
<Box padding="lg" backgroundColor="#f9f9f9">
<Button title="Sticky Bottom Button" />
</Box>
</VStack>
const [expanded, setExpanded] = useState(false);
<VStack spacing="md" padding="lg">
<HStack
justify="space-between"
align="center"
onPress={() => setExpanded(!expanded)}
>
<Text style={{ fontSize: 16, fontWeight: '600' }}>
Section Title
</Text>
<Icon name={expanded ? 'chevron-up' : 'chevron-down'} />
</HStack>
{expanded && (
<VStack spacing="sm" padding="md" backgroundColor="#f5f5f5">
<Text>Expandable content item 1</Text>
<Text>Expandable content item 2</Text>
<Text>Expandable content item 3</Text>
</VStack>
)}
</VStack>
const [step, setStep] = useState(1);
<VStack spacing="lg" padding="lg" flex={1}>
{/* Progress indicator */}
<HStack spacing="xs" justify="center">
{[1, 2, 3].map(stepNumber => (
<Box
key={stepNumber}
style={{
width: 30,
height: 4,
backgroundColor: step >= stepNumber ? '#007AFF' : '#E0E0E0',
borderRadius: 2
}}
/>
))}
</HStack>
{/* Step content */}
<VStack spacing="md" flex={1}>
{step === 1 && <PersonalInfoForm />}
{step === 2 && <AddressForm />}
{step === 3 && <ConfirmationForm />}
</VStack>
{/* Navigation */}
<HStack spacing="md">
{step > 1 && (
<Button
title="Previous"
variant="outline"
flex={1}
onPress={() => setStep(step - 1)}
/>
)}
<Button
title={step === 3 ? "Submit" : "Next"}
flex={1}
onPress={() => step < 3 ? setStep(step + 1) : handleSubmit()}
/>
</HStack>
</VStack>

Spacing & Layout

  • Use consistent spacing values from your theme
  • Prefer align="stretch" for form inputs to maintain consistent widths
  • Use justify="space-between" with explicit heights for sticky layouts

Content Organization

  • Group related content using nested VStack components
  • Use spacing consistently within related sections
  • Consider visual hierarchy with varying spacing sizes

Performance Tips

  • Avoid deeply nested VStack components when a simple spacing approach works
  • Use ScrollView wrapper for long vertical content
  • Consider FlatList for dynamic lists instead of mapping in VStack