45 個 component + 6 個 page 統一從舊 font-mono 遷移到 font-body (DM Mono),確保設計系統一致性。 font-body = DM Mono (等寬),視覺效果相同但走新設計 token。 保留: font-heading (Syne)、font-dot-matrix (VT323/DSEG7) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
93 lines
2.1 KiB
TypeScript
93 lines
2.1 KiB
TypeScript
'use client'
|
|
|
|
/**
|
|
* StatusOrb - Agent 狀態指示燈
|
|
* ============================
|
|
* i18n: 100% 使用 useTranslations
|
|
* 修復: 2026-03-29 Wave 3 i18n 清零
|
|
*/
|
|
|
|
import { useTranslations } from 'next-intl'
|
|
import { cn } from '@/lib/utils'
|
|
|
|
type AgentStatus = 'idle' | 'thinking' | 'executing' | 'waiting_approval'
|
|
|
|
interface StatusOrbProps {
|
|
status: AgentStatus
|
|
size?: 'sm' | 'md' | 'lg'
|
|
className?: string
|
|
}
|
|
|
|
// i18n key 對應表
|
|
const statusI18nKey: Record<AgentStatus, string> = {
|
|
idle: 'idle',
|
|
thinking: 'thinking',
|
|
executing: 'executing',
|
|
waiting_approval: 'waitingApproval',
|
|
}
|
|
|
|
const statusConfig: Record<AgentStatus, { color: string; animate: boolean }> = {
|
|
idle: {
|
|
color: 'bg-nothing-gray-600',
|
|
animate: false,
|
|
},
|
|
thinking: {
|
|
color: 'bg-status-warning',
|
|
animate: true,
|
|
},
|
|
executing: {
|
|
color: 'bg-status-healthy',
|
|
animate: true,
|
|
},
|
|
waiting_approval: {
|
|
color: 'bg-status-critical',
|
|
animate: true,
|
|
},
|
|
}
|
|
|
|
const sizeConfig = {
|
|
sm: 'w-8 h-8',
|
|
md: 'w-16 h-16',
|
|
lg: 'w-24 h-24',
|
|
}
|
|
|
|
export function StatusOrb({ status, size = 'md', className }: StatusOrbProps) {
|
|
const t = useTranslations('status')
|
|
const config = statusConfig[status]
|
|
const sizeClass = sizeConfig[size]
|
|
const label = t(statusI18nKey[status])
|
|
|
|
return (
|
|
<div className={cn('relative', className)}>
|
|
{/* Outer glow */}
|
|
<div
|
|
className={cn(
|
|
'absolute inset-0 rounded-full blur-xl opacity-30',
|
|
config.color,
|
|
config.animate && 'animate-pulse-slow'
|
|
)}
|
|
/>
|
|
|
|
{/* Main orb */}
|
|
<div
|
|
className={cn(
|
|
'relative rounded-full border border-nothing-gray-700',
|
|
sizeClass,
|
|
config.color,
|
|
config.animate && 'animate-breathe'
|
|
)}
|
|
>
|
|
{/* Inner highlight */}
|
|
<div className="absolute inset-2 rounded-full bg-gradient-to-br from-white/20 to-transparent" />
|
|
</div>
|
|
|
|
{/* Label */}
|
|
<div className="absolute -bottom-6 left-1/2 -translate-x-1/2 whitespace-nowrap">
|
|
<span className="font-body text-xs text-nothing-gray-500">
|
|
{label}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|