Skip to Content

Table

데이터를 표 형태로 표시하는 테이블 컴포넌트입니다.

개요

Table은 구조화된 데이터를 표 형태로 표시하는 컴포넌트입니다. Cals Table은 Cals 브랜드 스타일과 예약 상태 컬러가 적용되어 있으며, 예약 목록과 고객 관리 데이터를 효과적으로 표시합니다. Foundation Table의 모든 기능을 상속합니다.

주요 특징:

  • 정렬 가능한 컬럼
  • 예약 상태별 Row 색상
  • Cals 브랜드 컬러 적용 (Pink, Blue, Purple)
  • 예약 상태 컬러 완벽 지원 (Available, Pending, Confirmed, Cancelled, Completed)
  • 필터링 및 검색
  • 페이지네이션

사용 사례:

  • Cals 예약 목록 테이블 (상태별 row 색상)
  • 고객 예약 히스토리
  • 서비스 예약 현황
  • 고객 관리 목록

설치

npx @vortex/cli add table --package cals

기본 사용법

import "@vortex/ui-cals/theme"; // Cals 테마 적용 import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell, } from "@vortex/ui-cals"; export default function Example() { return ( <Table> <TableHeader> <TableRow> <TableHead>예약번호</TableHead> <TableHead>고객명</TableHead> <TableHead>상태</TableHead> </TableRow> </TableHeader> <TableBody> <TableRow> <TableCell>#12345</TableCell> <TableCell>홍길동</TableCell> <TableCell>예약 확정</TableCell> </TableRow> </TableBody> </Table> ); }

Variants (변형)

Default

기본 테이블 스타일입니다.

<Table> <TableHeader> <TableRow> <TableHead>컬럼 1</TableHead> <TableHead>컬럼 2</TableHead> </TableRow> </TableHeader> <TableBody> <TableRow> <TableCell>데이터 1</TableCell> <TableCell>데이터 2</TableCell> </TableRow> </TableBody> </Table>

With Status Colors (예약 상태별 Row 색상)

예약 상태에 따라 Row 배경색이 변경됩니다.

import { Badge } from "@vortex/ui-cals"; <Table> <TableHeader> <TableRow> <TableHead>예약번호</TableHead> <TableHead>상태</TableHead> </TableRow> </TableHeader> <TableBody> <TableRow className="bg-available/10"> <TableCell>#001</TableCell> <TableCell> <Badge variant="available">예약 가능</Badge> </TableCell> </TableRow> <TableRow className="bg-pending/10"> <TableCell>#002</TableCell> <TableCell> <Badge variant="pending">승인 대기</Badge> </TableCell> </TableRow> <TableRow className="bg-confirmed/10"> <TableCell>#003</TableCell> <TableCell> <Badge variant="confirmed">예약 확정</Badge> </TableCell> </TableRow> <TableRow className="bg-cancelled/10"> <TableCell>#004</TableCell> <TableCell> <Badge variant="cancelled">예약 취소</Badge> </TableCell> </TableRow> <TableRow className="bg-completed/10"> <TableCell>#005</TableCell> <TableCell> <Badge variant="completed">서비스 완료</Badge> </TableCell> </TableRow> </TableBody> </Table>;

With Actions

액션 버튼이 포함된 테이블입니다.

import { Button } from "@vortex/ui-cals"; import { Eye, Edit, Trash } from "lucide-react"; <Table> <TableHeader> <TableRow> <TableHead>예약번호</TableHead> <TableHead>고객명</TableHead> <TableHead className="text-right">액션</TableHead> </TableRow> </TableHeader> <TableBody> <TableRow> <TableCell>#12345</TableCell> <TableCell>홍길동</TableCell> <TableCell className="text-right"> <div className="flex gap-xs justify-end"> <Button variant="ghost" size="sm"> <Eye size={14} /> </Button> <Button variant="ghost" size="sm"> <Edit size={14} /> </Button> <Button variant="ghost" size="sm"> <Trash size={14} /> </Button> </div> </TableCell> </TableRow> </TableBody> </Table>;

Cals 브랜딩

브랜드 컬러

Cals Table은 다음 브랜드 컬러를 사용합니다:

  • Primary (Pink): #e91e63 - 헤더 강조, CTA 버튼
  • Secondary (Blue): #03a9f4 - 링크, 보조 액션
  • Accent (Purple): #9c27b0 - 특별 상태 표시

예약 상태 컬러 ⭐

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

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

Cals 특화 사용 가이드

예약 상태별 Row 색상:

