Skip to Content

Badge

상태나 카테고리를 표시하는 뱃지 컴포넌트입니다.

개요

Badge는 작은 라벨 형태로 상태, 카테고리, 또는 개수를 표시하는 컴포넌트입니다. Cals Badge는 Cals 브랜드 컬러(Pink, Blue, Purple)와 예약 상태 컬러 5가지를 활용하여 예약 시스템에서 직관적으로 정보를 전달합니다.

주요 특징:

  • 5가지 기본 Variant + 5가지 예약 상태 Variant
  • 3가지 Size (sm, md, lg)
  • Cals 브랜드 컬러 적용
  • 예약 상태 컬러 완벽 지원 (Available, Pending, Confirmed, Cancelled, Completed)
  • 닫기 버튼 옵션
  • 숫자 뱃지 지원

사용 사례:

  • Cals 예약 상태 표시 (예약 가능, 승인 대기, 확정, 취소, 완료)
  • 예약 목록/캘린더의 상태 뱃지
  • 알림 개수 표시
  • 예약 카테고리 태그

설치

npx @vortex/cli add badge --package cals

기본 사용법

import "@vortex/ui-cals/theme"; import { Badge } from "@vortex/ui-cals"; export default function Example() { return <Badge>New</Badge>; }

Variants (변형)

Default

<Badge variant="default">Default</Badge>

Success

<Badge variant="success">완료</Badge>

Warning

<Badge variant="warning">주의 필요</Badge>

Danger

<Badge variant="danger">오류</Badge>

Info

<Badge variant="info">정보</Badge>

예약 상태 Variants ⭐

Available (예약 가능)

예약 가능한 상태를 나타내는 Green 뱃지입니다.

<Badge variant="available">예약 가능</Badge>

사용 예시:

  • 예약 가능한 시간대 표시
  • 예약 가능 좌석/테이블 표시
  • 예약 캘린더의 가능 날짜

Pending (승인 대기)

승인 대기 상태를 나타내는 Orange 뱃지입니다.

<Badge variant="pending">승인 대기</Badge>

사용 예시:

  • 관리자 승인 대기 예약
  • 결제 대기 예약
  • 확인 대기 상태

Confirmed (예약 확정)

예약 확정 상태를 나타내는 Blue 뱃지입니다.

<Badge variant="confirmed">예약 확정</Badge>

사용 예시:

  • 확정된 예약 표시
  • 확인 완료된 예약
  • 진행 예정 예약

Cancelled (예약 취소)

예약 취소 상태를 나타내는 Red 뱃지입니다.

<Badge variant="cancelled">예약 취소</Badge>

사용 예시:

  • 취소된 예약 표시
  • 노쇼(No-show) 표시
  • 환불 완료 표시

Completed (서비스 완료)

서비스 완료 상태를 나타내는 Purple 뱃지입니다.

<Badge variant="completed">서비스 완료</Badge>

사용 예시:

  • 완료된 예약 표시
  • 서비스 제공 완료
  • 리뷰 대기 상태

Sizes (크기)

Small

<Badge size="sm">Small</Badge>

Medium (기본)

<Badge size="md">Medium</Badge>

Large

<Badge size="lg">Large</Badge>

Cals 브랜딩

브랜드 컬러

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

  • 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 특화 사용 가이드

예약 상태 표시:

<Badge variant="available">예약 가능</Badge> <Badge variant="pending">승인 대기</Badge> <Badge variant="confirmed">예약 확정</Badge> <Badge variant="cancelled">예약 취소</Badge> <Badge variant="completed">서비스 완료</Badge>

예약 목록에서 사용:

<div className="flex gap-sm"> <Badge variant="available">10:00 예약 가능</Badge> <Badge variant="pending">11:00 승인 대기</Badge> <Badge variant="confirmed">14:00 확정</Badge> <Badge variant="completed">16:00 완료</Badge> </div>

Foundation/iCignal/Cals 비교

속성FoundationiCignalCals
Primary Color중립 블루#2196f3 (iCignal Blue)#e91e63 (Cals Pink)
브랜드 적용없음iCignal AnalyticsCals 예약 시스템
특화 Variants없음없음5가지 예약 상태
사용 맥락범용데이터 상태 표시예약 상태 표시
예약 상태 지원✅ Available/Pending/Confirmed/Cancelled/Completed
테마중립적 테마iCignal 테마Cals 테마 (@vortex/ui-cals/theme)

import 경로 차이:

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

