102 lines
3.6 KiB
TypeScript
102 lines
3.6 KiB
TypeScript
/**
|
||
* Tag 组件
|
||
*
|
||
* 统一的标签组件,遵循三层架构设计,采用苹果美学风格
|
||
* 用于显示分类、类型等标签信息
|
||
* 支持多种颜色(blue、green、orange、purple等)和尺寸(sm、md、lg)
|
||
* 支持点击事件,可用于筛选等功能
|
||
*
|
||
* 苹果美学特点:
|
||
* - 圆角更大(rounded-full)
|
||
* - 背景色更柔和(低饱和度)
|
||
* - 选中状态使用更明显的视觉反馈
|
||
* - 过渡动画更流畅
|
||
*
|
||
* @created 2025-11-22
|
||
* @updated 2025-01-22 - 重新设计为苹果美学风格
|
||
* @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) {
|
||
const styles = useThemeStyles()
|
||
|
||
// 苹果美学风格的颜色配置(更柔和的背景,更清晰的文字)
|
||
const colorClasses = {
|
||
blue: selected
|
||
? 'bg-blue-500 dark:bg-blue-600 text-white border-blue-500 dark:border-blue-600'
|
||
: 'bg-blue-50 dark:bg-blue-950/30 text-blue-700 dark:text-blue-300 border-blue-200 dark:border-blue-800/50',
|
||
green: selected
|
||
? 'bg-emerald-500 dark:bg-emerald-600 text-white border-emerald-500 dark:border-emerald-600'
|
||
: 'bg-emerald-50 dark:bg-emerald-950/30 text-emerald-700 dark:text-emerald-300 border-emerald-200 dark:border-emerald-800/50',
|
||
orange: selected
|
||
? 'bg-orange-500 dark:bg-orange-600 text-white border-orange-500 dark:border-orange-600'
|
||
: 'bg-orange-50 dark:bg-orange-950/30 text-orange-700 dark:text-orange-300 border-orange-200 dark:border-orange-800/50',
|
||
purple: selected
|
||
? 'bg-purple-500 dark:bg-purple-600 text-white border-purple-500 dark:border-purple-600'
|
||
: 'bg-purple-50 dark:bg-purple-950/30 text-purple-700 dark:text-purple-300 border-purple-200 dark:border-purple-800/50',
|
||
indigo: selected
|
||
? 'bg-indigo-500 dark:bg-indigo-600 text-white border-indigo-500 dark:border-indigo-600'
|
||
: 'bg-indigo-50 dark:bg-indigo-950/30 text-indigo-700 dark:text-indigo-300 border-indigo-200 dark:border-indigo-800/50',
|
||
pink: selected
|
||
? 'bg-pink-500 dark:bg-pink-600 text-white border-pink-500 dark:border-pink-600'
|
||
: 'bg-pink-50 dark:bg-pink-950/30 text-pink-700 dark:text-pink-300 border-pink-200 dark:border-pink-800/50',
|
||
cyan: selected
|
||
? 'bg-cyan-500 dark:bg-cyan-600 text-white border-cyan-500 dark:border-cyan-600'
|
||
: 'bg-cyan-50 dark:bg-cyan-950/30 text-cyan-700 dark:text-cyan-300 border-cyan-200 dark:border-cyan-800/50',
|
||
}
|
||
|
||
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-full border',
|
||
'transition-all duration-200 ease-out',
|
||
'backdrop-blur-sm',
|
||
selected && 'shadow-md scale-105',
|
||
!selected && onClick && 'hover:scale-105 hover:shadow-sm',
|
||
onClick && 'cursor-pointer active:scale-95'
|
||
)
|
||
|
||
return (
|
||
<span
|
||
className={cn(
|
||
baseClasses,
|
||
colorClasses[color],
|
||
sizeClasses[size],
|
||
className
|
||
)}
|
||
onClick={onClick}
|
||
>
|
||
{children}
|
||
</span>
|
||
)
|
||
}
|
||
|