/** * StatusBadge — 정상/경계/유의 pill 뱃지 (Phase B) * Stitch 샘플의 상태 표시 스타일: completed(초록), incomplete(회색), warning(주황/빨강) */ import styled from 'styled-components'; import MatIcon from './MatIcon'; export type StatusBadgeType = 'normal' | 'borderline' | 'warning' | 'incomplete' | 'info'; export type StatusBadgeSize = 'sm' | 'md' | 'lg'; interface StatusBadgeProps { /** 상태 타입 */ type: StatusBadgeType; /** 표시 텍스트 (기본값은 type에서 유추) */ children?: React.ReactNode; /** 크기 (기본: md) */ size?: StatusBadgeSize; /** 아이콘 표시 여부 (기본: true) */ showIcon?: boolean; /** 추가 클래스명 */ className?: string; } const TYPE_STYLES = { normal: { bg: 'var(--md3-primary-container)', color: 'var(--md3-on-primary-container)', border: '1px solid var(--md3-primary)', icon: 'check_circle', }, borderline: { bg: '#fff3cd', color: '#856404', border: '1px solid #ffc107', icon: 'warning', }, warning: { bg: '#f8d7da', color: '#721c24', border: '1px solid #f5c6cb', icon: 'error', }, incomplete: { bg: 'var(--md3-surface-variant)', color: 'var(--md3-on-surface-variant)', border: '1px solid var(--md3-outline-variant)', icon: 'schedule', }, info: { bg: 'var(--md3-secondary-container)', color: 'var(--md3-on-secondary-container)', border: '1px solid var(--md3-secondary)', icon: 'info', }, }; const SIZE_STYLES = { sm: { px: '8px', py: '2px', fontSize: '10px', fontWeight: 600, gap: '4px', iconSize: 12 }, md: { px: '10px', py: '4px', fontSize: '11px', fontWeight: 600, gap: '5px', iconSize: 13 }, lg: { px: '12px', py: '6px', fontSize: '12px', fontWeight: 600, gap: '6px', iconSize: 14 }, }; const StyledBadge = styled.span<{ $type: StatusBadgeType; $size: StatusBadgeSize; }>` display: inline-flex; align-items: center; justify-content: center; gap: ${(p) => SIZE_STYLES[p.$size].gap}; padding: ${(p) => SIZE_STYLES[p.$size].py} ${(p) => SIZE_STYLES[p.$size].px}; border-radius: 9999px; border: ${(p) => TYPE_STYLES[p.$type].border}; background: ${(p) => TYPE_STYLES[p.$type].bg}; color: ${(p) => TYPE_STYLES[p.$type].color}; font-family: 'Inter', 'Pretendard', system-ui, sans-serif; font-size: ${(p) => SIZE_STYLES[p.$size].fontSize}; font-weight: ${(p) => SIZE_STYLES[p.$size].fontWeight}; letter-spacing: 0.02em; line-height: 1; white-space: nowrap; box-sizing: border-box; `; const DefaultLabels: Record = { normal: '완료', borderline: '경계', warning: '유의', incomplete: '미완료', info: '안내', }; export default function StatusBadge({ type, children, size = 'md', showIcon = true, className, }: StatusBadgeProps) { const label = children ?? DefaultLabels[type]; const icon = TYPE_STYLES[type].icon; return ( {showIcon && } {label} ); }