WuYongJie d1c6efc79d
Some checks failed
CI Check / check (push) Has been cancelled
feat: NAS 部署与 Harbor 推送流程
2025-12-03 14:39:06 +08:00

102 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 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>
)
}