style(web): 全站 font-mono → font-body (DM Mono 設計系統套用)
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>
This commit is contained in:
@@ -145,7 +145,7 @@ export function ApprovalCard({
|
||||
{/* Risk Badge */}
|
||||
<div
|
||||
className={cn(
|
||||
'inline-flex items-center gap-2 px-3 py-1 rounded-full border text-xs font-mono tracking-wider mb-3',
|
||||
'inline-flex items-center gap-2 px-3 py-1 rounded-full border text-xs font-body tracking-wider mb-3',
|
||||
riskStyle.bgColor,
|
||||
riskStyle.borderColor,
|
||||
riskStyle.color
|
||||
@@ -174,12 +174,12 @@ export function ApprovalCard({
|
||||
|
||||
{/* Signature Counter */}
|
||||
<div className="text-right shrink-0">
|
||||
<div className="font-mono text-xs text-nothing-gray-500 mb-1">
|
||||
<div className="font-body text-xs text-nothing-gray-500 mb-1">
|
||||
{t('signatures')}
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
'font-mono text-lg',
|
||||
'font-body text-lg',
|
||||
needsMoreSignatures ? 'text-status-warning' : 'text-status-healthy'
|
||||
)}
|
||||
>
|
||||
@@ -193,40 +193,40 @@ export function ApprovalCard({
|
||||
|
||||
{/* Blast Radius Section */}
|
||||
<div className="space-y-3">
|
||||
<h4 className="font-mono text-xs text-nothing-gray-500 tracking-wider">
|
||||
<h4 className="font-body text-xs text-nothing-gray-500 tracking-wider">
|
||||
{tBlast('title')}
|
||||
</h4>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
{/* Affected Pods */}
|
||||
<div className="bg-nothing-gray-900 rounded-card p-3">
|
||||
<div className="font-mono text-xs text-nothing-gray-500 mb-1">
|
||||
<div className="font-body text-xs text-nothing-gray-500 mb-1">
|
||||
{tBlast('affectedPods')}
|
||||
</div>
|
||||
<div className="font-mono text-lg text-nothing-white">
|
||||
<div className="font-body text-lg text-nothing-white">
|
||||
{request.blastRadius?.affectedPods ?? 0}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Estimated Downtime */}
|
||||
<div className="bg-nothing-gray-900 rounded-card p-3">
|
||||
<div className="font-mono text-xs text-nothing-gray-500 mb-1">
|
||||
<div className="font-body text-xs text-nothing-gray-500 mb-1">
|
||||
{tBlast('estimatedDowntime')}
|
||||
</div>
|
||||
<div className="font-mono text-lg text-nothing-white">
|
||||
<div className="font-body text-lg text-nothing-white">
|
||||
{request.blastRadius?.estimatedDowntime ?? '0'}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Related Services */}
|
||||
<div className="bg-nothing-gray-900 rounded-card p-3">
|
||||
<div className="font-mono text-xs text-nothing-gray-500 mb-1">
|
||||
<div className="font-body text-xs text-nothing-gray-500 mb-1">
|
||||
{tBlast('relatedServices')}
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-1 mt-1">
|
||||
{(request.blastRadius?.relatedServices ?? []).map((service) => (
|
||||
<span
|
||||
key={service}
|
||||
className="px-2 py-0.5 bg-nothing-gray-800 rounded text-xs font-mono text-nothing-gray-300"
|
||||
className="px-2 py-0.5 bg-nothing-gray-800 rounded text-xs font-body text-nothing-gray-300"
|
||||
>
|
||||
{service}
|
||||
</span>
|
||||
@@ -236,10 +236,10 @@ export function ApprovalCard({
|
||||
|
||||
{/* Data Impact */}
|
||||
<div className="bg-nothing-gray-900 rounded-card p-3">
|
||||
<div className="font-mono text-xs text-nothing-gray-500 mb-1">
|
||||
<div className="font-body text-xs text-nothing-gray-500 mb-1">
|
||||
{tBlast('dataImpact')}
|
||||
</div>
|
||||
<div className={cn('font-mono text-lg', dataImpactStyle.color)}>
|
||||
<div className={cn('font-body text-lg', dataImpactStyle.color)}>
|
||||
{dataImpactLabel}
|
||||
</div>
|
||||
</div>
|
||||
@@ -251,7 +251,7 @@ export function ApprovalCard({
|
||||
|
||||
{/* Dry-Run Checks */}
|
||||
<div className="space-y-3">
|
||||
<h4 className="font-mono text-xs text-nothing-gray-500 tracking-wider">
|
||||
<h4 className="font-body text-xs text-nothing-gray-500 tracking-wider">
|
||||
{tDryRun('validation')}
|
||||
</h4>
|
||||
<div className="space-y-2">
|
||||
@@ -271,12 +271,12 @@ export function ApprovalCard({
|
||||
>
|
||||
{check.passed ? '✓' : '✗'}
|
||||
</div>
|
||||
<span className="font-mono text-sm text-nothing-white">
|
||||
<span className="font-body text-sm text-nothing-white">
|
||||
{check.name}
|
||||
</span>
|
||||
</div>
|
||||
{check.message && (
|
||||
<span className="font-mono text-xs text-nothing-gray-500">
|
||||
<span className="font-body text-xs text-nothing-gray-500">
|
||||
{check.message}
|
||||
</span>
|
||||
)}
|
||||
@@ -291,7 +291,7 @@ export function ApprovalCard({
|
||||
{/* Footer: Meta + Actions */}
|
||||
<div className="flex items-center justify-between">
|
||||
{/* Meta */}
|
||||
<div className="font-mono text-xs text-nothing-gray-600">
|
||||
<div className="font-body text-xs text-nothing-gray-600">
|
||||
<span>{t('requestedBy')} </span>
|
||||
<span className="text-nothing-gray-400">{request.requestedBy}</span>
|
||||
<span className="mx-2">|</span>
|
||||
@@ -304,7 +304,7 @@ export function ApprovalCard({
|
||||
<button
|
||||
onClick={handleReject}
|
||||
className={cn(
|
||||
'px-5 py-2 rounded-button font-mono text-sm transition-all',
|
||||
'px-5 py-2 rounded-button font-body text-sm transition-all',
|
||||
'border border-nothing-gray-700 text-nothing-gray-400',
|
||||
'hover:border-nothing-red hover:text-nothing-red hover:bg-nothing-red/10'
|
||||
)}
|
||||
@@ -318,7 +318,7 @@ export function ApprovalCard({
|
||||
onClick={handleApprove}
|
||||
disabled={!allChecksPassed}
|
||||
className={cn(
|
||||
'px-5 py-2 rounded-button font-mono text-sm transition-all animate-pulse',
|
||||
'px-5 py-2 rounded-button font-body text-sm transition-all animate-pulse',
|
||||
'bg-nothing-red text-nothing-white border-2 border-nothing-red',
|
||||
'hover:bg-nothing-red/80'
|
||||
)}
|
||||
@@ -330,7 +330,7 @@ export function ApprovalCard({
|
||||
onClick={handleApprove}
|
||||
disabled={!allChecksPassed}
|
||||
className={cn(
|
||||
'px-5 py-2 rounded-button font-mono text-sm transition-all',
|
||||
'px-5 py-2 rounded-button font-body text-sm transition-all',
|
||||
allChecksPassed
|
||||
? isDestructive
|
||||
? 'bg-nothing-red/20 text-nothing-red border border-nothing-red/50 hover:bg-nothing-red/30'
|
||||
|
||||
@@ -190,7 +190,7 @@ export function DataPincer({
|
||||
{showLabel && (
|
||||
<div
|
||||
className={cn(
|
||||
'mt-6 font-mono tracking-wider uppercase',
|
||||
'mt-6 font-body tracking-wider uppercase',
|
||||
sizeClass.label,
|
||||
hasError ? 'text-status-critical' : 'text-nothing-gray-400',
|
||||
config.animate && 'animate-pulse'
|
||||
|
||||
@@ -266,7 +266,7 @@ export function ThinkingTerminalOptimized({
|
||||
</div>
|
||||
<h2 className="font-display text-display-sm">{t('title')}</h2>
|
||||
</div>
|
||||
<span className="font-mono text-xs text-nothing-gray-500">
|
||||
<span className="font-body text-xs text-nothing-gray-500">
|
||||
v1.0 | DOM Bypass | {lineCount} lines
|
||||
</span>
|
||||
</div>
|
||||
@@ -277,7 +277,7 @@ export function ThinkingTerminalOptimized({
|
||||
onClick={startStream}
|
||||
disabled={isStreaming}
|
||||
className={cn(
|
||||
'flex-1 py-3 px-4 rounded-button font-mono text-sm transition-all border',
|
||||
'flex-1 py-3 px-4 rounded-button font-body text-sm transition-all border',
|
||||
isStreaming
|
||||
? 'bg-nothing-gray-800 text-nothing-gray-500 border-nothing-gray-700 cursor-not-allowed'
|
||||
: 'bg-nothing-white text-nothing-black border-transparent hover:bg-nothing-gray-200'
|
||||
@@ -289,7 +289,7 @@ export function ThinkingTerminalOptimized({
|
||||
{isStreaming && (
|
||||
<button
|
||||
onClick={stopStream}
|
||||
className="py-3 px-4 rounded-button font-mono text-sm bg-status-critical/20 text-status-critical border border-status-critical/50 hover:bg-status-critical/30"
|
||||
className="py-3 px-4 rounded-button font-body text-sm bg-status-critical/20 text-status-critical border border-status-critical/50 hover:bg-status-critical/30"
|
||||
>
|
||||
{t('stop')}
|
||||
</button>
|
||||
@@ -299,7 +299,7 @@ export function ThinkingTerminalOptimized({
|
||||
onClick={clearTerminal}
|
||||
disabled={isStreaming || lineCount === 0}
|
||||
className={cn(
|
||||
'py-3 px-4 rounded-button font-mono text-sm border',
|
||||
'py-3 px-4 rounded-button font-body text-sm border',
|
||||
isStreaming || lineCount === 0
|
||||
? 'bg-nothing-gray-800 text-nothing-gray-500 border-nothing-gray-700 cursor-not-allowed'
|
||||
: 'bg-nothing-gray-800 text-nothing-gray-300 border-nothing-gray-700 hover:bg-nothing-gray-700'
|
||||
@@ -312,7 +312,7 @@ export function ThinkingTerminalOptimized({
|
||||
{/* Terminal Output - DOM Bypass Container */}
|
||||
<div
|
||||
ref={terminalRef}
|
||||
className="bg-nothing-gray-900 rounded-card p-4 overflow-y-auto font-mono text-sm"
|
||||
className="bg-nothing-gray-900 rounded-card p-4 overflow-y-auto font-body text-sm"
|
||||
style={{ maxHeight, minHeight: '150px' }}
|
||||
>
|
||||
{/* Content appended directly via DOM manipulation */}
|
||||
@@ -340,10 +340,10 @@ export function ThinkingTerminalOptimized({
|
||||
|
||||
{/* Footer */}
|
||||
<div className="flex items-center justify-between pt-2 border-t border-nothing-gray-800">
|
||||
<p className="font-mono text-xs text-nothing-gray-600">
|
||||
<p className="font-body text-xs text-nothing-gray-600">
|
||||
{t('stream')}
|
||||
</p>
|
||||
<p className="font-mono text-xs text-nothing-gray-600">
|
||||
<p className="font-body text-xs text-nothing-gray-600">
|
||||
{status === 'streaming' ? (
|
||||
<span className="text-status-thinking animate-pulse">● LIVE</span>
|
||||
) : (
|
||||
|
||||
@@ -59,7 +59,7 @@ function DependencyPathVisualizer({
|
||||
<div className="text-xs text-nothing-gray-500 mb-2">
|
||||
{direction === 'upstream' ? t('blastRadius') : t('rootCauseChain')}
|
||||
</div>
|
||||
<div className="font-mono text-sm space-y-1">
|
||||
<div className="font-body text-sm space-y-1">
|
||||
{paths.map((path, i) => (
|
||||
<div key={i} className="flex items-center gap-2">
|
||||
<span className="text-nothing-gray-600">{i === 0 ? '>' : '|'}</span>
|
||||
@@ -97,7 +97,7 @@ function ServiceChainVisualizer({
|
||||
</div>
|
||||
|
||||
{/* ASCII Art 風格圖形 */}
|
||||
<div className="font-mono text-xs leading-relaxed">
|
||||
<div className="font-body text-xs leading-relaxed">
|
||||
{isBlastRadius ? (
|
||||
// Blast Radius: 向上展示誰會受影響
|
||||
<>
|
||||
@@ -200,7 +200,7 @@ function FinOpsVisualizer({ data }: { data: NonNullable<ThinkingStep['finopsData
|
||||
</span>
|
||||
<span
|
||||
className={cn(
|
||||
'font-mono',
|
||||
'font-body',
|
||||
action.risk === 'low' && 'text-status-healthy',
|
||||
action.risk === 'medium' && 'text-status-warning',
|
||||
action.risk === 'high' && 'text-status-critical'
|
||||
@@ -338,7 +338,7 @@ export function ThinkingTerminal({
|
||||
</div>
|
||||
<h2 className="font-display text-display-sm">{t('title')}</h2>
|
||||
</div>
|
||||
<span className="font-mono text-xs text-nothing-gray-500">
|
||||
<span className="font-body text-xs text-nothing-gray-500">
|
||||
v0.1.0 | SSE
|
||||
</span>
|
||||
</div>
|
||||
@@ -348,7 +348,7 @@ export function ThinkingTerminal({
|
||||
onClick={() => startThinkingStream()}
|
||||
disabled={isStreaming}
|
||||
className={cn(
|
||||
'w-full py-3 px-4 rounded-button font-mono text-sm transition-all border',
|
||||
'w-full py-3 px-4 rounded-button font-body text-sm transition-all border',
|
||||
isStreaming
|
||||
? 'bg-nothing-gray-800 text-nothing-gray-500 border-nothing-gray-700 cursor-not-allowed'
|
||||
: 'bg-nothing-white text-nothing-black border-transparent hover:bg-nothing-gray-200'
|
||||
@@ -359,7 +359,7 @@ export function ThinkingTerminal({
|
||||
|
||||
{/* Terminal Output */}
|
||||
<div
|
||||
className="bg-nothing-gray-900 rounded-card p-4 overflow-y-auto font-mono text-sm"
|
||||
className="bg-nothing-gray-900 rounded-card p-4 overflow-y-auto font-body text-sm"
|
||||
style={{ maxHeight, minHeight: '150px' }}
|
||||
>
|
||||
{thinkingStream.length === 0 && !isStreaming && !error && (
|
||||
@@ -383,10 +383,10 @@ export function ThinkingTerminal({
|
||||
|
||||
{/* Footer */}
|
||||
<div className="flex items-center justify-between pt-2 border-t border-nothing-gray-800">
|
||||
<p className="font-mono text-xs text-nothing-gray-600">
|
||||
<p className="font-body text-xs text-nothing-gray-600">
|
||||
{t('stream')}
|
||||
</p>
|
||||
<p className="font-mono text-xs text-nothing-gray-600">
|
||||
<p className="font-body text-xs text-nothing-gray-600">
|
||||
{t('events', { count: thinkingStream.length })}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user