Skip to Content

Tabs

탭 네비게이션 컴포넌트입니다.

개요

Tabs는 관련된 콘텐츠를 탭으로 전환하며 표시하는 컴포넌트입니다. Cals Tabs는 Cals 브랜드 스타일과 예약 상태 컬러가 적용되어 있으며, 예약 상태별 탭 전환과 관리 메뉴 탭에 최적화되어 있습니다. Foundation Tabs의 모든 기능을 상속합니다.

주요 특징:

  • 탭 전환 애니메이션
  • 키보드 네비게이션
  • Cals 브랜드 컬러 적용 (Pink, Blue, Purple)
  • 예약 상태 탭 완벽 지원 (Available, Pending, Confirmed, Cancelled, Completed)
  • 아이콘 및 Badge 지원
  • 반응형 디자인

사용 사례:

  • Cals 예약 상태별 탭 (전체/확정/대기/취소/완료)
  • 관리 메뉴 탭 (예약 관리/고객 관리/서비스 관리)
  • 대시보드 뷰 전환
  • 설정 카테고리

설치

npx @vortex/cli add tabs --package cals

기본 사용법

import "@vortex/ui-cals/theme"; // Cals 테마 적용 import { Tabs, TabsList, TabsTrigger, TabsContent } from "@vortex/ui-cals"; export default function Example() { return ( <Tabs defaultValue="tab1"> <TabsList> <TabsTrigger value="tab1">탭 1</TabsTrigger> <TabsTrigger value="tab2">탭 2</TabsTrigger> </TabsList> <TabsContent value="tab1"> <p>탭 1 내용</p> </TabsContent> <TabsContent value="tab2"> <p>탭 2 내용</p> </TabsContent> </Tabs> ); }

Variants (변형)

Default

기본 탭 스타일입니다.

<Tabs defaultValue="all"> <TabsList> <TabsTrigger value="all">전체</TabsTrigger> <TabsTrigger value="active">활성</TabsTrigger> <TabsTrigger value="inactive">비활성</TabsTrigger> </TabsList> <TabsContent value="all">전체 내용</TabsContent> <TabsContent value="active">활성 내용</TabsContent> <TabsContent value="inactive">비활성 내용</TabsContent> </Tabs>

With Icons

아이콘이 포함된 탭입니다.

import { Calendar, Clock, Check } from "lucide-react"; <Tabs defaultValue="reservations"> <TabsList> <TabsTrigger value="reservations"> <Calendar size={16} className="mr-xs" /> 예약 목록 </TabsTrigger> <TabsTrigger value="pending"> <Clock size={16} className="mr-xs" /> 승인 대기 </TabsTrigger> <TabsTrigger value="completed"> <Check size={16} className="mr-xs" /> 완료 </TabsTrigger> </TabsList> <TabsContent value="reservations">예약 목록</TabsContent> <TabsContent value="pending">승인 대기</TabsContent> <TabsContent value="completed">완료</TabsContent> </Tabs>;

With Badge (예약 상태별 개수 표시)

Badge가 포함된 탭입니다.

import { Badge } from "@vortex/ui-cals"; <Tabs defaultValue="all"> <TabsList> <TabsTrigger value="all"> 전체 <Badge variant="outline" size="sm" className="ml-xs"> 120 </Badge> </TabsTrigger> <TabsTrigger value="confirmed"> 예약 확정 <Badge variant="confirmed" size="sm" className="ml-xs"> 45 </Badge> </TabsTrigger> <TabsTrigger value="pending"> 승인 대기 <Badge variant="pending" size="sm" className="ml-xs"> 12 </Badge> </TabsTrigger> </TabsList> <TabsContent value="all">전체 예약</TabsContent> <TabsContent value="confirmed">확정된 예약</TabsContent> <TabsContent value="pending">승인 대기 예약</TabsContent> </Tabs>;

Cals 브랜딩

브랜드 컬러

Cals Tabs는 다음 브랜드 컬러를 사용합니다:

  • Primary (Pink): #e91e63 - 활성 탭 강조
  • Secondary (Blue): #03a9f4 - 보조 탭 강조
  • Accent (Purple): #9c27b0 - 특별 탭 강조

예약 상태 컬러 ⭐

