91 lines
3.5 KiB
TypeScript
91 lines
3.5 KiB
TypeScript
/**
|
||
* Tag 组件
|
||
*
|
||
* 统一的标签组件,适合后台筛选与分类展示
|
||
* 用于显示分类、类型等标签信息
|
||
* 支持少量语义色和尺寸(xs、sm、md、lg)
|
||
* 支持点击事件,可用于筛选等功能
|
||
*
|
||
* @created 2025-11-22
|
||
* @updated 2026-05-25 - 收敛为后台工作台风格
|
||
* @component
|
||
*/
|
||
|
||
'use client'
|
||
|
||
import { ReactNode } from 'react'
|
||
import { useThemeStyles, cn } from '@/lib/ui-styles'
|
||
|
||
interface TagProps {
|
||
children: ReactNode
|
||
color?: 'blue' | 'green' | 'orange' | 'purple' | 'indigo' | 'pink' | 'cyan'
|
||
size?: 'xs' | 'sm' | 'md' | 'lg'
|
||
className?: string
|
||
onClick?: () => void
|
||
selected?: boolean
|
||
}
|
||
|
||
export default function Tag({
|
||
children,
|
||
color = 'blue',
|
||
size = 'md',
|
||
className = '',
|
||
onClick,
|
||
selected = false,
|
||
}: TagProps) {
|
||
useThemeStyles()
|
||
|
||
const colorClasses: Record<NonNullable<TagProps['color']>, string> = {
|
||
blue: selected
|
||
? 'bg-slate-900 dark:bg-slate-100 text-white dark:text-slate-950 border-slate-900 dark:border-slate-100'
|
||
: 'bg-white dark:bg-slate-900 text-slate-700 dark:text-slate-200 border-slate-300 dark:border-slate-700 hover:bg-slate-50 dark:hover:bg-slate-800',
|
||
green: selected
|
||
? 'bg-emerald-700 dark:bg-emerald-500 text-white border-emerald-700 dark:border-emerald-500'
|
||
: 'bg-emerald-50 dark:bg-emerald-950/30 text-emerald-800 dark:text-emerald-200 border-emerald-200 dark:border-emerald-800 hover:bg-emerald-100 dark:hover:bg-emerald-950/50',
|
||
orange: selected
|
||
? 'bg-amber-700 dark:bg-amber-500 text-white dark:text-slate-950 border-amber-700 dark:border-amber-500'
|
||
: 'bg-amber-50 dark:bg-amber-950/30 text-amber-800 dark:text-amber-200 border-amber-200 dark:border-amber-800 hover:bg-amber-100 dark:hover:bg-amber-950/50',
|
||
purple: selected
|
||
? 'bg-slate-700 dark:bg-slate-200 text-white dark:text-slate-950 border-slate-700 dark:border-slate-200'
|
||
: 'bg-slate-50 dark:bg-slate-900 text-slate-700 dark:text-slate-200 border-slate-300 dark:border-slate-700 hover:bg-slate-100 dark:hover:bg-slate-800',
|
||
indigo: selected
|
||
? 'bg-slate-700 dark:bg-slate-200 text-white dark:text-slate-950 border-slate-700 dark:border-slate-200'
|
||
: 'bg-slate-50 dark:bg-slate-900 text-slate-700 dark:text-slate-200 border-slate-300 dark:border-slate-700 hover:bg-slate-100 dark:hover:bg-slate-800',
|
||
pink: selected
|
||
? 'bg-slate-700 dark:bg-slate-200 text-white dark:text-slate-950 border-slate-700 dark:border-slate-200'
|
||
: 'bg-slate-50 dark:bg-slate-900 text-slate-700 dark:text-slate-200 border-slate-300 dark:border-slate-700 hover:bg-slate-100 dark:hover:bg-slate-800',
|
||
cyan: selected
|
||
? 'bg-slate-700 dark:bg-slate-200 text-white dark:text-slate-950 border-slate-700 dark:border-slate-200'
|
||
: 'bg-slate-50 dark:bg-slate-900 text-slate-700 dark:text-slate-200 border-slate-300 dark:border-slate-700 hover:bg-slate-100 dark:hover:bg-slate-800',
|
||
}
|
||
|
||
const sizeClasses = {
|
||
xs: 'px-2.5 py-0.5 text-[11px] font-medium',
|
||
sm: 'px-3 py-1 text-xs font-medium',
|
||
md: 'px-4 py-1.5 text-sm font-medium',
|
||
lg: 'px-5 py-2 text-base font-medium',
|
||
} as const
|
||
|
||
const baseClasses = cn(
|
||
'inline-flex items-center justify-center',
|
||
'rounded-md border',
|
||
'transition-colors duration-200 ease-out',
|
||
onClick && 'cursor-pointer'
|
||
)
|
||
|
||
return (
|
||
<span
|
||
className={cn(
|
||
baseClasses,
|
||
colorClasses[color],
|
||
sizeClasses[size],
|
||
className
|
||
)}
|
||
onClick={onClick}
|
||
>
|
||
{children}
|
||
</span>
|
||
)
|
||
}
|
||
|