# Tabs URL: /lynx/components/tabs Source: https://github.com/daangn/seed-design/blob/dev/docs/content/lynx/components/tabs.mdx 한 화면의 콘텐츠를 탭 단위로 구분하고, 탭 선택이나 좌우 스와이프로 전환하는 컴포넌트입니다. Lynx Engine 최소 버전: 3.6 사용 XElement: , 사용 가능 버전: @seed-design/lynx-react@0.5.0, @seed-design/lynx-css@0.9.0 ## Preview ```tsx import "./styles"; import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "@/components/ui/tabs"; export default function Example() { return ( 라벨1 라벨2 라벨3 Content 1 Content 2 Content 3 ); } ``` ## 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 ( 첫 번째 두 번째 첫 번째 콘텐츠 두 번째 콘텐츠 ); } ``` `TabsCarousel`에는 `TabsContent`를 자식으로 전달합니다. 앱 레이아웃에 맞는 높이를 지정하고, `swipeable`을 설정하면 좌우 스와이프로 탭을 바꿀 수 있습니다. iOS의 화면 왼쪽 가장자리에서 시작하는 뒤로 가기 제스처 범위는 `iosBackGestureEdgeWidth`로 조절할 수 있습니다. `TabsList`의 `scrollAlign`은 선택한 탭을 가로 목록에 맞추는 방식입니다. `"nearest"`, `"start"`, `"center"`, `"end"`를 지원하며 기본값은 `"start"`입니다. ## Examples ### Layout Fill (Default) ```tsx import "./styles"; import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "@/components/ui/tabs"; export default function Example() { return ( 라벨1 라벨2 라벨3 Content 1 Content 2 Content 3 ); } ``` ### Layout Hug ```tsx import "./styles"; import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "@/components/ui/tabs"; export default function Example() { return ( 라벨1 라벨2 라벨3 Content 1 Content 2 Content 3 ); } ``` ### Size Medium ```tsx import "./styles"; import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "@/components/ui/tabs"; export default function Example() { return ( 라벨1 라벨2 라벨3 Content 1 Content 2 Content 3 ); } ``` ### Size Small (Default) ```tsx import "./styles"; import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "@/components/ui/tabs"; export default function Example() { return ( 라벨1 라벨2 라벨3 Content 1 Content 2 Content 3 ); } ``` ### Transition Lynx의 `TabsCarousel`은 탭을 선택할 때 native viewpager의 `selectTab`을 `smooth: false`로 호출하므로 콘텐츠가 즉시 바뀝니다. 전환 효과가 필요하면 `TabsCarousel` 대신 선택 값을 기준으로 콘텐츠를 직접 렌더링하고 앱에서 애니메이션을 적용하세요. ### Swipeable Trigger를 탭하거나 콘텐츠를 좌우로 밀면 선택 값과 Indicator가 함께 이동합니다. ```tsx import "./styles"; import { TabsCarousel, TabsContent, TabsList, TabsRoot, TabsTrigger } from "@/components/ui/tabs"; export default function Example() { return ( 라벨1 라벨2 라벨3 Content 1 Content 2 Content 3 ); } ``` ### Carousel Prevent Drag Lynx는 `carouselPreventDrag`를 지원하지 않습니다. Carousel 안에서 드래그와 충돌하는 조작 요소는 Carousel 밖에 배치하세요. ### Disabled `disabled` Trigger는 탭할 수 없습니다. Carousel이 비활성 탭에 도달하면 다음 활성 탭으로 이동합니다. ```tsx import "./styles"; import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "@/components/ui/tabs"; export default function Example() { return ( 라벨1 라벨2 라벨3 Content 1 Content 2 Content 3 ); } ``` ### Notification ```tsx import "./styles"; import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "@/components/ui/tabs"; export default function Example() { return ( 라벨1 라벨2 라벨3 Content 1 Content 2 Content 3 ); } ``` ### Sticky List 탭이 전체 화면을 차지하고 `TabsList`가 화면 위에 고정되어야 할 때 사용합니다. ```tsx import "./styles"; import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "@/components/ui/tabs"; export default function Example() { return ( 라벨1 라벨2 라벨3 Content 1 Content 2 Content 3 ); } ``` ### Standalone `TabsContent`를 사용하지 않고 콘텐츠 영역을 직접 구성할 때 사용합니다. 이 구성에서는 Tabs가 제공하는 스와이프 기능을 사용할 수 없습니다. ```tsx import "./styles"; import { useState } from "@lynx-js/react"; import { TabsList, TabsRoot, TabsTrigger } from "@/components/ui/tabs"; export default function Example() { const [activeTab, setActiveTab] = useState("1"); function handleValueChange(value: string) { "background only"; setActiveTab(value); } return ( 라벨1 라벨2 라벨3 {activeTab === "1" && ( Content 1 )} {activeTab === "2" && ( Content 2 )} {activeTab === "3" && ( Content 3 )} ); } ``` ### Dynamic Height `TabsCarousel`의 `autoHeight`, `lazyMount`, `unmountOnExit` 없이도 `TabsContent`를 Carousel 밖에 배치하면 선택된 콘텐츠 높이에 맞춰 아래 콘텐츠의 위치를 바꿀 수 있습니다. 이 구성은 스와이프를 제공하지 않습니다. ```tsx import "./styles"; import { TabsContent, TabsList, TabsRoot, TabsTrigger } from "@/components/ui/tabs"; export default function Example() { return ( 라벨1 라벨2 라벨3 Content 1 Content 2 Content 3 아래 콘텐츠 ); } ``` ### Scroll to Top `TabsTrigger`의 `bindtap`은 이미 선택된 Trigger를 다시 탭할 때도 호출됩니다. 아래 예시는 네 번째 항목부터 보이도록 시작하며, 선택된 탭을 다시 탭하면 현재 콘텐츠의 `scroll-view`가 맨 위로 이동합니다. ```tsx import "./styles"; import { useCallback, useRef, useState } from "@lynx-js/react"; import type { NodesRef } from "@lynx-js/types"; import { TabsCarousel, TabsContent, TabsList, TabsRoot, TabsTrigger } from "@/components/ui/tabs"; const SCROLL_ITEMS = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; function scrollToTop(ref: NodesRef | null) { "background only"; ref?.invoke({ method: "scrollTo", params: { offset: 0, smooth: true } }).exec(); } export default function Example() { const [currentTab, setCurrentTab] = useState("1"); const firstContentRef = useRef(null); const secondContentRef = useRef(null); const setFirstContentRef = useCallback((node: NodesRef | null) => { "background only"; firstContentRef.current = node; }, []); const setSecondContentRef = useCallback((node: NodesRef | null) => { "background only"; secondContentRef.current = node; }, []); function handleFirstTriggerTap() { "background only"; if (currentTab === "1") scrollToTop(firstContentRef.current); } function handleSecondTriggerTap() { "background only"; if (currentTab === "2") scrollToTop(secondContentRef.current); } return ( 라벨1 라벨2 {SCROLL_ITEMS.map((item) => ( Content 1 · {item} ))} {SCROLL_ITEMS.map((item) => ( Content 2 · {item} ))} ); } ``` ## Web Version Differences - 탭 이벤트는 `onClick` 대신 `bindtap`으로 받습니다. - Carousel은 네이티브 ``, 가로 탭 목록은 ``를 사용합니다. - 접근성은 ARIA 대신 Lynx의 `accessibility-*` 속성을 사용합니다. 스와이프와 Indicator 이동은 QR 코드 패널에서 Lynx Explorer로 확인하세요. 브라우저 미리보기와 네이티브 기기의 제스처 결과가 다를 수 있습니다. ## Unsupported Lynx Features - 세로 `orientation` - 키보드 방향키, Home/End, roving focus - RTL 순서와 스와이프 방향 반전 - `asChild` - `lazyMount`, `unmountOnExit` - Carousel의 `loop`, `autoHeight`, `dragThreshold`, `carouselPreventDrag` - 콘텐츠 전환 애니메이션