Cals는 예약 시스템에 특화된 5가지 상태 컬러를 제공합니다:

  • Available (Green): #4caf50 - 예약 가능
  • Pending (Orange): #ff9800 - 승인 대기
  • Confirmed (Blue): #03a9f4 - 예약 확정
  • Cancelled (Red): #f44336 - 예약 취소
  • Completed (Purple): #9c27b0 - 서비스 완료

Cals 특화 사용 가이드

예약 상태별 탭 전환:

import { Tabs, TabsList, TabsTrigger, TabsContent } from "@vortex/ui-cals"; import { Badge } from "@vortex/ui-cals"; import { Calendar, Clock, Check, X, CheckCircle } from "lucide-react"; <Tabs defaultValue="all"> <TabsList> <TabsTrigger value="all"> <Calendar size={16} className="mr-xs" /> 전체 <Badge variant="outline" size="sm" className="ml-xs"> 120 </Badge> </TabsTrigger> <TabsTrigger value="available"> <Calendar size={16} className="mr-xs" /> 예약 가능 <Badge variant="available" size="sm" className="ml-xs"> 30 </Badge> </TabsTrigger> <TabsTrigger value="pending"> <Clock size={16} className="mr-xs" /> 승인 대기 <Badge variant="pending" size="sm" className="ml-xs"> 12 </Badge> </TabsTrigger> <TabsTrigger value="confirmed"> <Check size={16} className="mr-xs" /> 예약 확정 <Badge variant="confirmed" size="sm" className="ml-xs"> 45 </Badge> </TabsTrigger> <TabsTrigger value="cancelled"> <X size={16} className="mr-xs" /> 예약 취소 <Badge variant="cancelled" size="sm" className="ml-xs"> 8 </Badge> </TabsTrigger> <TabsTrigger value="completed"> <CheckCircle size={16} className="mr-xs" /> 완료 <Badge variant="completed" size="sm" className="ml-xs"> 25 </Badge> </TabsTrigger> </TabsList> <TabsContent value="all">{/* 전체 예약 목록 */}</TabsContent> <TabsContent value="available">{/* 예약 가능 목록 */}</TabsContent> <TabsContent value="pending">{/* 승인 대기 목록 */}</TabsContent> <TabsContent value="confirmed">{/* 예약 확정 목록 */}</TabsContent> <TabsContent value="cancelled">{/* 예약 취소 목록 */}</TabsContent> <TabsContent value="completed">{/* 완료 목록 */}</TabsContent> </Tabs>;

관리 메뉴 탭:

import { Tabs, TabsList, TabsTrigger, TabsContent } from "@vortex/ui-cals"; import { Calendar, Users, Package, Settings } from "lucide-react"; <Tabs defaultValue="reservations"> <TabsList> <TabsTrigger value="reservations"> <Calendar size={16} className="mr-xs" /> 예약 관리 </TabsTrigger> <TabsTrigger value="customers"> <Users size={16} className="mr-xs" /> 고객 관리 </TabsTrigger> <TabsTrigger value="services"> <Package size={16} className="mr-xs" /> 서비스 관리 </TabsTrigger> <TabsTrigger value="settings"> <Settings size={16} className="mr-xs" /> 설정 </TabsTrigger> </TabsList> <TabsContent value="reservations">{/* 예약 관리 */}</TabsContent> <TabsContent value="customers">{/* 고객 관리 */}</TabsContent> <TabsContent value="services">{/* 서비스 관리 */}</TabsContent> <TabsContent value="settings">{/* 설정 */}</TabsContent> </Tabs>;

Foundation/iCignal/Cals 비교

