# Tabs URL: /lynx/components/tabs Source: https://github.com/daangn/seed-design/blob/dev/docs/content/lynx/components/tabs.mdx 한 화면의 콘텐츠를 탭 단위로 구분하고, 탭 선택이나 좌우 스와이프로 전환하는 컴포넌트입니다. 사용 가능 버전: @seed-design/lynx-react@0.5.0, @seed-design/lynx-css@0.9.0 ## Preview ```tsx import "./styles"; import { root, useState } from "@lynx-js/react"; import { Tabs, useSeedClassName } from "@seed-design/lynx-react"; function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); const [value, setValue] = useState("one"); function handleValueChange(nextValue: string) { "background only"; setValue(nextValue); } return ( 선택된 탭: {value} 첫 번째 두 번째 세 번째 첫 번째 콘텐츠 두 번째 콘텐츠 세 번째 콘텐츠 ); } root.render(); ``` ## Installation - npm: npx @seed-design/cli add ui:tabs - pnpm: pnpm dlx @seed-design/cli add ui:tabs - yarn: yarn dlx @seed-design/cli add ui:tabs - bun: bun x @seed-design/cli add ui:tabs ## Props ### `TabsRoot` ### `TabsList` ### `TabsTrigger` ### `TabsCarousel` ### `TabsContent` ## Usage ```tsx import { TabsCarousel, TabsContent, TabsList, TabsRoot, TabsTrigger, } from "@/components/ui/tabs"; export function App() { return ( 첫 번째 두 번째 첫 번째 콘텐츠 두 번째 콘텐츠 ); } ``` Registry의 `TabsList`는 `Tabs.Indicator`를 자동으로 추가합니다. `TabsCarousel`도 내부에서 `Tabs.CarouselCamera`를 조립하므로 각 `TabsContent`만 자식으로 전달하면 됩니다. `TabsCarousel`은 Lynx 네이티브 ``를 사용합니다. Carousel에 앱 레이아웃에 맞는 높이를 지정해야 하며, `swipeable`을 설정하면 좌우 스와이프로 탭을 바꿀 수 있습니다. iOS에서는 화면 왼쪽 32px 안에서 시작하는 뒤로가기 제스처를 우선합니다. 앱의 제스처 영역과 맞춰야 한다면 `iosBackGestureEdgeWidth`로 너비를 조정하세요. ## Examples ### Swipeable Trigger를 탭하거나 콘텐츠를 좌우로 밀면 선택 값과 Indicator가 함께 이동합니다. ```tsx import "./styles"; import { root, useState } from "@lynx-js/react"; import { Tabs, useSeedClassName } from "@seed-design/lynx-react"; function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); const [value, setValue] = useState("one"); function handleValueChange(nextValue: string) { "background only"; setValue(nextValue); } return ( 선택된 탭: {value} 첫 번째 두 번째 세 번째 왼쪽이나 오른쪽으로 밀어보세요. 두 번째 콘텐츠 세 번째 콘텐츠 ); } root.render(); ``` ### Disabled `disabled` Trigger는 탭할 수 없습니다. Carousel이 비활성 탭에 도달하면 다음 활성 탭으로 이동합니다. ```tsx import "./styles"; import { root } from "@lynx-js/react"; import { Tabs, useSeedClassName } from "@seed-design/lynx-react"; function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); return ( 첫 번째 비활성 탭 세 번째 첫 번째 콘텐츠 비활성 콘텐츠 세 번째 콘텐츠 ); } root.render(); ``` ### Layout `triggerLayout="fill"`은 Trigger를 같은 너비로 배치합니다. `triggerLayout="hug"`은 레이블 너비에 맞춰 배치하고, 화면을 넘으면 List를 가로로 스크롤합니다. ```tsx import "./styles"; import { root } from "@lynx-js/react"; import { Tabs, useSeedClassName } from "@seed-design/lynx-react"; function TabsExample({ triggerLayout }: { triggerLayout: "fill" | "hug" }) { return ( triggerLayout="{triggerLayout}" 첫 번째 길이가 긴 두 번째 탭 세 번째 ); } function Root() { const seedClassName = useSeedClassName({ colorMode: "system" }); return ( ); } root.render(); ``` `size`는 `small`과 `medium`을 지원합니다. 긴 레이블과 큰 글자 크기에서도 한 줄을 유지하며 `hug` List의 가로 스크롤로 처리합니다. ## Web Version Differences | 항목 | React Web | Lynx | | --------- | --------------------------------- | ----------------------------------------------- | | 렌더링 요소 | HTML `div`, `button` | 네이티브 `view`, `text`, `scroll-view`, `viewpager` | | 탭 선택 이벤트 | `onClick` 기반 | `bindtap` 기반, 공개 상태 이벤트는 `onValueChange` | | Carousel | Embla Carousel | 네이티브 `` | | 가로 List | CSS overflow | 네이티브 `` | | 제어 방식 | `value`, `defaultValue` | 동일 | | 접근성 | ARIA `tablist`, `tab`, `tabpanel` | Lynx `accessibility-*` 속성 | | Indicator | DOM 측정과 CSS 변수 | `bindlayoutchange` 측정과 viewpager offset 보간 | 스와이프 관성, 비활성 탭 건너뛰기, Indicator 이동은 QR 코드 탭에서 Lynx Explorer로 확인하세요. 문서의 WebLynx 미리보기와 네이티브 기기의 제스처 결과가 다를 수 있습니다. ## Unsupported Lynx Features 현재 Lynx 구현은 다음 Web 기능을 지원하지 않습니다. - 세로 `orientation` - 키보드 방향키, Home/End, roving focus - RTL 순서와 스와이프 방향 반전 - `asChild` - `lazyMount`, `unmountOnExit` - Carousel의 `loop`, `autoHeight`, `dragThreshold` - `carouselPreventDrag` Lynx의 native viewpager는 page slot을 유지해야 하므로 Carousel 콘텐츠를 lazy unmount하지 않습니다. 높이가 다른 콘텐츠는 `autoHeight` 대신 Carousel 컨테이너 높이를 앱에서 정하세요.