Featuring Design System
Layout

VStack

자식 요소를 세로로 배치하는 수직 스택 컴포넌트.

개요

VStack<Flex $css={{ flexDirection: 'column' }}> 의 단축 컴포넌트입니다. display: flex, flex-direction: column이 기본 적용되며, Box의 모든 props를 그대로 상속합니다.

폼 필드 목록이나 카드 내부 콘텐츠처럼 요소를 위에서 아래로 쌓을 때 사용합니다.

언제 사용하나요

  • 폼 필드를 위에서 아래로 나열할 때
  • 카드 내부의 제목, 본문, 버튼을 수직으로 구성할 때
  • 페이지 섹션을 차례로 쌓아 올릴 때
  • 수직 방향 간격(gap)만 제어하면 되는 단순한 레이아웃

언제 사용하면 안 되나요

  • 요소를 가로로 나열할 때 → HStack
  • 방향을 동적으로 바꾸거나 양방향 레이아웃이 필요할 때 → Flex
  • 격자 형태로 배치할 때 → Grid

접근성

기본적으로 <div>를 렌더링합니다. render prop으로 의미에 맞는 요소를 지정하세요.

// 폼 컨테이너
<VStack render={<form />} $css={{ gap: '$spacing-400' }}>
  <input type="text" />
  <input type="email" />
  <button type="submit">제출</button>
</VStack>

// 정렬되지 않은 목록
<VStack render={<ul />} $css={{ gap: '$spacing-200', listStyle: 'none' }}>
  <li>항목 1</li>
  <li>항목 2</li>
</VStack>

Usage

기본 사용법

<VStack $css={{ gap: '$spacing-300' }}>
<Box $css={{ padding: '$spacing-300', bgColor: '$primary-10', rounded: '$radius-100' }}><Typo variant="$body-2">One</Typo></Box>
<Box $css={{ padding: '$spacing-300', bgColor: '$primary-10', rounded: '$radius-100' }}><Typo variant="$body-2">Two</Typo></Box>
<Box $css={{ padding: '$spacing-300', bgColor: '$primary-10', rounded: '$radius-100' }}><Typo variant="$body-2">Three</Typo></Box>
</VStack>

gap으로 간격 조정

<HStack $css={{ gap: '$spacing-600', alignItems: 'flex-start' }}>
<VStack $css={{ gap: '$spacing-100' }}>
  <Box $css={{ padding: '$spacing-200', bgColor: '$background-3', rounded: '$radius-100' }}><Typo variant="$body-2">좁은 간격</Typo></Box>
  <Box $css={{ padding: '$spacing-200', bgColor: '$background-3', rounded: '$radius-100' }}><Typo variant="$body-2">좁은 간격</Typo></Box>
  <Box $css={{ padding: '$spacing-200', bgColor: '$background-3', rounded: '$radius-100' }}><Typo variant="$body-2">좁은 간격</Typo></Box>
</VStack>
<VStack $css={{ gap: '$spacing-400' }}>
  <Box $css={{ padding: '$spacing-200', bgColor: '$background-3', rounded: '$radius-100' }}><Typo variant="$body-2">넓은 간격</Typo></Box>
  <Box $css={{ padding: '$spacing-200', bgColor: '$background-3', rounded: '$radius-100' }}><Typo variant="$body-2">넓은 간격</Typo></Box>
  <Box $css={{ padding: '$spacing-200', bgColor: '$background-3', rounded: '$radius-100' }}><Typo variant="$body-2">넓은 간격</Typo></Box>
</VStack>
</HStack>

stretch (기본 alignItems)

flexbox의 기본 align-itemsstretch이므로, 별도 설정 없이도 자식 요소가 부모 너비를 꽉 채웁니다.

<VStack $css={{ gap: '$spacing-200', width: '300px' }}>
<Box $css={{ padding: '$spacing-300', bgColor: '$primary-10', rounded: '$radius-100' }}><Typo variant="$body-2">꽉 찬 너비</Typo></Box>
<Box $css={{ padding: '$spacing-300', bgColor: '$primary-20', rounded: '$radius-100' }}><Typo variant="$body-2">꽉 찬 너비</Typo></Box>
<Box $css={{ padding: '$spacing-300', bgColor: '$primary-30', rounded: '$radius-100' }}><Typo variant="$body-2">꽉 찬 너비</Typo></Box>
</VStack>

alignItems로 가로 정렬 변경

flex-start로 자식 요소를 내용 너비만큼만 렌더링하거나, center로 중앙 정렬합니다.