속성FoundationiCignalCals
활성 색상중립 블루iCignal Blue (#2196f3)Cals Pink (#e91e63)
브랜드 적용없음iCignal AnalyticsCals 예약 시스템
특화 기능없음Analytics 뷰 전환예약 상태 탭
사용 맥락범용데이터 분석예약 관리
상태 컬러✅ 5가지 예약 상태
Badge 통합✅ 상태별 개수 표시
테마중립적 테마iCignal 테마Cals 테마 (@vortex/ui-cals/theme)

import 경로 차이:

// Foundation import { Tabs } from "@vortex/ui-foundation"; // iCignal import "@vortex/ui-icignal/theme"; import { Tabs } from "@vortex/ui-icignal"; // Cals import "@vortex/ui-cals/theme"; // 테마 import 필수 import { Tabs } from "@vortex/ui-cals";

Props API

PropTypeDefaultDescription
defaultValuestring-기본 선택 탭
valuestring-선택된 탭 (제어 모드)
onValueChange(value: string) => void-탭 변경 핸들러
classNamestring-추가 CSS 클래스

접근성

Tabs 컴포넌트는 WCAG 2.1 AA 기준을 준수합니다.

ARIA 속성:

  • role="tablist" (탭 목록)
  • role="tab" (개별 탭)
  • role="tabpanel" (탭 콘텐츠)
  • aria-selected (선택 상태)

키보드 네비게이션:

  • Tab: 탭 목록으로 포커스 이동
  • Arrow Left/Right: 탭 간 이동
  • Home/End: 첫/마지막 탭으로 이동
  • Enter / Space: 탭 선택

스크린 리더 지원:

  • 탭 개수 안내
  • 현재 선택된 탭 안내
  • 탭 내용 명확하게 전달

예제

예제 1: 예약 상태별 탭 관리 ⭐

import "@vortex/ui-cals/theme"; import { Tabs, TabsList, TabsTrigger, TabsContent } from "@vortex/ui-cals"; import { Badge, Button } from "@vortex/ui-cals"; import { Card, CardHeader, CardContent } from "@vortex/ui-cals"; import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell, } from "@vortex/ui-cals"; import { Calendar, Clock, Check, X, CheckCircle, Plus } from "lucide-react"; export default function ReservationStatusTabs() { const reservationsByStatus = { all: [ { id: "#001", customer: "홍길동", date: "2024-01-20", status: "confirmed", }, { id: "#002", customer: "김영희", date: "2024-01-21", status: "pending" }, { id: "#003", customer: "이철수", date: "2024-01-22", status: "completed", }, ], available: [ { id: "#010", slot: "10:00-11:00", capacity: 5, available: 5 }, { id: "#011", slot: "14:00-15:00", capacity: 5, available: 3 }, ], pending: [ { id: "#002", customer: "김영희", date: "2024-01-21", time: "10:00" }, ], confirmed: [ { id: "#001", customer: "홍길동", date: "2024-01-20", time: "14:00" }, ], cancelled: [ { id: "#005", customer: "박민수", date: "2024-01-19", time: "16:00" }, ], completed: [ { id: "#003", customer: "이철수", date: "2024-01-18", time: "11:00" }, ], }; const counts = { all: 120, available: 30, pending: 12, confirmed: 45, cancelled: 8, completed: 25, }; return ( <Card> <CardHeader> <div className="flex items-center justify-between"> <h2 className="text-xl font-bold">예약 관리</h2> <Button variant="primary"> <Plus size={16} className="mr-xs" /> 신규 예약 </Button> </div> </CardHeader> <CardContent> <Tabs defaultValue="all"> <TabsList className="w-full grid grid-cols-6"> <TabsTrigger value="all"> <Calendar size={16} className="mr-xs" /> 전체 <Badge variant="outline" size="sm" className="ml-xs"> {counts.all} </Badge> </TabsTrigger> <TabsTrigger value="available"> <Calendar size={16} className="mr-xs" /> 예약 가능 <Badge variant="available" size="sm" className="ml-xs"> {counts.available} </Badge> </TabsTrigger> <TabsTrigger value="pending"> <Clock size={16} className="mr-xs" /> 승인 대기 <Badge variant="pending" size="sm" className="ml-xs"> {counts.pending} </Badge> </TabsTrigger> <TabsTrigger value="confirmed"> <Check size={16} className="mr-xs" /> 예약 확정 <Badge variant="confirmed" size="sm" className="ml-xs"> {counts.confirmed} </Badge> </TabsTrigger> <TabsTrigger value="cancelled"> <X size={16} className="mr-xs" /> 예약 취소 <Badge variant="cancelled" size="sm" className="ml-xs"> {counts.cancelled} </Badge> </TabsTrigger> <TabsTrigger value="completed"> <CheckCircle size={16} className="mr-xs" /> 완료 <Badge variant="completed" size="sm" className="ml-xs"> {counts.completed} </Badge> </TabsTrigger> </TabsList> <TabsContent value="all" className="mt-lg"> <Table> <TableHeader> <TableRow> <TableHead>예약번호</TableHead> <TableHead>고객명</TableHead> <TableHead>예약일</TableHead> <TableHead>상태</TableHead> </TableRow> </TableHeader> <TableBody> {reservationsByStatus.all.map((reservation) => ( <TableRow key={reservation.id}> <TableCell>{reservation.id}</TableCell> <TableCell>{reservation.customer}</TableCell> <TableCell>{reservation.date}</TableCell> <TableCell> <Badge variant={reservation.status}> {reservation.status === "confirmed" && "예약 확정"} {reservation.status === "pending" && "승인 대기"} {reservation.status === "completed" && "완료"} </Badge> </TableCell> </TableRow> ))} </TableBody> </Table> </TabsContent> <TabsContent value="available" className="mt-lg"> <Table> <TableHeader> <TableRow> <TableHead>시간대</TableHead> <TableHead>정원</TableHead> <TableHead>예약 가능</TableHead> <TableHead className="text-right">액션</TableHead> </TableRow> </TableHeader> <TableBody> {reservationsByStatus.available.map((slot) => ( <TableRow key={slot.id}> <TableCell>{slot.slot}</TableCell> <TableCell>{slot.capacity}명</TableCell> <TableCell> <Badge variant="available">{slot.available}명</Badge> </TableCell> <TableCell className="text-right"> <Button variant="primary" size="sm"> 예약하기 </Button> </TableCell> </TableRow> ))} </TableBody> </Table> </TabsContent> <TabsContent value="pending" className="mt-lg"> <Table> <TableHeader> <TableRow> <TableHead>예약번호</TableHead> <TableHead>고객명</TableHead> <TableHead>예약일시</TableHead> <TableHead className="text-right">액션</TableHead> </TableRow> </TableHeader> <TableBody> {reservationsByStatus.pending.map((reservation) => ( <TableRow key={reservation.id} className="bg-pending/10"> <TableCell>{reservation.id}</TableCell> <TableCell>{reservation.customer}</TableCell> <TableCell> {reservation.date} {reservation.time} </TableCell> <TableCell className="text-right"> <div className="flex gap-xs justify-end"> <Button variant="confirmed" size="sm"> 승인 </Button> <Button variant="outline" size="sm"> 거절 </Button> </div> </TableCell> </TableRow> ))} </TableBody> </Table> </TabsContent> {/* 나머지 TabsContent도 유사하게 구현 */} </Tabs> </CardContent> </Card> ); }

