surf-uiby COLDSURF
Native

TabBar

하단 탭바의 면. 네비게이션은 안 든다.

피드
import { TabBar } from '@coldsurfers/surf-ui/native/TabBar'import { Text } from '@coldsurfers/surf-ui/native/Text'import { House, Search, Tickets, UserRound } from 'lucide-react'import { useState } from 'react'import { View } from 'react-native'const TABS = [  { key: 'feed', label: '피드', Icon: House },  { key: 'events', label: '이벤트', Icon: Tickets },  { key: 'search', label: '검색', Icon: Search },  { key: 'my', label: '나의 창꼬', Icon: UserRound },]export default function Example() {  const [selected, setSelected] = useState('feed')  return (    <>      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>        <Text textStyle="body" tone="muted">          {TABS.find((tab) => tab.key === selected)?.label}        </Text>      </View>      <TabBar>        {TABS.map(({ key, label, Icon }) => (          <TabBar.Item            key={key}            label={label}            active={key === selected}            onPress={() => setSelected(key)}            renderIcon={({ color, size, strokeWidth }) => (              <Icon color={color} size={size} strokeWidth={strokeWidth} aria-hidden />            )}          />        ))}      </TabBar>    </>  )}

웹에 짝이 없는 표면입니다. 이건 면(chrome)이지 네비게이션도 배치도 아닙니다.

무엇을 들고 무엇을 안 드는가

여기여기가 아닌 곳
색 · 테두리 · 높이(safe-area 포함) · 아이템 배치 · 라벨 서식 · 활성 tint라우터 배선 · route → 아이콘 매핑 · 햅틱 → 소비처
화면 하단 고정 · 숨김 애니메이션 → AnimatedTabBar

위치를 정하지 않는 이유는 의존입니다. reanimated 애니메이션 스타일은 Animated.* 에만 먹으므로, 위치와 이동을 한 컴포넌트가 들면 이 파일이 reanimated 를 물게 됩니다. 그러면 애니메이션을 안 쓰는 소비처까지 그 의존을 집니다. 여기 의존은 emotion 과 safe-area-context 둘뿐입니다.

아이콘을 노드가 아니라 함수로 받는 이유

색 · 크기 · 굵기는 활성 여부에서 나오는 이 면의 계약이고, 무엇을 그릴지는 소비처의 것입니다. 노드로 받으면 소비처가 tint 를 알아야 하고, 그러면 색 계약이 밖으로 샙니다.

renderIcon={({ color, size, strokeWidth }) => (
  <House color={color} size={size} strokeWidth={strokeWidth} />
)}

활성 상태는 채움 아이콘 세트가 아니라 굵기와 accent 색으로 말합니다 (1.5 → 2.5).

높이는 useTabBarHeight() 에서 읽는다

AnimatedTabBar 로 띄우면 탭바가 레이아웃에서 빠져 자리를 비워 주지 않습니다. 화면이 자기 콘텐츠 아래 여백을 이 값으로 잡아야 합니다.

const tabBarHeight = useTabBarHeight()
<ScrollView contentContainerStyle={{ paddingBottom: tabBarHeight }} />

인셋을 상수로 박지 않습니다 — 홈 인디케이터 높이는 기기마다 다르고 0 인 기기(SE · iPad)도 있어서, 박으면 그런 기기에서 탭바 아래가 빈 채로 남습니다.

화면 전체가 이 여백을 져야 하면 직접 계산하는 대신 AppScreen 의 offsetBottom="tabBar" 를 씁니다.

위 미리보기의 높이는 실기기 높이가 아닙니다

브라우저에서는 Platform.OS === 'web' 이라 아래 여백이 0 입니다. 실기기에서는 iOS 가 홈 인디케이터 인셋만큼, Android 가 12 만큼 더 큽니다.

그리고 useSafeAreaInsets() 를 부르므로 앱 루트에 SafeAreaProvider 가 있어야 합니다.

Props

Prop

Type

그 밖의 ViewProps 속성은 루트 엘리먼트로 그대로 통과한다.

TabBar.Item

Prop

Type

그 밖의 TouchableOpacityProps 속성은 루트 엘리먼트로 그대로 통과한다.

On this page