<HStack $css={{ gap: '$spacing-600', alignItems: 'flex-start' }}>
<VStack $css={{ gap: '$spacing-200', alignItems: 'flex-start' }}>
  <Box $css={{ padding: '$spacing-200', bgColor: '$primary-10', rounded: '$radius-100' }}><Typo variant="$body-2">짧음</Typo></Box>
  <Box $css={{ padding: '$spacing-200', bgColor: '$primary-10', rounded: '$radius-100' }}><Typo variant="$body-2">조금 더 긴 텍스트</Typo></Box>
  <Box $css={{ padding: '$spacing-200', bgColor: '$primary-10', rounded: '$radius-100' }}><Typo variant="$body-2">A</Typo></Box>
</VStack>
<VStack $css={{ gap: '$spacing-200', alignItems: 'center', width: '160px' }}>
  <Box $css={{ padding: '$spacing-200', bgColor: '$primary-10', rounded: '$radius-100' }}><Typo variant="$body-2">짧음</Typo></Box>
  <Box $css={{ padding: '$spacing-200', bgColor: '$primary-10', rounded: '$radius-100' }}><Typo variant="$body-2">조금 더 긴 텍스트</Typo></Box>
  <Box $css={{ padding: '$spacing-200', bgColor: '$primary-10', rounded: '$radius-100' }}><Typo variant="$body-2">A</Typo></Box>
</VStack>
</HStack>

반응형 gap

<VStack $css={{ gap: { mobile: '$spacing-200', tablet: '$spacing-400', desktop: '$spacing-600' } }}>
<Box $css={{ padding: '$spacing-300', bgColor: '$background-2', rounded: '$radius-200' }}><Typo variant="$body-2">섹션 1</Typo></Box>
<Box $css={{ padding: '$spacing-300', bgColor: '$background-2', rounded: '$radius-200' }}><Typo variant="$body-2">섹션 2</Typo></Box>
<Box $css={{ padding: '$spacing-300', bgColor: '$background-2', rounded: '$radius-200' }}><Typo variant="$body-2">섹션 3</Typo></Box>
</VStack>

폼 레이아웃

<VStack $css={{ gap: '$spacing-400', padding: '$spacing-500', bgColor: '$background-2', rounded: '$radius-300', maxWidth: '360px' }}>
<VStack $css={{ gap: '$spacing-100' }}>
  <Box render={<label />} $css={{ color: '$text-1' }}><Typo variant="$label-2">이름</Typo></Box>
  <Box render={<input />} $css={{ padding: '$spacing-200', rounded: '$radius-100', bgColor: '$background-1', borderColor: '$border-default' }} style={{ border: '1px solid', width: '100%', boxSizing: 'border-box' }} placeholder="홍길동" />
</VStack>
<VStack $css={{ gap: '$spacing-100' }}>
  <Box render={<label />} $css={{ color: '$text-1' }}><Typo variant="$label-2">이메일</Typo></Box>
  <Box render={<input />} $css={{ padding: '$spacing-200', rounded: '$radius-100', bgColor: '$background-1', borderColor: '$border-default' }} style={{ border: '1px solid', width: '100%', boxSizing: 'border-box' }} placeholder="hello@example.com" />
</VStack>
<Box render={<button />} $css={{ padding: '$spacing-300', bgColor: '$primary-50', color: '$white', rounded: '$radius-200' }} style={{ border: 'none', cursor: 'pointer', width: '100%' }}><Typo variant="$body-2">제출</Typo></Box>
</VStack>

$css로 추가 스타일 적용

<VStack $css={{ gap: '$spacing-300', padding: '$spacing-400', bgColor: '$background-2', rounded: '$radius-300', maxWidth: '240px', elevation: '$elevation-md' }}>
<Box $css={{ color: '$text-1' }}><Typo variant="$heading-6">카드 제목</Typo></Box>
<Box $css={{ color: '$text-3' }}><Typo variant="$body-2">카드 본문 내용이 여기에 들어갑니다.</Typo></Box>
<Box $css={{ padding: '$spacing-200', bgColor: '$primary-10', rounded: '$radius-100', color: '$primary-80', alignSelf: 'flex-start' }}><Typo variant="$label-2">더 보기</Typo></Box>
</VStack>

Props

VStack은 별도의 props를 추가하지 않습니다. BoxProps를 그대로 사용합니다.

Prop

Type

스타일

VStack은 내부적으로 아래 스타일을 기본 적용합니다. $css로 덮어쓸 수 있습니다.

CSS 속성기본값
displayflex
flex-directioncolumn