예제 2: 관리 메뉴 탭 ⭐

import "@vortex/ui-cals/theme"; import { Tabs, TabsList, TabsTrigger, TabsContent } from "@vortex/ui-cals"; import { Calendar, Users, Package, BarChart3 } from "lucide-react"; export default function AdminMenuTabs() { return ( <div className="p-lg"> <h1 className="text-2xl font-bold mb-lg">Cals 관리자</h1> <Tabs defaultValue="reservations"> <TabsList> <TabsTrigger value="reservations"> <Calendar size={18} className="mr-sm" /> 예약 관리 </TabsTrigger> <TabsTrigger value="customers"> <Users size={18} className="mr-sm" /> 고객 관리 </TabsTrigger> <TabsTrigger value="services"> <Package size={18} className="mr-sm" /> 서비스 관리 </TabsTrigger> <TabsTrigger value="analytics"> <BarChart3 size={18} className="mr-sm" /> 통계 분석 </TabsTrigger> </TabsList> <TabsContent value="reservations" className="mt-lg"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-lg"> {/* 예약 관리 대시보드 */} </div> </TabsContent> <TabsContent value="customers" className="mt-lg"> <div className="space-y-lg">{/* 고객 관리 */}</div> </TabsContent> <TabsContent value="services" className="mt-lg"> <div className="space-y-lg">{/* 서비스 관리 */}</div> </TabsContent> <TabsContent value="analytics" className="mt-lg"> <div className="space-y-lg">{/* 통계 분석 */}</div> </TabsContent> </Tabs> </div> ); }

관련 컴포넌트

Last updated on