Tabs
같은 계층의 콘텐츠 영역을 오갈 때 써요.
Anatomy
- 01Tab Item레이블 단위. 선택되면 굵기 700, variant 별 선택색
- 02Indicator선택 탭 아래 2px 선. 150ms 로 슬라이드해요
- 03Divider탭바 아래 1px 선. 탭과 콘텐츠를 나눠요
Properties
Variant(Primary·Secondary) · Layout(Fill·Hug) · Size(Medium·Small) · State 네 축으로 구성돼요.
Variant
Primary 는 페이지 최상단 메인 네비게이션, Secondary 는 섹션 안 서브 카테고리에 써요. 선택 탭은 하단 2px 선으로 표시해요.
Layout
Fill 은 탭 너비를 균등 분할하고, Hug 는 레이블 길이에 맞춰요.
Size
Medium(44px) · Small(40px) 두 단계예요.
State
Enabled · Selected · Disabled. Tabs 의 Disabled 는 투명도 35% 예요.
Guidelines
Variant 선택
✓ DO
- 최상단 메인 네비게이션은 Primary
- 섹션 안 서브 카테고리는 Secondary
- 2 depth 면 Primary 아래 Secondary
✗ DON'T
- 같은 계층에 Primary 와 Secondary 혼용
- 드롭다운·필터 대신 탭 쓰기
- 페이지 간 라우팅(네비게이션 몫)
Fill과 Hug 레이아웃
Fill 은 탭이 3~5개이고 균등한 무게가 필요할 때, Hug 는 6개 이상이거나 레이블 길이가 제각각일 때 써요. 억지로 균등 분할하면 짧은 탭이 어색하게 넓어져요.
탭 수 제한
2~7개로 유지해요. 8개를 넘으면 한눈에 안 들어오니 Hug + 가로 스크롤을 검토해요.
2 Depth 탭 구조
1차 분류는 Primary, 2차 분류는 Secondary 예요. Primary 아래 Secondary 까지가 최대 깊이고, 3 depth 는 쓰지 않아요.
탭 vs 다른 컴포넌트
탭은 같은 계층의 콘텐츠를 오갈 때만 써요. 아래 상황은 다른 컴포넌트 몫이에요.
| 상황 | 대안 |
|---|---|
| 옵션이 2–4개이고 즉시 필터링 | Segment Control |
| 항목이 많거나 동적으로 변함 | Select |
| 다른 페이지로 이동 | Navigation / Link |
Specification
Container
| 속성 | 값 | 설명 |
|---|---|---|
| height (medium) | 44px | 기본 높이 |
| height (small) | 40px | 소형 높이 |
| indicator-height | 2px | 선택 탭 하단 강조선 |
| divider-height | 1px | 탭바 하단 구분선 |
| indicator-transition | duration-fast (150ms) | Indicator 슬라이드 전환 |
Item
| 속성 | State | Primary | Secondary |
|---|---|---|---|
| label color | Enabled | --color-label-subtle | --color-label-subtle |
| label color | Selected | --color-accent-normal | --color-label-normal |
| label color | Disabled | --color-label-disable | --color-label-disable |
| indicator color | Selected | --color-accent-normal | --color-label-normal |
| font-weight | Selected | 700 (Bold) | 700 (Bold) |
| padding-x (medium) | — | spacing-md (20px) | spacing-md (20px) |
| padding-x (small) | — | spacing-sm (16px) | spacing-sm (16px) |
⚠️ 위 표의 토큰명 중 다음 두 개는 tokens.css 에 실존하지 않아요(Figma 원본 표기 오류). 구현 시에는 교정값을 써요: --color-label-subtle → --color-label-alternative · --color-label-disable → --color-label-assistive
npm i @polarisoffice/pds-reactVariant
Primary 는 최상단 메인 네비게이션, Secondary 는 섹션 안 서브 카테고리예요.
import { Tabs } from '@polarisoffice/pds-react';
const items = [
{ value: 'all', label: '전체' },
{ value: 'doc', label: '문서' },
{ value: 'sheet', label: '스프레드시트' },
];
<Tabs variant="primary" layout="hug" items={items} defaultValue="all" />
<Tabs variant="secondary" layout="hug" items={items} defaultValue="all" />Layout
Fill 은 3–5개 균등 분할, Hug 는 6개 이상이거나 레이블 길이가 제각각일 때.
import { Tabs } from '@polarisoffice/pds-react';
<Tabs layout="fill" items={items} defaultValue="all" />
<Tabs layout="hug" items={items} defaultValue="all" />Size
Medium 44px · Small 40px.
import { Tabs } from '@polarisoffice/pds-react';
<Tabs size="medium" items={items} defaultValue="all" />
<Tabs size="small" items={items} defaultValue="all" />Controlled
선택 탭 하단 인디케이터는 150ms(duration-fast)로 슬라이드해요.
import { Tabs } from '@polarisoffice/pds-react';
import { useState } from 'react';
const [tab, setTab] = useState('all');
<Tabs items={items} value={tab} onChange={setTab} />Disabled
Tabs 의 Disabled 는 투명도 35% 예요.
import { Tabs } from '@polarisoffice/pds-react';
<Tabs
items={[
{ value: 'all', label: '전체' },
{ value: 'archive', label: '보관함', disabled: true },
]}
defaultValue="all"
/>