feat: add all application source code
- apps/api: FastAPI backend with Dockerfile - apps/web: Next.js frontend with Dockerfile - apps/sensor: Signal collection agent - packages: shared packages Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
148
apps/web/src/components/cyber/data-pincer-card.tsx
Normal file
148
apps/web/src/components/cyber/data-pincer-card.tsx
Normal file
@@ -0,0 +1,148 @@
|
||||
'use client'
|
||||
|
||||
/**
|
||||
* DataPincerCard - AWOOOI 數據鉗容器組件
|
||||
* ========================================
|
||||
* Nothing.tech 純白工業風視覺容器
|
||||
*
|
||||
* 視覺特徵:
|
||||
* - awoooi-glass: 白玻璃毛玻璃效果
|
||||
* - 極細灰色邊框 (border-nothing-mist)
|
||||
* - 左側狀態指示細線 (無漸層、不遮蔽數據)
|
||||
*
|
||||
* i18n: 100% 使用 useTranslations,禁止任何寫死字串
|
||||
* 符合 AWOOOI L1 契約 - 視覺憲法
|
||||
*/
|
||||
|
||||
import { type ReactNode } from 'react'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
// ==================== Types ====================
|
||||
|
||||
export type CardStatus = 'healthy' | 'warning' | 'critical' | 'thinking' | 'idle'
|
||||
|
||||
interface DataPincerCardProps {
|
||||
children: ReactNode
|
||||
title?: string
|
||||
status?: CardStatus
|
||||
className?: string
|
||||
/** 是否顯示左側狀態指示線 */
|
||||
showStatusLine?: boolean
|
||||
/** 卡片尺寸 */
|
||||
size?: 'sm' | 'md' | 'lg'
|
||||
}
|
||||
|
||||
// ==================== Config ====================
|
||||
|
||||
const statusLineColors: Record<CardStatus, string> = {
|
||||
healthy: 'bg-status-healthy',
|
||||
warning: 'bg-status-warning',
|
||||
critical: 'bg-status-critical',
|
||||
thinking: 'bg-status-thinking',
|
||||
idle: 'bg-nothing-gray-300',
|
||||
}
|
||||
|
||||
const sizeConfig = {
|
||||
sm: 'p-3',
|
||||
md: 'p-4',
|
||||
lg: 'p-6',
|
||||
}
|
||||
|
||||
// ==================== Component ====================
|
||||
|
||||
export function DataPincerCard({
|
||||
children,
|
||||
title,
|
||||
status = 'idle',
|
||||
className,
|
||||
showStatusLine = true,
|
||||
size = 'md',
|
||||
}: DataPincerCardProps) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
// awoooi-glass 白玻璃效果
|
||||
'relative overflow-hidden rounded-xl',
|
||||
'bg-white/70 backdrop-blur-[16px]',
|
||||
// 極細灰色邊框 (border-nothing-mist)
|
||||
'border border-nothing-gray-200/60',
|
||||
// 輕柔陰影
|
||||
'shadow-[0_2px_12px_rgba(0,0,0,0.04)]',
|
||||
// 尺寸
|
||||
sizeConfig[size],
|
||||
// 過渡動畫
|
||||
'transition-all duration-200',
|
||||
// Hover 效果
|
||||
'hover:shadow-[0_4px_20px_rgba(0,0,0,0.06)]',
|
||||
'hover:border-nothing-gray-300/80',
|
||||
className
|
||||
)}
|
||||
>
|
||||
{/* 左側狀態指示細線 - 無漸層、不遮蔽數據 */}
|
||||
{showStatusLine && (
|
||||
<div
|
||||
className={cn(
|
||||
'absolute left-0 top-0 bottom-0 w-1 rounded-l-xl',
|
||||
statusLineColors[status],
|
||||
// 思考狀態時呼吸動畫
|
||||
status === 'thinking' && 'animate-pulse'
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* 標題 (如有) */}
|
||||
{title && (
|
||||
<div className="mb-4 pb-3 border-b border-nothing-gray-200/40">
|
||||
<h3 className="font-mono text-xs uppercase tracking-wider text-ink-secondary">
|
||||
{title}
|
||||
</h3>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 內容 */}
|
||||
<div className={cn(showStatusLine && 'pl-2')}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// ==================== Variants ====================
|
||||
|
||||
/** 大型數據面板 */
|
||||
export function DataPincerPanel({
|
||||
children,
|
||||
title,
|
||||
status = 'idle',
|
||||
className,
|
||||
}: Omit<DataPincerCardProps, 'size' | 'showStatusLine'>) {
|
||||
return (
|
||||
<DataPincerCard
|
||||
title={title}
|
||||
status={status}
|
||||
size="lg"
|
||||
showStatusLine={true}
|
||||
className={cn('min-h-[200px]', className)}
|
||||
>
|
||||
{children}
|
||||
</DataPincerCard>
|
||||
)
|
||||
}
|
||||
|
||||
/** 緊湊型狀態卡片 */
|
||||
export function DataPincerCompact({
|
||||
children,
|
||||
status = 'idle',
|
||||
className,
|
||||
}: Omit<DataPincerCardProps, 'size' | 'title'>) {
|
||||
return (
|
||||
<DataPincerCard
|
||||
status={status}
|
||||
size="sm"
|
||||
showStatusLine={true}
|
||||
className={className}
|
||||
>
|
||||
{children}
|
||||
</DataPincerCard>
|
||||
)
|
||||
}
|
||||
14
apps/web/src/components/cyber/index.ts
Normal file
14
apps/web/src/components/cyber/index.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* AWOOOI Cyber Components
|
||||
* =======================
|
||||
* Nothing.tech 純白工業風視覺組件庫
|
||||
*
|
||||
* 命名規範: Data Pincer (數據鉗) 系列
|
||||
*/
|
||||
|
||||
export {
|
||||
DataPincerCard,
|
||||
DataPincerPanel,
|
||||
DataPincerCompact,
|
||||
type CardStatus,
|
||||
} from './data-pincer-card'
|
||||
Reference in New Issue
Block a user