Props API

PropTypeDefaultDescription
variant’default’ | ‘success’ | ‘warning’ | ‘danger’ | ‘info’ | ‘available’ | ‘pending’ | ‘confirmed’ | ‘cancelled’ | ‘completed''default’뱃지 변형
size’sm’ | ‘md’ | ‘lg''md’뱃지 크기
closablebooleanfalse닫기 버튼 표시
onClose() => void-닫기 버튼 클릭 핸들러
classNamestring-추가 CSS 클래스
childrenReactNode-뱃지 내용

접근성

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

ARIA 속성:

  • role="status" (상태 뱃지)
  • aria-label (닫기 버튼)

색상 대비 (Cals 브랜드 컬러 기준):

  • Available: 4.5:1 이상
  • Pending: 4.5:1 이상
  • Confirmed: 4.5:1 이상
  • Cancelled: 4.5:1 이상
  • Completed: 4.5:1 이상

예제

예제 1: 예약 목록의 상태 표시 ⭐

import "@vortex/ui-cals/theme"; import { Badge } from "@vortex/ui-cals"; import { Calendar, Clock, Check, X, CheckCircle } from "lucide-react"; export default function ReservationList() { const reservations = [ { id: 1, customer: "홍길동", date: "2024-01-20", time: "10:00", status: "available", statusText: "예약 가능", }, { id: 2, customer: "김철수", date: "2024-01-20", time: "11:00", status: "pending", statusText: "승인 대기", }, { id: 3, customer: "이영희", date: "2024-01-20", time: "14:00", status: "confirmed", statusText: "예약 확정", }, { id: 4, customer: "박민수", date: "2024-01-19", time: "15:00", status: "cancelled", statusText: "예약 취소", }, { id: 5, customer: "정수진", date: "2024-01-19", time: "16:00", status: "completed", statusText: "서비스 완료", }, ]; return ( <Table> <TableHeader> <TableRow> <TableHead>예약 번호</TableHead> <TableHead>고객명</TableHead> <TableHead>예약일시</TableHead> <TableHead>상태</TableHead> </TableRow> </TableHeader> <TableBody> {reservations.map((reservation) => ( <TableRow key={reservation.id}> <TableCell>#{reservation.id}</TableCell> <TableCell>{reservation.customer}</TableCell> <TableCell> {reservation.date} {reservation.time} </TableCell> <TableCell> <Badge variant={reservation.status}> {reservation.status === "available" && ( <Calendar size={14} className="mr-xs" /> )} {reservation.status === "pending" && ( <Clock size={14} className="mr-xs" /> )} {reservation.status === "confirmed" && ( <Check size={14} className="mr-xs" /> )} {reservation.status === "cancelled" && ( <X size={14} className="mr-xs" /> )} {reservation.status === "completed" && ( <CheckCircle size={14} className="mr-xs" /> )} {reservation.statusText} </Badge> </TableCell> </TableRow> ))} </TableBody> </Table> ); }

예제 2: 예약 캘린더의 날짜 뱃지 ⭐

import "@vortex/ui-cals/theme"; import { Badge } from "@vortex/ui-cals"; export default function ReservationCalendar() { const dates = [ { date: 15, status: "available", count: 5 }, { date: 16, status: "pending", count: 2 }, { date: 17, status: "confirmed", count: 8 }, { date: 18, status: "cancelled", count: 1 }, { date: 19, status: "completed", count: 10 }, { date: 20, status: "available", count: 3 }, ]; return ( <div className="grid grid-cols-7 gap-md"> {dates.map((day) => ( <div key={day.date} className="border rounded-lg p-md hover:shadow-md transition-shadow" > <div className="text-center mb-sm"> <span className="text-2xl font-bold">{day.date}</span> </div> <Badge variant={day.status} size="sm" className="w-full justify-center" > {day.status === "available" && `${day.count}석`} {day.status === "pending" && `대기 ${day.count}`} {day.status === "confirmed" && `확정 ${day.count}`} {day.status === "cancelled" && `취소 ${day.count}`} {day.status === "completed" && `완료 ${day.count}`} </Badge> </div> ))} </div> ); }

예제 3: 예약 상태별 필터링 ⭐

import "@vortex/ui-cals/theme"; import { Badge } from "@vortex/ui-cals"; import { useState } from "react"; export default function ReservationFilter() { const [activeFilter, setActiveFilter] = useState("all"); const filters = [ { id: "all", label: "전체", count: 48 }, { id: "available", label: "예약 가능", count: 12, variant: "available" }, { id: "pending", label: "승인 대기", count: 5, variant: "pending" }, { id: "confirmed", label: "예약 확정", count: 18, variant: "confirmed" }, { id: "cancelled", label: "예약 취소", count: 3, variant: "cancelled" }, { id: "completed", label: "서비스 완료", count: 10, variant: "completed" }, ]; return ( <div className="space-y-lg"> <div className="flex gap-sm flex-wrap"> {filters.map((filter) => ( <button key={filter.id} onClick={() => setActiveFilter(filter.id)} className={` px-md py-sm rounded-lg border-2 transition-all ${ activeFilter === filter.id ? "border-primary bg-primary/10" : "border-border hover:border-primary/50" } `} > <div className="flex items-center gap-sm"> <span className="font-medium">{filter.label}</span> <Badge variant={filter.variant || "default"} size="sm"> {filter.count} </Badge> </div> </button> ))} </div> <div className="text-sm text-muted-foreground"> {activeFilter === "all" && "전체 예약을 표시합니다"} {activeFilter === "available" && "예약 가능한 시간대만 표시합니다"} {activeFilter === "pending" && "승인 대기 중인 예약만 표시합니다"} {activeFilter === "confirmed" && "확정된 예약만 표시합니다"} {activeFilter === "cancelled" && "취소된 예약만 표시합니다"} {activeFilter === "completed" && "완료된 예약만 표시합니다"} </div> </div> ); }

예제 4: 알림 개수 뱃지

import "@vortex/ui-cals/theme"; import { Badge } from "@vortex/ui-cals"; import { Bell, Calendar, Clock, Check } from "lucide-react"; export default function NotificationBadges() { return ( <div className="flex gap-lg"> {/* 전체 알림 */} <Button variant="ghost" className="relative"> <Bell size={20} /> <Badge variant="danger" size="sm" className="absolute -top-1 -right-1"> 8 </Badge> </Button> {/* 신규 예약 알림 */} <Button variant="ghost" className="relative"> <Calendar size={20} /> <Badge variant="available" size="sm" className="absolute -top-1 -right-1" > 3 </Badge> </Button> {/* 승인 대기 알림 */} <Button variant="ghost" className="relative"> <Clock size={20} /> <Badge variant="pending" size="sm" className="absolute -top-1 -right-1"> 5 </Badge> </Button> {/* 확정 완료 알림 */} <Button variant="ghost" className="relative"> <Check size={20} /> <Badge variant="confirmed" size="sm" className="absolute -top-1 -right-1" > 12 </Badge> </Button> </div> ); }

예제 5: 예약 상세 정보 카드

import "@vortex/ui-cals/theme"; import { Badge } from "@vortex/ui-cals"; import { Calendar, Clock, User, MapPin, Phone } from "lucide-react"; export default function ReservationDetailCard() { return ( <Card> <CardHeader> <div className="flex items-center justify-between"> <h3>예약 상세 정보</h3> <Badge variant="confirmed" size="lg"> <Check size={16} className="mr-xs" /> 예약 확정 </Badge> </div> </CardHeader> <CardContent className="space-y-md"> <div className="flex items-center gap-sm"> <Calendar size={16} className="text-muted-foreground" /> <span>2024년 1월 20일 (토)</span> <Badge variant="available" size="sm"> 주말 </Badge> </div> <div className="flex items-center gap-sm"> <Clock size={16} className="text-muted-foreground" /> <span>14:00 - 16:00</span> <Badge variant="pending" size="sm"> 2시간 </Badge> </div> <div className="flex items-center gap-sm"> <User size={16} className="text-muted-foreground" /> <span>홍길동 (성인 2명, 아동 1명)</span> </div> <div className="flex items-center gap-sm"> <MapPin size={16} className="text-muted-foreground" /> <span>VIP룸 A</span> <Badge variant="accent" size="sm"> 프리미엄 </Badge> </div> <div className="flex items-center gap-sm"> <Phone size={16} className="text-muted-foreground" /> <span>010-1234-5678</span> </div> </CardContent> <CardFooter> <div className="w-full p-md bg-muted rounded-md"> <div className="flex items-center justify-between"> <span className="font-medium">예약 금액</span> <Badge variant="completed" size="lg"> 결제 완료 ₩150,000 </Badge> </div> </div> </CardFooter> </Card> ); }

관련 컴포넌트

Last updated on