API
tabs(TabItem[]) · activeKey · onChange(key) · baseId(a11y id prefix)
TabItem
key · label · badge?(number) · disabled?(boolean)
TabsContent
tabKey + baseId — aria-controls/aria-labelledby 자동 연결
배지
badge > 0일 때 자동 표시, 99 초과 시 '99+' 처리
접근성
Radix가 tablist/tab/tabpanel + arrow-key 네비게이션 자동 관리

기본

라이브 (tabs + TabsContent activeKey onChange 상태 관리)

시험 기간, 접근 규칙, 준비 상태를 확인합니다.

코드 보기tsx
import { useState } from "react";
import { Tabs, TabsContent } from "@olundot/ui";

export function TabsBasic() {
  const [active, setActive] = useState("overview");
  const tabs = [
    { key: "overview", label: "개요" },
    { key: "questions", label: "문항" },
    { key: "students", label: "수강생" },
  ];
  return (
    <Tabs tabs={tabs} activeKey={active} onChange={setActive} baseId="basic-tabs">
      <TabsContent tabKey="overview" baseId="basic-tabs">
        <p style={{ padding: "16px 0", color: "var(--text-secondary)", fontSize: "0.875rem" }}>
          시험 기간, 접근 규칙, 준비 상태를 확인합니다.
        </p>
      </TabsContent>
      <TabsContent tabKey="questions" baseId="basic-tabs">
        <p style={{ padding: "16px 0", color: "var(--text-secondary)", fontSize: "0.875rem" }}>
          32개 문항 목록입니다.
        </p>
      </TabsContent>
      <TabsContent tabKey="students" baseId="basic-tabs">
        <p style={{ padding: "16px 0", color: "var(--text-secondary)", fontSize: "0.875rem" }}>
          128명의 수강생이 등록되어 있습니다.
        </p>
      </TabsContent>
    </Tabs>
  );
}

배지 포함

라이브 (tab badge — 카운트 표시)

응시 대기 12명

코드 보기tsx
import { useState } from "react";
import { Tabs, TabsContent } from "@olundot/ui";

export function TabsWithBadges() {
  const [active, setActive] = useState("pending");
  const tabs = [
    { key: "all", label: "전체", badge: 48 },
    { key: "pending", label: "대기", badge: 12 },
    { key: "submitted", label: "제출", badge: 36 },
    { key: "graded", label: "채점 완료", badge: 0 },
  ];
  return (
    <Tabs tabs={tabs} activeKey={active} onChange={setActive} baseId="badge-tabs">
      <TabsContent tabKey="all" baseId="badge-tabs">
        <p style={{ padding: "16px 0", color: "var(--text-secondary)", fontSize: "0.875rem" }}>전체 48명</p>
      </TabsContent>
      <TabsContent tabKey="pending" baseId="badge-tabs">
        <p style={{ padding: "16px 0", color: "var(--text-secondary)", fontSize: "0.875rem" }}>응시 대기 12명</p>
      </TabsContent>
      <TabsContent tabKey="submitted" baseId="badge-tabs">
        <p style={{ padding: "16px 0", color: "var(--text-secondary)", fontSize: "0.875rem" }}>제출 완료 36명</p>
      </TabsContent>
      <TabsContent tabKey="graded" baseId="badge-tabs">
        <p style={{ padding: "16px 0", color: "var(--text-secondary)", fontSize: "0.875rem" }}>채점 완료 0명</p>
      </TabsContent>
    </Tabs>
  );
}

비활성 탭

정적 (disabled tab — pointer-events-none + text-disabled)

발행된 강의 목록입니다.

코드 보기tsx
import { useState } from "react";
import { Tabs, TabsContent } from "@olundot/ui";

export function TabsDisabled() {
  const [active, setActive] = useState("published");
  const tabs = [
    { key: "published", label: "발행됨" },
    { key: "draft", label: "초안" },
    { key: "archived", label: "보관됨", disabled: true },
    { key: "deleted", label: "삭제됨", disabled: true },
  ];
  return (
    <Tabs tabs={tabs} activeKey={active} onChange={setActive} baseId="disabled-tabs">
      <TabsContent tabKey="published" baseId="disabled-tabs">
        <p style={{ padding: "16px 0", color: "var(--text-secondary)", fontSize: "0.875rem" }}>
          발행된 강의 목록입니다.
        </p>
      </TabsContent>
      <TabsContent tabKey="draft" baseId="disabled-tabs">
        <p style={{ padding: "16px 0", color: "var(--text-secondary)", fontSize: "0.875rem" }}>
          초안 목록입니다.
        </p>
      </TabsContent>
      <TabsContent tabKey="archived" baseId="disabled-tabs">
        <p style={{ padding: "16px 0", color: "var(--text-secondary)", fontSize: "0.875rem" }}>
          보관된 항목 (비활성)
        </p>
      </TabsContent>
      <TabsContent tabKey="deleted" baseId="disabled-tabs">
        <p style={{ padding: "16px 0", color: "var(--text-secondary)", fontSize: "0.875rem" }}>
          삭제된 항목 (비활성)
        </p>
      </TabsContent>
    </Tabs>
  );
}