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 비교
| 속성 | Foundation | iCignal | Cals |
|---|---|---|---|
| 활성 색상 | 중립 블루 | iCignal Blue (#2196f3) | Cals Pink (#e91e63) |
| 브랜드 적용 | 없음 | iCignal Analytics | Cals 예약 시스템 |
| 특화 기능 | 없음 | 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
| Prop | Type | Default | Description |
|---|---|---|---|
| defaultValue | string | - | 기본 선택 탭 |
| value | string | - | 선택된 탭 (제어 모드) |
| onValueChange | (value: string) => void | - | 탭 변경 핸들러 |
| className | string | - | 추가 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>
);
}관련 컴포넌트
- Foundation Tabs - 기본 버전 참조
- iCignal Tabs - iCignal 버전 참조
- Badge - 탭 개수 표시
- Button - 탭 액션
- Card - 탭 컨테이너
- Table - 탭 콘텐츠 테이블
Last updated on