Tabs
먼저 보고, 그다음 계약을 읽습니다
접근성 탭 네비게이션(가로/세로) — Radix Tabs 위 .axe-tabs 스타일.
Component intent의도와 경계 읽기
@radix-ui/react-tabs 위에 .axe-tabs__* 스타일을 입힌 얇은 wrapper. orientation="horizontal"(기본) 은 ← → 키 이동 + 활성 트리거 하단 underline, orientation="vertical" 은 ↑ ↓ 키 이동 + 좌측 rail + 활성 트리거 좌측 indicator 로 렌더된다. Tabs/TabsList/TabsTrigger/TabsContent 4-파트로 구성하며 roving tabindex·arrow nav·aria 배선은 전부 Radix 가 처리한다.
예제
SSOT에 등록된 실제 API 기준 snippet입니다. standalone 배지만 독립 실행 단위이며, fragment는 주변 state·handler 문맥을 생략합니다.
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@axe/ui";<Tabs defaultValue="overview"> <TabsList> <TabsTrigger value="overview">Overview</TabsTrigger> <TabsTrigger value="usage">Usage</TabsTrigger> </TabsList> <TabsContent value="overview">개요 내용…</TabsContent> <TabsContent value="usage">사용법 내용…</TabsContent></Tabs>import { Tabs, TabsList, TabsTrigger, TabsContent } from "@axe/ui";<Tabs orientation="vertical" value={tab} onValueChange={setTab}> <TabsList> <TabsTrigger value="general">일반</TabsTrigger> <TabsTrigger value="security">보안</TabsTrigger> </TabsList> <TabsContent value="general">…</TabsContent> <TabsContent value="security">…</TabsContent></Tabs><div class="axe-tabs axe-tabs--horizontal"> <div class="axe-tabs__list" role="tablist"> <button class="axe-tabs__trigger" role="tab" data-state="active" aria-selected="true" aria-controls="p-1" id="t-1">Overview</button> <button class="axe-tabs__trigger" role="tab" data-state="inactive" aria-selected="false" aria-controls="p-2" id="t-2">Usage</button> </div> <div class="axe-tabs__content" role="tabpanel" id="p-1" aria-labelledby="t-1" data-state="active">개요 내용…</div> <div class="axe-tabs__content" role="tabpanel" id="p-2" aria-labelledby="t-2" data-state="inactive" hidden>사용법 내용…</div></div>Props
TSX 소스가 진실입니다. 주요 export 컴포넌트의 public API만 노출합니다.
| 이름 | 타입 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
orientation | "horizontal" | "vertical" | — | "horizontal" | Tabs 루트 — 방향. .axe-tabs--{orientation} 및 Radix orientation 에 반영. |
...rest | React.ComponentPropsWithoutRef<typeof TabsPrimitive.Root> | — | — | Tabs 루트 — 나머지는 Radix Tabs.Root 로 전파(value, defaultValue, onValueChange, dir, activationMode 등). |
TabsTrigger.value | string | 필수 | — | 이 트리거가 활성화하는 패널 키. 대응 TabsContent.value 와 매칭. |
TabsContent.value | string | 필수 | — | 이 패널의 키. 대응 TabsTrigger.value 와 매칭. |
TabsList / TabsTrigger / TabsContent ...rest | React.ComponentPropsWithoutRef<typeof TabsPrimitive.*> | — | — | 각각 Radix Tabs.List/Trigger/Content 로 전파(disabled, forceMount 등). |
.axe-* 클래스 계약
React 밖에서도 같은 표면을 그리는 공개 계약입니다. stable은 minor 버전 안에서 이름을 바꾸지 않습니다.
| 클래스 | 안정성 | 용도 |
|---|---|---|
.axe-tabs | stable | Tabs 루트(Radix Root). |
.axe-tabs--horizontal | stable | 가로 방향 변형(활성 하단 underline). |
.axe-tabs--vertical | stable | 세로 방향 변형(좌측 rail + 활성 좌측 indicator). |
.axe-tabs__list | stable | 트리거 묶음(Radix List, role=tablist). |
.axe-tabs__trigger | stable | 탭 트리거(Radix Trigger, role=tab). 활성 = [data-state="active"], 비활성 disabled = [data-disabled]. |
.axe-tabs__content | stable | 탭 패널(Radix Content, role=tabpanel). 비활성 = [data-state="inactive"] 로 숨김. |
접근성
키보드, ARIA, 구현 노트를 함께 검토합니다.
- ← → — horizontal 에서 트리거 이동(roving)
- ↑ ↓ — vertical 에서 트리거 이동
- Home / End — 첫/마지막 트리거
- Tab — 활성 트리거에서 패널로 이동
role=tablist(List) / tab(Trigger) / tabpanel(Content) 와 aria-selected·aria-controls·aria-labelledby, roving tabindex 를 전부 Radix 가 부여한다. 활성 상태는 [data-state="active"] 로 노출된다(underline/indicator 는 CSS 가 이 속성을 따라감).
기본 activationMode 는 automatic — 화살표로 트리거에 포커스가 닿으면 즉시 활성/패널 전환된다. Tabs 에 value/onValueChange 를 주면 controlled, defaultValue 만 주면 uncontrolled(둘 다 Radix Root prop).