// bg-{status}/10 클래스로 상태별 배경색 적용 <TableRow className="bg-available/10"> // 연한 Green <TableRow className="bg-pending/10"> // 연한 Orange <TableRow className="bg-confirmed/10"> // 연한 Blue <TableRow className="bg-cancelled/10"> // 연한 Red <TableRow className="bg-completed/10"> // 연한 Purple

예약 목록 테이블:

import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from '@vortex/ui-cals' import { Badge, Button } from '@vortex/ui-cals' import { Calendar, Clock, Check, X } from 'lucide-react' const reservations = [ { id: '#001', customer: '홍길동', date: '2024-01-20 14:00', service: '프리미엄', status: 'confirmed' }, { id: '#002', customer: '김영희', date: '2024-01-21 10:00', service: '스탠다드', status: 'pending' }, { id: '#003', customer: '이철수', date: '2024-01-22 15:30', service: 'VIP', status: 'available' } ] <Table> <TableHeader> <TableRow> <TableHead>예약번호</TableHead> <TableHead>고객명</TableHead> <TableHead>예약일시</TableHead> <TableHead>서비스</TableHead> <TableHead>상태</TableHead> <TableHead className="text-right">액션</TableHead> </TableRow> </TableHeader> <TableBody> {reservations.map((reservation) => ( <TableRow key={reservation.id} className={`bg-${reservation.status}/10`}> <TableCell className="font-medium">{reservation.id}</TableCell> <TableCell>{reservation.customer}</TableCell> <TableCell> <div className="flex items-center gap-xs"> <Calendar size={14} /> {reservation.date} </div> </TableCell> <TableCell>{reservation.service}</TableCell> <TableCell> <Badge variant={reservation.status}> {reservation.status === 'confirmed' && '예약 확정'} {reservation.status === 'pending' && '승인 대기'} {reservation.status === 'available' && '예약 가능'} </Badge> </TableCell> <TableCell className="text-right"> <div className="flex gap-xs justify-end"> <Button variant="ghost" size="sm"> <Check size={14} /> </Button> <Button variant="ghost" size="sm"> <X size={14} /> </Button> </div> </TableCell> </TableRow> ))} </TableBody> </Table>

Foundation/iCignal/Cals 비교

속성FoundationiCignalCals
브랜드 컬러중립 회색iCignal BlueCals Pink/Blue/Purple
특화 기능없음Analytics 데이터예약 상태 Row 색상
사용 맥락범용데이터 분석예약 관리
상태 컬러✅ 5가지 예약 상태
Row 색상✅ 상태별 배경색
테마중립적 테마iCignal 테마Cals 테마 (@vortex/ui-cals/theme)

import 경로 차이:

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

Props API

PropTypeDefaultDescription
classNamestring-추가 CSS 클래스
childrenReactNode-테이블 내용

접근성

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

시맨틱 HTML:

  • <table>, <thead>, <tbody>, <tr>, <th>, <td> 사용
  • scope 속성으로 헤더-데이터 관계 명시

키보드 네비게이션:

  • Tab: 테이블 내 포커스 가능한 요소로 이동
  • Arrow Keys: 셀 간 네비게이션 (고급 기능)

스크린 리더 지원:

  • 테이블 캡션 제공 (선택사항)
  • 헤더가 명확하게 읽힘
  • 상태 정보가 정확하게 전달됨

색상 대비:

  • 텍스트와 배경 4.5:1 이상
  • 예약 상태 Row 색상 대비 충족

예제

예제 1: 예약 목록 테이블 ⭐

