Featuring Design System
Layout

HStack

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

개요

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

아이콘 + 텍스트 조합이나 버튼 그룹처럼 요소를 나란히 놓을 때 Flex 대신 쓰면 의도가 더 명확해집니다.

언제 사용하나요

  • 버튼 그룹, 툴바, 탭 목록처럼 요소를 가로로 나열할 때
  • 아이콘과 텍스트를 한 줄에 함께 배치할 때
  • 내비게이션 바의 링크 목록을 구성할 때
  • 수평 방향 간격(gap)만 제어하면 되는 단순한 레이아웃

언제 사용하면 안 되나요

  • 요소를 세로로 쌓을 때 → VStack
  • 방향을 동적으로 바꾸거나 양방향 레이아웃이 필요할 때 → Flex
  • 격자 형태로 배치할 때 → Grid
  • 자식을 정중앙에 놓을 때 → Center

접근성

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

// 내비게이션 링크 목록
<HStack render={<nav />} $css={{ gap: '$spacing-300' }}>
  <a href="/">홈</a>
  <a href="/about">소개</a>
</HStack>

// 정렬된 목록
<HStack render={<ul />} $css={{ gap: '$spacing-200', listStyle: 'none' }}>
  <li>One</li>
  <li>Two</li>
</HStack>

Usage

기본 사용법

<HStack $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>
</HStack>

gap으로 간격 조정

$cssgap에 spacing 토큰을 사용합니다.

<VStack $css={{ gap: '$spacing-400' }}>
<HStack $css={{ gap: '$spacing-100' }}>
  <Box $css={{ padding: '$spacing-200', bgColor: '$background-3', rounded: '$radius-100' }}><Typo variant="$body-2">A</Typo></Box>
  <Box $css={{ padding: '$spacing-200', bgColor: '$background-3', rounded: '$radius-100' }}><Typo variant="$body-2">B</Typo></Box>
  <Box $css={{ padding: '$spacing-200', bgColor: '$background-3', rounded: '$radius-100' }}><Typo variant="$body-2">C</Typo></Box>
</HStack>
<HStack $css={{ gap: '$spacing-400' }}>
  <Box $css={{ padding: '$spacing-200', bgColor: '$background-3', rounded: '$radius-100' }}><Typo variant="$body-2">A</Typo></Box>
  <Box $css={{ padding: '$spacing-200', bgColor: '$background-3', rounded: '$radius-100' }}><Typo variant="$body-2">B</Typo></Box>
  <Box $css={{ padding: '$spacing-200', bgColor: '$background-3', rounded: '$radius-100' }}><Typo variant="$body-2">C</Typo></Box>
</HStack>
</VStack>

alignItems로 수직 정렬

기본값은 stretch입니다. 높이가 다른 요소를 중앙에 맞추려면 center를 사용하세요.

<HStack $css={{ gap: '$spacing-300', alignItems: 'center', bgColor: '$background-2', padding: '$spacing-300', rounded: '$radius-200' }}>
<Box $css={{ padding: '$spacing-200', bgColor: '$primary-10', rounded: '$radius-100' }}><Typo variant="$body-2">짧은 텍스트</Typo></Box>
<Box $css={{ padding: '$spacing-400', bgColor: '$primary-20', 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>
</HStack>

양쪽 정렬 (space-between)

첫 번째 요소는 왼쪽, 마지막 요소는 오른쪽에 붙이는 패턴입니다.

<HStack $css={{ justifyContent: 'space-between', alignItems: 'center', bgColor: '$background-2', padding: '$spacing-300', rounded: '$radius-200' }}>
<Box $css={{ padding: '$spacing-200', bgColor: '$primary-10', rounded: '$radius-100' }}><Typo variant="$body-2">로고</Typo></Box>
<HStack $css={{ gap: '$spacing-200' }}>
  <Box $css={{ padding: '$spacing-200', bgColor: '$background-3', rounded: '$radius-100' }}><Typo variant="$body-2">메뉴 1</Typo></Box>
  <Box $css={{ padding: '$spacing-200', bgColor: '$background-3', rounded: '$radius-100' }}><Typo variant="$body-2">메뉴 2</Typo></Box>
</HStack>
</HStack>

줄바꿈 (flexWrap)

항목이 많아 넘칠 때 flexWrap: 'wrap'으로 자동 줄바꿈합니다.

<HStack $css={{ gap: '$spacing-200', flexWrap: 'wrap', maxWidth: '320px' }}>
{['React', 'TypeScript', 'Vite', 'Storybook', 'Rollup', 'Vanilla Extract', 'Base UI', 'pnpm'].map((tag) => (
  <Box key={tag} $css={{ padding: '$spacing-100 $spacing-200', bgColor: '$primary-10', rounded: '$radius-full', color: '$primary-80' }}><Typo variant="$label-2">{tag}</Typo></Box>
))}
</HStack>

반응형 gap

breakpoint별로 간격을 다르게 줄 수 있습니다.

<HStack $css={{ gap: { mobile: '$spacing-100', tablet: '$spacing-300', desktop: '$spacing-500' } }}>
<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>
</HStack>

render prop으로 시맨틱 요소 지정

<HStack render={<nav />} $css={{ gap: '$spacing-400', padding: '$spacing-300', bgColor: '$background-2', rounded: '$radius-200' }}>
<Box render={<a />} $css={{ color: '$text-1', padding: '$spacing-100' }} href="#"><Typo variant="$body-2">홈</Typo></Box>
<Box render={<a />} $css={{ color: '$text-1', padding: '$spacing-100' }} href="#"><Typo variant="$body-2">소개</Typo></Box>
<Box render={<a />} $css={{ color: '$text-1', padding: '$spacing-100' }} href="#"><Typo variant="$body-2">문서</Typo></Box>
</HStack>

Props

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

Prop

Type

스타일

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

CSS 속성기본값
displayflex
flex-directionrow