import "@vortex/ui-cals/theme"; import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell, } from "@vortex/ui-cals"; import { Badge, Button } from "@vortex/ui-cals"; import { Card, CardHeader, CardContent } from "@vortex/ui-cals"; import { Calendar, Clock, User, Phone, Check, X, Eye } from "lucide-react"; export default function ReservationListTable() { const reservations = [ { id: "#12345", customer: "홍길동", phone: "010-1234-5678", date: "2024-01-20", time: "14:00", service: "프리미엄 패키지", price: "150,000원", status: "confirmed", }, { id: "#12346", customer: "김영희", phone: "010-2345-6789", date: "2024-01-21", time: "10:00", service: "스탠다드 패키지", price: "100,000원", status: "pending", }, { id: "#12347", customer: "이철수", phone: "010-3456-7890", date: "2024-01-22", time: "15:30", service: "VIP 패키지", price: "200,000원", status: "available", }, { id: "#12348", customer: "박민수", phone: "010-4567-8901", date: "2024-01-19", time: "11:00", service: "베이직 패키지", price: "80,000원", status: "cancelled", }, { id: "#12349", customer: "정수진", phone: "010-5678-9012", date: "2024-01-18", time: "16:00", service: "프리미엄 패키지", price: "150,000원", status: "completed", }, ]; const getStatusBadge = (status) => { const statusMap = { available: { label: "예약 가능", icon: Calendar }, pending: { label: "승인 대기", icon: Clock }, confirmed: { label: "예약 확정", icon: Check }, cancelled: { label: "예약 취소", icon: X }, completed: { label: "서비스 완료", icon: Check }, }; const { label, icon: Icon } = statusMap[status]; return ( <Badge variant={status}> <Icon size={14} className="mr-xs" /> {label} </Badge> ); }; return ( <Card> <CardHeader> <div className="flex items-center justify-between"> <h2 className="text-xl font-bold">예약 목록</h2> <Button variant="primary"> <Calendar size={16} className="mr-xs" /> 신규 예약 등록 </Button> </div> </CardHeader> <CardContent> <Table> <TableHeader> <TableRow> <TableHead>예약번호</TableHead> <TableHead>고객 정보</TableHead> <TableHead>예약 일시</TableHead> <TableHead>서비스</TableHead> <TableHead className="text-right">금액</TableHead> <TableHead>상태</TableHead> <TableHead className="text-right">액션</TableHead> </TableRow> </TableHeader> <TableBody> {reservations.map((reservation) => ( <TableRow key={reservation.id} className={`bg-${reservation.status}/10 hover:bg-${reservation.status}/20 transition-colors`} > <TableCell className="font-medium">{reservation.id}</TableCell> <TableCell> <div className="space-y-xs"> <div className="flex items-center gap-xs"> <User size={14} className="text-muted-foreground" /> <span className="font-medium"> {reservation.customer} </span> </div> <div className="flex items-center gap-xs text-sm text-muted-foreground"> <Phone size={12} /> {reservation.phone} </div> </div> </TableCell> <TableCell> <div className="space-y-xs"> <div className="flex items-center gap-xs"> <Calendar size={14} className="text-muted-foreground" /> {reservation.date} </div> <div className="flex items-center gap-xs text-sm text-muted-foreground"> <Clock size={12} /> {reservation.time} </div> </div> </TableCell> <TableCell>{reservation.service}</TableCell> <TableCell className="text-right font-medium"> {reservation.price} </TableCell> <TableCell>{getStatusBadge(reservation.status)}</TableCell> <TableCell className="text-right"> <div className="flex gap-xs justify-end"> <Button variant="ghost" size="sm" aria-label="상세보기"> <Eye size={14} /> </Button> {reservation.status === "pending" && ( <> <Button variant="ghost" size="sm" aria-label="승인"> <Check size={14} className="text-green-600" /> </Button> <Button variant="ghost" size="sm" aria-label="거절"> <X size={14} className="text-red-600" /> </Button> </> )} </div> </TableCell> </TableRow> ))} </TableBody> </Table> </CardContent> </Card> ); }

예제 2: 고객 예약 히스토리 ⭐

import "@vortex/ui-cals/theme"; import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell, } from "@vortex/ui-cals"; import { Badge } from "@vortex/ui-cals"; import { Star, Calendar } from "lucide-react"; export default function CustomerReservationHistory() { const history = [ { date: "2024-01-18", service: "프리미엄 패키지", status: "completed", rating: 5, }, { date: "2024-01-15", service: "스탠다드 패키지", status: "completed", rating: 4, }, { date: "2024-01-20", service: "VIP 패키지", status: "confirmed", rating: null, }, { date: "2024-01-10", service: "베이직 패키지", status: "cancelled", rating: null, }, ]; return ( <div className="space-y-md"> <h3 className="text-lg font-semibold">예약 이력</h3> <Table> <TableHeader> <TableRow> <TableHead>예약일</TableHead> <TableHead>서비스</TableHead> <TableHead>상태</TableHead> <TableHead>평점</TableHead> </TableRow> </TableHeader> <TableBody> {history.map((item, index) => ( <TableRow key={index} className={`bg-${item.status}/10`}> <TableCell> <div className="flex items-center gap-xs"> <Calendar size={14} /> {item.date} </div> </TableCell> <TableCell>{item.service}</TableCell> <TableCell> <Badge variant={item.status}> {item.status === "completed" && "완료"} {item.status === "confirmed" && "확정"} {item.status === "cancelled" && "취소"} </Badge> </TableCell> <TableCell> {item.rating ? ( <div className="flex items-center gap-xs"> {[...Array(item.rating)].map((_, i) => ( <Star key={i} size={14} className="fill-yellow-400 text-yellow-400" /> ))} </div> ) : ( <span className="text-muted-foreground text-sm">-</span> )} </TableCell> </TableRow> ))} </TableBody> </Table> </div> ); }

관련 컴포넌트

Last updated on