diff --git a/apps/web/src/app/[locale]/action-logs/page.tsx b/apps/web/src/app/[locale]/action-logs/page.tsx index 09f247308..ea7fca0b4 100644 --- a/apps/web/src/app/[locale]/action-logs/page.tsx +++ b/apps/web/src/app/[locale]/action-logs/page.tsx @@ -139,12 +139,12 @@ function StatCard({ />
-

+

{label}

{value}

{subValue && ( -

+

{subValue}

)} @@ -349,7 +349,7 @@ export default function ActionLogPage({ {/* Toolbar */}
-
+
{totalCount > 0 ? `${totalCount} ${t('actionLog.columns.operation').toLowerCase()}s` : ''} @@ -361,7 +361,7 @@ export default function ActionLogPage({ }} disabled={isLoading} className={cn( - 'flex items-center gap-1 px-3 py-1.5 rounded-lg text-xs font-mono', + 'flex items-center gap-1 px-3 py-1.5 rounded-lg text-xs font-body', 'bg-nothing-gray-100 text-nothing-gray-600', 'hover:bg-nothing-gray-200 transition-colors', 'disabled:opacity-50 disabled:cursor-not-allowed' @@ -378,7 +378,7 @@ export default function ActionLogPage({ {error && (
- + {t('actionLog.fetchError')}: {error}
@@ -388,7 +388,7 @@ export default function ActionLogPage({ {isLoading && logs.length === 0 && (
- + {t('actionLog.loading')}
@@ -398,7 +398,7 @@ export default function ActionLogPage({ {!isLoading && logs.length === 0 && !error && (
-

+

{t('actionLog.noLogs')}

@@ -410,25 +410,25 @@ export default function ActionLogPage({ - - - - - - - @@ -439,13 +439,13 @@ export default function ActionLogPage({ key={log.id} className="border-b border-nothing-gray-100 hover:bg-nothing-gray-50/50 transition-colors" > - - - - - @@ -497,7 +497,7 @@ export default function ActionLogPage({ {/* Pagination */} {totalPages > 1 && (
- + {t('actionLog.pagination.page', { current: page, total: totalPages, @@ -508,7 +508,7 @@ export default function ActionLogPage({ onClick={handlePrevPage} disabled={page <= 1 || isLoading} className={cn( - 'flex items-center gap-1 px-3 py-1.5 rounded-lg text-xs font-mono', + 'flex items-center gap-1 px-3 py-1.5 rounded-lg text-xs font-body', 'border border-nothing-gray-200', 'hover:bg-nothing-gray-50 transition-colors', 'disabled:opacity-50 disabled:cursor-not-allowed' @@ -521,7 +521,7 @@ export default function ActionLogPage({ onClick={handleNextPage} disabled={page >= totalPages || isLoading} className={cn( - 'flex items-center gap-1 px-3 py-1.5 rounded-lg text-xs font-mono', + 'flex items-center gap-1 px-3 py-1.5 rounded-lg text-xs font-body', 'border border-nothing-gray-200', 'hover:bg-nothing-gray-50 transition-colors', 'disabled:opacity-50 disabled:cursor-not-allowed' @@ -541,7 +541,7 @@ export default function ActionLogPage({

{t('footer.copyright')}

-

+

{t('footer.poweredBy')} v1.0.0

diff --git a/apps/web/src/app/[locale]/alerts/page.tsx b/apps/web/src/app/[locale]/alerts/page.tsx index 7909dcb03..4b6a14fbe 100644 --- a/apps/web/src/app/[locale]/alerts/page.tsx +++ b/apps/web/src/app/[locale]/alerts/page.tsx @@ -33,7 +33,7 @@ function SeverityBadge({ severity }: { severity: string }) { const style = SEVERITY_STYLE[severity] ?? SEVERITY_STYLE['P3'] return ( {severity === 'P0' && } @@ -57,12 +57,12 @@ function StatPill({ label, value, highlight }: { label: string; value: number; h : 'bg-white border-nothing-gray-200' )}> 0 ? 'text-status-critical' : 'text-nothing-black' )}> {value} - + {label} @@ -100,7 +100,7 @@ export default function AlertsPage({ params }: { params: { locale: string } }) { {t('nav.alerts')} -

+

{t('incident.activeIncidents')} · {t('alerts.autoRefresh', { seconds: 15 })}

@@ -109,7 +109,7 @@ export default function AlertsPage({ params }: { params: { locale: string } }) { disabled={isLoading} className={cn( 'flex items-center gap-1.5 px-3 py-1.5 rounded-lg', - 'text-xs font-mono bg-nothing-gray-100 text-nothing-gray-600', + 'text-xs font-body bg-nothing-gray-100 text-nothing-gray-600', 'hover:bg-nothing-gray-200 transition-colors', 'disabled:opacity-50 disabled:cursor-not-allowed' )} @@ -131,7 +131,7 @@ export default function AlertsPage({ params }: { params: { locale: string } }) { {error && (
- {error} + {error}
)} @@ -139,7 +139,7 @@ export default function AlertsPage({ params }: { params: { locale: string } }) { {isLoading && sorted.length === 0 && (
- {t('common.loading')} + {t('common.loading')}
)} @@ -147,8 +147,8 @@ export default function AlertsPage({ params }: { params: { locale: string } }) { {!isLoading && sorted.length === 0 && !error && (
-

{t('incident.noActiveIncidents')}

-

{t('incident.systemStable')}

+

{t('incident.noActiveIncidents')}

+

{t('incident.systemStable')}

)} @@ -163,7 +163,7 @@ export default function AlertsPage({ params }: { params: { locale: string } }) { {/* Section header */}
- + {tAlerts('incidentCount', { count: group.length })}
diff --git a/apps/web/src/app/[locale]/auto-repair/page.tsx b/apps/web/src/app/[locale]/auto-repair/page.tsx index 80c211416..4c22c2460 100644 --- a/apps/web/src/app/[locale]/auto-repair/page.tsx +++ b/apps/web/src/app/[locale]/auto-repair/page.tsx @@ -86,11 +86,11 @@ function StatCard({ 'rounded-lg border p-4', highlight ? 'bg-claw-blue/5 border-claw-blue/20' : 'bg-white border-nothing-gray-200' )}> -

{label}

-

+

{label}

+

{value}

- {sub &&

{sub}

} + {sub &&

{sub}

}
) } @@ -147,18 +147,18 @@ function IncidentEvalRow({ onClick={() => setExpanded(v => !v)} > {severity} - {incidentId} + {incidentId} {loading && } {!loading && eval_ && ( eval_.can_auto_repair - ? {t('canAutoRepair')} - : {t('notEligibleShort')} + ? {t('canAutoRepair')} + : {t('notEligibleShort')} )} {expanded ? : }
@@ -168,34 +168,34 @@ function IncidentEvalRow({
- Playbook -

{eval_.playbook_name ?? '—'}

+ Playbook +

{eval_.playbook_name ?? '—'}

- {t('riskLevel')} + {t('riskLevel')}

- + {eval_.risk_level}

{eval_.success_rate != null && (
- {t('successRate')} -

{(eval_.success_rate * 100).toFixed(1)}%

+ {t('successRate')} +

{(eval_.success_rate * 100).toFixed(1)}%

)} {eval_.total_executions != null && (
- {t('execCount')} -

{eval_.total_executions}

+ {t('execCount')} +

{eval_.total_executions}

)}
- {t('decisionReason')} -

{eval_.reason}

+ {t('decisionReason')} +

{eval_.reason}

{/* Execute result */} @@ -208,14 +208,14 @@ function IncidentEvalRow({ {result.success ? : } - + {result.success ? t('execSuccess', { ms: result.execution_time_ms }) : t('execFailed', { error: result.error })}
{result.executed_steps.length > 0 && (
    {result.executed_steps.map((step, i) => ( -
  • +
  • {step}
  • @@ -232,7 +232,7 @@ function IncidentEvalRow({ disabled={executing} className={cn( 'flex items-center gap-2 px-4 py-2 rounded-lg', - 'bg-claw-blue text-white font-mono text-sm font-semibold', + 'bg-claw-blue text-white font-body text-sm font-semibold', 'hover:bg-claw-blue/90 transition-colors', 'disabled:opacity-50 disabled:cursor-not-allowed' )} @@ -305,7 +305,7 @@ export default function AutoRepairPage({ params }: { params: { locale: string } {tNav('autoRepair')} -

    +

    {t('subtitle')}

    @@ -314,7 +314,7 @@ export default function AutoRepairPage({ params }: { params: { locale: string } disabled={statsLoading} className={cn( 'flex items-center gap-1.5 px-3 py-1.5 rounded-lg', - 'text-xs font-mono bg-nothing-gray-100 text-nothing-gray-600', + 'text-xs font-body bg-nothing-gray-100 text-nothing-gray-600', 'hover:bg-nothing-gray-200 transition-colors', 'disabled:opacity-50 disabled:cursor-not-allowed' )} @@ -328,7 +328,7 @@ export default function AutoRepairPage({ params }: { params: { locale: string } {statsError && (
    - {statsError} + {statsError}
    )} @@ -369,10 +369,10 @@ export default function AutoRepairPage({ params }: { params: { locale: string } ? : }
    -

    +

    {stats.auto_repair_eligible ? t('ready') : t('notReady')}

    -

    +

    {stats.auto_repair_eligible ? t('readyDesc', { count: stats.high_quality_playbooks }) : t('notReadyDesc')} @@ -383,7 +383,7 @@ export default function AutoRepairPage({ params }: { params: { locale: string } {/* Incident evaluation list */}

    -

    +

    {t('incidentEval')}

    @@ -396,7 +396,7 @@ export default function AutoRepairPage({ params }: { params: { locale: string } {!incidentsLoading && eligibleIncidents.length === 0 && (
    -

    {t('noEligible')}

    +

    {t('noEligible')}

    )} diff --git a/apps/web/src/app/[locale]/demo/page.tsx b/apps/web/src/app/[locale]/demo/page.tsx index fc11bb24a..fb0f123c8 100644 --- a/apps/web/src/app/[locale]/demo/page.tsx +++ b/apps/web/src/app/[locale]/demo/page.tsx @@ -171,7 +171,7 @@ export default function DemoPage({ params }: { params: { locale: string } }) { {/* Error Display */} {createError && (
    -

    {createError}

    +

    {createError}

    )}
    diff --git a/apps/web/src/app/[locale]/monitoring/page.tsx b/apps/web/src/app/[locale]/monitoring/page.tsx index 2f2b60328..cf2bdf38c 100644 --- a/apps/web/src/app/[locale]/monitoring/page.tsx +++ b/apps/web/src/app/[locale]/monitoring/page.tsx @@ -84,10 +84,10 @@ function HealthSummary({ data }: { data: DashboardResponse }) { { label: '異常', count: data.critical_count, color: 'text-status-critical', bg: 'bg-status-critical/10' }, ].map(item => (
    -
    +
    {item.count}
    -
    +
    {item.label} · {Math.round(item.count / total * 100)}%
    @@ -155,7 +155,7 @@ export default function MonitoringPage({ params }: { params: { locale: string } {t('nav.monitoring')} -

    +

    {t('alerts.autoRefresh', { seconds: 30 })}

    @@ -164,7 +164,7 @@ export default function MonitoringPage({ params }: { params: { locale: string } disabled={isLoading} className={cn( 'flex items-center gap-1.5 px-3 py-1.5 rounded-lg', - 'text-xs font-mono bg-nothing-gray-100 text-nothing-gray-600', + 'text-xs font-body bg-nothing-gray-100 text-nothing-gray-600', 'hover:bg-nothing-gray-200 transition-colors', 'disabled:opacity-50 disabled:cursor-not-allowed' )} @@ -178,7 +178,7 @@ export default function MonitoringPage({ params }: { params: { locale: string } {dashError && (
    - {dashError} + {dashError}
    )} @@ -187,7 +187,7 @@ export default function MonitoringPage({ params }: { params: { locale: string } {/* Gold Metrics */}
    -

    +

    黃金指標 (Gold Metrics)

    {metricsLoading && metrics.length === 0 ? ( @@ -201,7 +201,7 @@ export default function MonitoringPage({ params }: { params: { locale: string } {/* Host Grid */}
    -

    +

    主機狀態 (Four-Host Architecture)

    @@ -210,7 +210,7 @@ export default function MonitoringPage({ params }: { params: { locale: string } {/* Service Table */} {dashboard && dashboard.services && dashboard.services.length > 0 && (
    -

    +

    服務清單

    @@ -218,7 +218,7 @@ export default function MonitoringPage({ params }: { params: { locale: string }
{['服務名稱', '狀態', '延遲', '可用率', '最後檢查'].map(h => ( - ))} @@ -230,25 +230,25 @@ export default function MonitoringPage({ params }: { params: { locale: string } 'border-b border-nothing-gray-100 last:border-0', i % 2 === 0 ? 'bg-white' : 'bg-nothing-gray-50/50' )}> - - - -
+ {t('actionLog.columns.time')} + {t('actionLog.columns.operation')} + {t('actionLog.columns.target')} + {t('actionLog.columns.namespace')} + {t('actionLog.columns.status')} + {t('actionLog.columns.duration')} + {t('actionLog.columns.executor')}
+ {formatDate(log.created_at)} + {log.target_resource} + {log.namespace} {log.success ? ( - + {t('actionLog.status.success')} ) : ( - + {t('actionLog.status.failure')} )} + {formatDuration(log.execution_duration_ms)} + {log.executed_by}
+ {h} + {svc.name} {STATUS_ICON[svc.status]} {svc.status} + {svc.latency_ms != null ? `${svc.latency_ms}ms` : '--'} + {svc.uptime_pct != null ? `${svc.uptime_pct.toFixed(2)}%` : '--'} + {svc.last_checked ? new Date(svc.last_checked).toLocaleTimeString() : '--'} diff --git a/apps/web/src/app/[locale]/settings/page.tsx b/apps/web/src/app/[locale]/settings/page.tsx index 2e7eab49b..7e2cffa6b 100644 --- a/apps/web/src/app/[locale]/settings/page.tsx +++ b/apps/web/src/app/[locale]/settings/page.tsx @@ -42,7 +42,7 @@ function SettingRow({

{label}

- {description &&

{description}

} + {description &&

{description}

}
{children}
@@ -131,7 +131,7 @@ export default function SettingsPage({ params }: { params: { locale: string } }) )} > - {t(section.titleKey)} + {t(section.titleKey)} {activeSection !== section.id && } ))} @@ -144,12 +144,12 @@ export default function SettingsPage({ params }: { params: { locale: string } }) {/* Appearance */} {activeSection === 'appearance' && (
-

{t('appearanceSettings')}

+

{t('appearanceSettings')}

- v7.0 + v7.0
@@ -163,7 +163,7 @@ export default function SettingsPage({ params }: { params: { locale: string } }) {/* Language */} {activeSection === 'language' && (
-

{t('languageSettings')}

+

{t('languageSettings')}

{[ { code: 'zh-TW', labelKey: 'zhTW', subKey: 'zhTWSub' }, { code: 'en', labelKey: 'en', subKey: 'enSub' }, @@ -180,7 +180,7 @@ export default function SettingsPage({ params }: { params: { locale: string } }) >

{t(lang.labelKey)}

-

{t(lang.subKey)}

+

{t(lang.subKey)}

{params.locale === lang.code && }
@@ -191,7 +191,7 @@ export default function SettingsPage({ params }: { params: { locale: string } }) {/* Notifications */} {activeSection === 'notify' && (
-

{t('notifySettings')}

+

{t('notifySettings')}

@@ -199,7 +199,7 @@ export default function SettingsPage({ params }: { params: { locale: string } }) - {t('backendConfig')} + {t('backendConfig')}
)} @@ -207,7 +207,7 @@ export default function SettingsPage({ params }: { params: { locale: string } }) {/* System */} {activeSection === 'system' && (
-

{t('systemSettings')}

+

{t('systemSettings')}

{[ { labelKey: 'frontendVersion', value: 'v1.0.0' }, { labelKey: 'apiEndpoint', value: process.env.NEXT_PUBLIC_API_URL ?? t('notConfigured') }, @@ -215,7 +215,7 @@ export default function SettingsPage({ params }: { params: { locale: string } }) { labelKey: 'phase', value: 'Phase 23 (2026-04-01)' }, ].map(item => ( - {item.value} + {item.value} ))}
@@ -226,12 +226,12 @@ export default function SettingsPage({ params }: { params: { locale: string } })
{saved && ( - + {t('saved')} diff --git a/apps/web/src/components/agent/approval-card.tsx b/apps/web/src/components/agent/approval-card.tsx index 3e82831e4..c824c84d8 100644 --- a/apps/web/src/components/agent/approval-card.tsx +++ b/apps/web/src/components/agent/approval-card.tsx @@ -145,7 +145,7 @@ export function ApprovalCard({ {/* Risk Badge */}
-
+
{t('signatures')}
@@ -193,40 +193,40 @@ export function ApprovalCard({ {/* Blast Radius Section */}
-

+

{tBlast('title')}

{/* Affected Pods */}
-
+
{tBlast('affectedPods')}
-
+
{request.blastRadius?.affectedPods ?? 0}
{/* Estimated Downtime */}
-
+
{tBlast('estimatedDowntime')}
-
+
{request.blastRadius?.estimatedDowntime ?? '0'}
{/* Related Services */}
-
+
{tBlast('relatedServices')}
{(request.blastRadius?.relatedServices ?? []).map((service) => ( {service} @@ -236,10 +236,10 @@ export function ApprovalCard({ {/* Data Impact */}
-
+
{tBlast('dataImpact')}
-
+
{dataImpactLabel}
@@ -251,7 +251,7 @@ export function ApprovalCard({ {/* Dry-Run Checks */}
-

+

{tDryRun('validation')}

@@ -271,12 +271,12 @@ export function ApprovalCard({ > {check.passed ? '✓' : '✗'}
- + {check.name}
{check.message && ( - + {check.message} )} @@ -291,7 +291,7 @@ export function ApprovalCard({ {/* Footer: Meta + Actions */}
{/* Meta */} -
+
{t('requestedBy')} {request.requestedBy} | @@ -304,7 +304,7 @@ export function ApprovalCard({
- + v1.0 | DOM Bypass | {lineCount} lines
@@ -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 && ( @@ -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 */}
{/* Content appended directly via DOM manipulation */} @@ -340,10 +340,10 @@ export function ThinkingTerminalOptimized({ {/* Footer */}
-

+

{t('stream')}

-

+

{status === 'streaming' ? ( ● LIVE ) : ( diff --git a/apps/web/src/components/agent/thinking-terminal.tsx b/apps/web/src/components/agent/thinking-terminal.tsx index dc7a9a49f..7ed3cfb05 100644 --- a/apps/web/src/components/agent/thinking-terminal.tsx +++ b/apps/web/src/components/agent/thinking-terminal.tsx @@ -59,7 +59,7 @@ function DependencyPathVisualizer({

{direction === 'upstream' ? t('blastRadius') : t('rootCauseChain')}
-
+
{paths.map((path, i) => (
{i === 0 ? '>' : '|'} @@ -97,7 +97,7 @@ function ServiceChainVisualizer({
{/* ASCII Art 風格圖形 */} -
+
{isBlastRadius ? ( // Blast Radius: 向上展示誰會受影響 <> @@ -200,7 +200,7 @@ function FinOpsVisualizer({ data }: { data: NonNullable

{t('title')}

- + v0.1.0 | SSE
@@ -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 */}
{thinkingStream.length === 0 && !isStreaming && !error && ( @@ -383,10 +383,10 @@ export function ThinkingTerminal({ {/* Footer */}
-

+

{t('stream')}

-

+

{t('events', { count: thinkingStream.length })}

diff --git a/apps/web/src/components/ai/ai-command-panel.tsx b/apps/web/src/components/ai/ai-command-panel.tsx index 222b3c887..4f8bf014b 100644 --- a/apps/web/src/components/ai/ai-command-panel.tsx +++ b/apps/web/src/components/ai/ai-command-panel.tsx @@ -73,13 +73,13 @@ export function AICommandPanel({ className }: AICommandPanelProps) {
- + {tApproval('pendingApprovals')}
- + {pendingApprovals.length}
@@ -107,7 +107,7 @@ export function AICommandPanel({ className }: AICommandPanelProps) { {pendingApprovals.length === 0 && (
-

+

{tApproval('noApprovals')}

diff --git a/apps/web/src/components/ai/ai-thinking-panel.tsx b/apps/web/src/components/ai/ai-thinking-panel.tsx index 6c5809f98..17e3b70c3 100644 --- a/apps/web/src/components/ai/ai-thinking-panel.tsx +++ b/apps/web/src/components/ai/ai-thinking-panel.tsx @@ -179,18 +179,18 @@ export function AIThinkingPanel({
{/* Header */}
- + OpenClaw AI {alertType && ( - + {alertType} )}
{/* Typewriter text - Dot Matrix Style (Phase 8.0 #16: CSS cursor blink) */} -
+
{displayText}
@@ -216,7 +216,7 @@ export function AIThinkingPanel({ {/* Bottom status bar */}
-
+
{currentPhase === 'complete' ? t('analysisComplete') : t('processingAlert')} diff --git a/apps/web/src/components/ai/hitl-section.tsx b/apps/web/src/components/ai/hitl-section.tsx index eb86cce16..bb1656480 100644 --- a/apps/web/src/components/ai/hitl-section.tsx +++ b/apps/web/src/components/ai/hitl-section.tsx @@ -280,7 +280,7 @@ export function HITLSection({ locale: _locale, className }: HITLSectionProps) { disabled={isSimulating} className={cn( 'flex items-center gap-1.5 px-3 py-1.5 rounded-lg', - 'font-mono text-xs font-medium', + 'font-body text-xs font-medium', 'bg-status-critical/10 text-status-critical border border-status-critical/20', 'hover:bg-status-critical/20 transition-colors', 'disabled:opacity-50 disabled:cursor-not-allowed' @@ -298,7 +298,7 @@ export function HITLSection({ locale: _locale, className }: HITLSectionProps) { disabled={isSimulating} className={cn( 'flex items-center gap-1.5 px-3 py-1.5 rounded-lg', - 'font-mono text-xs font-medium', + 'font-body text-xs font-medium', 'bg-status-warning/10 text-status-warning border border-status-warning/20', 'hover:bg-status-warning/20 transition-colors', 'disabled:opacity-50 disabled:cursor-not-allowed' @@ -332,7 +332,7 @@ export function HITLSection({ locale: _locale, className }: HITLSectionProps) { {tApproval('noApprovals')} -

+

[SYS] All clear. Awaiting alerts...

@@ -356,7 +356,7 @@ export function HITLSection({ locale: _locale, className }: HITLSectionProps) { {/* Phase 3: Permission Warning Badge */} {!hasPermission && ( -
+
需要 {getRequiredRolesDisplay(frontendApproval.riskLevel)}
@@ -382,11 +382,11 @@ export function HITLSection({ locale: _locale, className }: HITLSectionProps) { {/* Current User */}
- + 登入身份: {currentUserName} - 切換: + 切換:
{/* Debug Info */} -
+
Pending: {pendingApprovals.length} | Status: {openclawStatus}
@@ -452,29 +452,29 @@ export function HITLSection({ locale: _locale, className }: HITLSectionProps) { {/* Risk Level Badge */}
- + {accessDeniedModal.riskLevel} RISK
{/* Message */} -

+

此操作需要更高權限簽核

-

+

您的角色: {currentUserRole.toUpperCase()}

{/* Required Roles */}
-

+

需要以下角色之一

{accessDeniedModal.requiredRoles.split(' / ').map((role) => ( {role} @@ -485,7 +485,7 @@ export function HITLSection({ locale: _locale, className }: HITLSectionProps) { {/* Action Button */} diff --git a/apps/web/src/components/ai/openclaw-panel.tsx b/apps/web/src/components/ai/openclaw-panel.tsx index f3490536c..6e186dcd7 100644 --- a/apps/web/src/components/ai/openclaw-panel.tsx +++ b/apps/web/src/components/ai/openclaw-panel.tsx @@ -279,7 +279,7 @@ export function OpenClawPanel({ {/* Complete indicator */} {status === 'complete' && (
- + READY
diff --git a/apps/web/src/components/ai/openclaw-state-machine.tsx b/apps/web/src/components/ai/openclaw-state-machine.tsx index 291223330..e45a260dd 100644 --- a/apps/web/src/components/ai/openclaw-state-machine.tsx +++ b/apps/web/src/components/ai/openclaw-state-machine.tsx @@ -292,12 +292,12 @@ export function OpenClawStateMachine({ {/* Status Bar */}
- + STATE: - {error} + {error}
)} @@ -326,7 +326,7 @@ export function OpenClawStateMachine({ onClick={fetchPendingApprovals} disabled={isLoading} className={cn( - 'flex items-center gap-1 px-2 py-1 rounded text-[10px] font-mono', + 'flex items-center gap-1 px-2 py-1 rounded text-[10px] font-body', 'bg-nothing-gray-100 text-nothing-gray-600', 'hover:bg-nothing-gray-200 transition-colors', 'disabled:opacity-50 disabled:cursor-not-allowed' @@ -349,10 +349,10 @@ export function OpenClawStateMachine({
{/* 批次操作提示 */}
- + {pendingApprovals.length} 筆待簽核 - + 點擊查看詳情
@@ -400,13 +400,13 @@ export function OpenClawStateMachine({ {/* 標題 */}
- + {title}
{approval.riskLevel} - + {approval.currentSignatures}/{approval.requiredSignatures}
@@ -530,10 +530,10 @@ export function OpenClawStateMachine({ {machineState === 'idle' && pendingApprovals.length === 0 && !isLoading && (
-

+

{t('ai.standby')}

-

+

{lastFetch ? `Last check: ${lastFetch.toLocaleTimeString()}` : 'Waiting for first fetch...'} @@ -544,7 +544,7 @@ export function OpenClawStateMachine({ {/* Demo mode warning */} {demoMode && (

-

+

Demo mode is enabled. Real API polling is disabled.

diff --git a/apps/web/src/components/ai/thinking-stream.tsx b/apps/web/src/components/ai/thinking-stream.tsx index ddd326977..2024ca676 100644 --- a/apps/web/src/components/ai/thinking-stream.tsx +++ b/apps/web/src/components/ai/thinking-stream.tsx @@ -134,7 +134,7 @@ function ThinkingLine({ // 減少高頻 setState 造成的 DOM 重繪 return ( -
+
{/* Prefix */} (
-
+
{t('signatures')}
0 && (
-
+
已簽核: {signatures.map((sig, idx) => ( @@ -486,7 +486,7 @@ export function ApprovalCard({ {/* kubectl 命令: 獨立顯示,可複製 */} {request.action.includes('|') && ( - + {request.action.split('|')[1].trim()} )} @@ -504,7 +504,7 @@ export function ApprovalCard({ {/* Blast Radius - 可折疊面板 */}
-

+

{tBlast('title')} {/* 摘要預覽 */} @@ -528,14 +528,14 @@ export function ApprovalCard({ />
-
+
{tBlast('relatedServices')}
{(request.blastRadius.relatedServices ?? []).map((svc) => ( {svc} @@ -552,7 +552,7 @@ export function ApprovalCard({
- + {tBlast('dataImpact')}: {dataImpactLabel}
@@ -562,12 +562,12 @@ export function ApprovalCard({ {/* Dry-Run Checks - 可折疊面板 (預設收合) */}
-

+

{tDryRun('validation')} {/* 通過/失敗摘要 */} )} - + {check.name}

{check.message && ( {/* Meta */}
-
+
{t('requestedBy')} {request.requestedBy} | @@ -636,7 +636,7 @@ export function ApprovalCard({ - + 正在處理中...
@@ -646,7 +646,7 @@ export function ApprovalCard({ {/* 唯讀模式 - 不顯示按鈕 */} {readOnly ? (
-

+

此紀錄為歷史存檔,僅供稽核參考

@@ -657,7 +657,7 @@ export function ApprovalCard({
- + {t('waitingSecondSig')}
@@ -673,7 +673,7 @@ export function ApprovalCard({ disabled={isLoading || isProcessing} className={cn( 'flex-1 flex items-center justify-center gap-2', - 'px-6 py-3.5 rounded-xl font-mono text-sm font-semibold', + 'px-6 py-3.5 rounded-xl font-body text-sm font-semibold', 'bg-nothing-gray-50 border-2 border-nothing-gray-200 text-nothing-gray-600', 'hover:border-nothing-gray-300 hover:bg-nothing-gray-100 hover:text-nothing-gray-800', 'active:scale-[0.97]', @@ -707,7 +707,7 @@ export function ApprovalCard({
{/* Long Press Hint - Subtle */} -

+

{t('holdHint', { seconds: holdSeconds, action: hasPartialSignatures ? t('actionSign') : isDestructive ? t('actionConfirm') : t('actionApprove') @@ -740,9 +740,9 @@ function MetricBox({ label, value, className, highlight = false }: MetricBoxProp highlight ? 'border-status-warning/30' : 'border-nothing-gray-200', className )}> -

{label}
+
{label}
{value} diff --git a/apps/web/src/components/approval/approval-thread-item.tsx b/apps/web/src/components/approval/approval-thread-item.tsx index 6898498d5..02084872f 100644 --- a/apps/web/src/components/approval/approval-thread-item.tsx +++ b/apps/web/src/components/approval/approval-thread-item.tsx @@ -143,14 +143,14 @@ export function ApprovalThreadItem({ {/* 頂部: 風險指示器 + 時間 */}
{approval.riskLevel}
- + {relativeTime}
@@ -167,7 +167,7 @@ export function ApprovalThreadItem({ {/* 底部: 動作類型 + 狀態指示 */}
- + {actionSummary} {tBatch('title')}

-
+
{stats.total} {t('pendingApprovals')}
@@ -192,25 +192,25 @@ export function BatchModeSelector({
- + LOW: {stats.low}
- + MED: {stats.medium}
- + HIGH: {stats.high}
- + CRIT: {stats.critical}
@@ -241,7 +241,7 @@ export function BatchModeSelector({ {tBatch('bulkApprove')}
- + {stats.canBulkApprove} {tBatch('eligible')} @@ -263,7 +263,7 @@ export function BatchModeSelector({ {tBatch('sequential')}
- + {stats.total} {tBatch('items')} @@ -287,7 +287,7 @@ export function BatchModeSelector({ {tBatch('criticalOnly')}
- + {stats.critical} {tBatch('items')} diff --git a/apps/web/src/components/approval/compact-approval-item.tsx b/apps/web/src/components/approval/compact-approval-item.tsx index 26af6ea94..fd3c95bcb 100644 --- a/apps/web/src/components/approval/compact-approval-item.tsx +++ b/apps/web/src/components/approval/compact-approval-item.tsx @@ -109,14 +109,14 @@ export function CompactApprovalItem({ {/* 標題與摘要 */}
- + {title}
{tRisk(request.riskLevel)} - + {request.currentSignatures}/{request.requiredSignatures}
diff --git a/apps/web/src/components/approval/conversational-view.tsx b/apps/web/src/components/approval/conversational-view.tsx index 209da89dd..28cd7beba 100644 --- a/apps/web/src/components/approval/conversational-view.tsx +++ b/apps/web/src/components/approval/conversational-view.tsx @@ -236,7 +236,7 @@ export function ConversationalView({ {/* SSE 連線狀態 */}
1 && (
- + {selectedIndex + 1} / {approvals.length}
@@ -302,7 +302,7 @@ export function ConversationalView({ {approvals.length === 0 ? (
-

{t('noPendingApprovals')}

+

{t('noPendingApprovals')}

) : ( approvals.map((approval) => ( @@ -353,7 +353,7 @@ export function ConversationalView({
{/* 分頁指示器 */} -
+
{selectedIndex + 1} / {approvals.length}
{/* 快速導航按鈕 */} @@ -411,7 +411,7 @@ export function ConversationalView({
)} @@ -439,7 +439,7 @@ export function ConversationalView({
-

+

{t('holdToApproveHint')}

@@ -469,7 +469,7 @@ function ShortcutRow({ {t('pendingApprovals')} - + {approvals.length}
@@ -254,14 +254,14 @@ export function LiveApprovalPanel({ {/* Error State */} {error && (
-

{t('fetchError')}: {error}

+

{t('fetchError')}: {error}

)} {/* Phase 20: CSRF Error State */} {csrfError && (
-

+

⚠️ CSRF Token 載入失敗,簽核功能暫時無法使用

@@ -270,7 +270,7 @@ export function LiveApprovalPanel({ {/* Phase 20: CSRF Loading State */} {csrfLoading && (
-

+

🔐 正在載入安全憑證...

@@ -282,7 +282,7 @@ export function LiveApprovalPanel({
-

{t('noApprovals')}

+

{t('noApprovals')}

@@ -291,11 +291,11 @@ export function LiveApprovalPanel({ {/* Current User Role Display (Phase 3 Demo) */}
- + 登入身份: {currentUser.name} +
需要 {getRequiredRolesDisplay(approval.riskLevel)}
@@ -356,7 +356,7 @@ export function LiveApprovalPanel({
-

+

{t('signSuccess')}

@@ -368,7 +368,7 @@ export function LiveApprovalPanel({
-

+

{tCommon('error')}

@@ -394,20 +394,20 @@ export function LiveApprovalPanel({ value={rejectReason} onChange={(e) => setRejectReason(e.target.value)} placeholder={t('enterReason')} - className="w-full h-32 px-4 py-3 rounded-lg border border-nothing-gray-200 bg-white/50 resize-none font-mono text-sm focus:outline-none focus:ring-2 focus:ring-status-critical/50" + className="w-full h-32 px-4 py-3 rounded-lg border border-nothing-gray-200 bg-white/50 resize-none font-body text-sm focus:outline-none focus:ring-2 focus:ring-status-critical/50" autoFocus />
@@ -438,29 +438,29 @@ export function LiveApprovalPanel({ {/* Risk Level Badge */}
- + {accessDeniedModal.riskLevel} RISK
{/* Message */} -

+

此操作需要更高權限簽核

-

+

您的角色: {currentUser.role.toUpperCase()}

{/* Required Roles */}
-

+

需要以下角色之一

{accessDeniedModal.requiredRoles.split(' / ').map((role) => ( {role} @@ -471,7 +471,7 @@ export function LiveApprovalPanel({ {/* Action Button */} diff --git a/apps/web/src/components/charts/ai-process-stepper.tsx b/apps/web/src/components/charts/ai-process-stepper.tsx index 573d9e595..814978715 100644 --- a/apps/web/src/components/charts/ai-process-stepper.tsx +++ b/apps/web/src/components/charts/ai-process-stepper.tsx @@ -155,7 +155,7 @@ function Step({ step, index, isLast }: StepProps) {
diff --git a/apps/web/src/components/charts/global-pulse-chart.tsx b/apps/web/src/components/charts/global-pulse-chart.tsx index 3bd4113a2..c43073ed5 100644 --- a/apps/web/src/components/charts/global-pulse-chart.tsx +++ b/apps/web/src/components/charts/global-pulse-chart.tsx @@ -139,7 +139,7 @@ function MetricCard({ metric }: MetricCardProps) {

{metric.value} {metric.unit && ( - + {metric.unit} )} diff --git a/apps/web/src/components/charts/time-series-chart.tsx b/apps/web/src/components/charts/time-series-chart.tsx index 7d8662d5d..3ceeb0302 100644 --- a/apps/web/src/components/charts/time-series-chart.tsx +++ b/apps/web/src/components/charts/time-series-chart.tsx @@ -98,7 +98,7 @@ function CustomTooltip({ active, payload, unit }: CustomTooltipProps) { return (

{time}

-

+

{data.value.toFixed(2)}{unit && ` ${unit}`}

diff --git a/apps/web/src/components/cyber/data-pincer-card.tsx b/apps/web/src/components/cyber/data-pincer-card.tsx index f479fd89e..d919a501c 100644 --- a/apps/web/src/components/cyber/data-pincer-card.tsx +++ b/apps/web/src/components/cyber/data-pincer-card.tsx @@ -93,7 +93,7 @@ export function DataPincerCard({ {/* 標題 (如有) */} {title && (
-

+

{title}

diff --git a/apps/web/src/components/dashboard/connection-status.tsx b/apps/web/src/components/dashboard/connection-status.tsx index 0338c1fa0..19717a92e 100644 --- a/apps/web/src/components/dashboard/connection-status.tsx +++ b/apps/web/src/components/dashboard/connection-status.tsx @@ -90,11 +90,11 @@ export function ConnectionStatus({ {showLabel && (
- + {t(labelKey)} {showLastUpdate && lastUpdate && ( - + {lastUpdateStr} )} @@ -102,7 +102,7 @@ export function ConnectionStatus({ )} {mockMode && ( - + {t('mockMode')} )} @@ -127,7 +127,7 @@ export function ConnectionStatusCompact({ className }: { className?: string }) { )} > - + {t(connectionLabelKeys[connectionStatus])}
diff --git a/apps/web/src/components/dashboard/host-card.tsx b/apps/web/src/components/dashboard/host-card.tsx index dafed01cb..586d46219 100644 --- a/apps/web/src/components/dashboard/host-card.tsx +++ b/apps/web/src/components/dashboard/host-card.tsx @@ -113,7 +113,7 @@ export function HostCard({
- + {ip}
@@ -140,18 +140,18 @@ export function HostCard({ >
- + {service.name}
{service.port && ( - + :{service.port} )} {service.latencyMs !== null && service.latencyMs !== undefined && ( - + {service.latencyMs.toFixed(1)}ms )} @@ -168,7 +168,7 @@ export function HostCard({
{tDashboard('cpu')} - + {formatPercent(metrics.cpuPercent)}
@@ -191,7 +191,7 @@ export function HostCard({
{tDashboard('memory')} - + {formatPercent(metrics.memoryPercent)}
@@ -218,7 +218,7 @@ export function HostCard({
- + {new Date().toLocaleTimeString('zh-TW', { hour: '2-digit', minute: '2-digit', diff --git a/apps/web/src/components/dashboard/live-dashboard.tsx b/apps/web/src/components/dashboard/live-dashboard.tsx index eafec884f..89c1d071e 100644 --- a/apps/web/src/components/dashboard/live-dashboard.tsx +++ b/apps/web/src/components/dashboard/live-dashboard.tsx @@ -225,12 +225,12 @@ function OpenClawPanel() {

{t('name')}

- + {t('monitoring')}
- v5.0.0 + v5.0.0 @@ -243,7 +243,7 @@ function OpenClawPanel() {
- + {tCommon('loading')} {ip}
@@ -126,7 +126,7 @@ export function LiveHostCard({
- + {ip}
@@ -137,7 +137,7 @@ export function LiveHostCard({ {fallbackData.services.map((service) => (
- + {service.name}
@@ -197,7 +197,7 @@ export function LiveHostCard({ {getRoleIcon(host.role || '')}
- + {host.ip} @@ -210,7 +210,7 @@ export function LiveHostCard({
{host.name} {host.role && ( - + {host.role.replace('_', ' ')} )} @@ -226,20 +226,20 @@ export function LiveHostCard({ >
- + {service.name}
{service.port && ( - + :{service.port} )} {service.latency_ms !== null && service.latency_ms !== undefined && ( 100 ? 'text-status-warning' : 'text-nothing-gray-500' @@ -287,7 +287,7 @@ export function LiveHostCard({
- + {new Date(host.last_check).toLocaleTimeString('zh-TW', { hour: '2-digit', minute: '2-digit', @@ -330,8 +330,8 @@ function MetricBar({ return (
- {label} - + {label} + {collectingLabel}
@@ -372,12 +372,12 @@ function MetricBar({ ) : ( )} - {label} + {label}
= criticalThreshold ? 'text-status-critical' : value >= warningThreshold @@ -389,7 +389,7 @@ function MetricBar({ {/* Dynamic Baseline Display */} {baselineValue !== null && baselineValue !== undefined && ( - + ({formatPercent(baselineValue)}) )} diff --git a/apps/web/src/components/genui/ApprovalCard.tsx b/apps/web/src/components/genui/ApprovalCard.tsx index 546446e13..18d1669e5 100644 --- a/apps/web/src/components/genui/ApprovalCard.tsx +++ b/apps/web/src/components/genui/ApprovalCard.tsx @@ -84,7 +84,7 @@ export const ApprovalCard: React.FC = ({ data }) => { Approval Required // {data.approvalId}
-
{data.riskLevel} @@ -94,7 +94,7 @@ export const ApprovalCard: React.FC = ({ data }) => {
{/* Metadata */} {(data.requestedBy || data.requestedAt) && ( -
+
{data.requestedBy && (
@@ -132,13 +132,13 @@ export const ApprovalCard: React.FC = ({ data }) => { {/* Nuclear Key Authorization */}
{executionResult === 'success' ? ( -
+
{t('executionAuthorized')} {t('authorized')}
) : executionResult === 'error' ? ( -
+
{t('executionFailed')}
@@ -158,7 +158,7 @@ export const ApprovalCard: React.FC = ({ data }) => { } const Label = ({ children }: { children: React.ReactNode }) => ( - + {children} ) diff --git a/apps/web/src/components/genui/GenUIRenderer.tsx b/apps/web/src/components/genui/GenUIRenderer.tsx index fac246434..b1258553e 100644 --- a/apps/web/src/components/genui/GenUIRenderer.tsx +++ b/apps/web/src/components/genui/GenUIRenderer.tsx @@ -127,7 +127,7 @@ const LoadingCard: React.FC<{ componentName: string }> = ({ componentName }) =>
- + Loading {componentName}...
@@ -139,8 +139,8 @@ const ErrorCard: React.FC<{ title: string; message: string }> = ({ title, messag
-
{title}
-
{message}
+
{title}
+
{message}
diff --git a/apps/web/src/components/genui/IncidentTimelineCard.tsx b/apps/web/src/components/genui/IncidentTimelineCard.tsx index d8c33d0dc..ab632c66f 100644 --- a/apps/web/src/components/genui/IncidentTimelineCard.tsx +++ b/apps/web/src/components/genui/IncidentTimelineCard.tsx @@ -53,11 +53,11 @@ export const IncidentTimelineCard: React.FC = ({ data
{data.severity && ( - + {data.severity} )} - + {data.status}
@@ -67,18 +67,18 @@ export const IncidentTimelineCard: React.FC = ({ data
{data.events.map((event, i) => (
-
+
{event.timestamp}
- {event.type} - {event.message} + {event.message}
))} diff --git a/apps/web/src/components/genui/K8sPodStatusCard.tsx b/apps/web/src/components/genui/K8sPodStatusCard.tsx index a0bb99bba..78fbfe0c9 100644 --- a/apps/web/src/components/genui/K8sPodStatusCard.tsx +++ b/apps/web/src/components/genui/K8sPodStatusCard.tsx @@ -77,7 +77,7 @@ export const K8sPodStatusCard: React.FC = ({ data }) => { K8s Pods // {data.namespace}
-
+
{summary.running}/{summary.total} RUNNING
@@ -87,7 +87,7 @@ export const K8sPodStatusCard: React.FC = ({ data }) => { {data.pods.map((pod, i) => (
{statusIcon(pod.status)} {pod.name} diff --git a/apps/web/src/components/genui/MetricsSummaryCard.tsx b/apps/web/src/components/genui/MetricsSummaryCard.tsx index 53d56d326..14f072175 100644 --- a/apps/web/src/components/genui/MetricsSummaryCard.tsx +++ b/apps/web/src/components/genui/MetricsSummaryCard.tsx @@ -55,7 +55,7 @@ export const MetricsSummaryCard: React.FC = ({ data }) SignOz Metrics // Real-time
-
+
{status}
@@ -93,26 +93,26 @@ export const MetricsSummaryCard: React.FC = ({ data })
{data.cpu !== undefined && (
- CPU: + CPU:
80 ? 'bg-red-500' : data.cpu > 60 ? 'bg-yellow-500' : 'bg-green-500'}`} style={{ width: `${data.cpu}%` }} />
- {data.cpu}% + {data.cpu}%
)} {data.memory !== undefined && (
- MEM: + MEM:
80 ? 'bg-red-500' : data.memory > 60 ? 'bg-yellow-500' : 'bg-green-500'}`} style={{ width: `${data.memory}%` }} />
- {data.memory}% + {data.memory}%
)}
@@ -121,7 +121,7 @@ export const MetricsSummaryCard: React.FC = ({ data }) {/* Pods status */} {data.pods && (
-
+
Pods: {data.pods.running}/{data.pods.total} running
@@ -141,7 +141,7 @@ const MetricBox: React.FC<{
{icon} - {label} + {label}
{value} diff --git a/apps/web/src/components/genui/NuclearKeyButton.tsx b/apps/web/src/components/genui/NuclearKeyButton.tsx index b13e6a18b..0e489d28f 100644 --- a/apps/web/src/components/genui/NuclearKeyButton.tsx +++ b/apps/web/src/components/genui/NuclearKeyButton.tsx @@ -167,7 +167,7 @@ export const NuclearKeyButton: React.FC = ({ w-full py-4 px-6 rounded-sm border-2 bg-green-50 border-green-500 flex items-center justify-center gap-2 - font-mono font-bold text-green-700 + font-body font-bold text-green-700 transition-all duration-300 `}> @@ -218,7 +218,7 @@ export const NuclearKeyButton: React.FC = ({ className={`${config.textColor} ${isHolding ? 'animate-pulse' : ''} sm:w-5 sm:h-5`} /> - + {isHolding ? ( {label} ({Math.ceil((1 - progress) * (duration ?? 1500) / 1000)}s) @@ -230,7 +230,7 @@ export const NuclearKeyButton: React.FC = ({ {/* Risk Badge */} @@ -241,7 +241,7 @@ export const NuclearKeyButton: React.FC = ({ {/* Shortcut Hint - Hidden on mobile touch devices */} {showShortcut && !disabled && ( -
+
{isHolding ? ( {t('keepHolding')} @@ -271,7 +271,7 @@ export const NuclearKeyButton: React.FC = ({ {/* Critical Warning */} {isCritical && !disabled && !isHolding && (
diff --git a/apps/web/src/components/genui/SentryErrorCard.tsx b/apps/web/src/components/genui/SentryErrorCard.tsx index dd5d45809..33e2202c2 100644 --- a/apps/web/src/components/genui/SentryErrorCard.tsx +++ b/apps/web/src/components/genui/SentryErrorCard.tsx @@ -41,14 +41,14 @@ export const SentryErrorCard: React.FC = ({ data }) => { Sentry // {data.errorId}
-
+
{level}
- + Error
@@ -56,7 +56,7 @@ export const SentryErrorCard: React.FC = ({ data }) => {
-
+
{data.count !== undefined && (
Count:{' '} @@ -76,7 +76,7 @@ export const SentryErrorCard: React.FC = ({ data }) => { href={data.url} target="_blank" rel="noopener noreferrer" - className="inline-flex items-center gap-1 text-sm font-mono text-[#4A90D9] hover:underline" + className="inline-flex items-center gap-1 text-sm font-body text-[#4A90D9] hover:underline" > View in Sentry diff --git a/apps/web/src/components/genui/TraceWaterfallCard.tsx b/apps/web/src/components/genui/TraceWaterfallCard.tsx index 117dd80fe..212024d13 100644 --- a/apps/web/src/components/genui/TraceWaterfallCard.tsx +++ b/apps/web/src/components/genui/TraceWaterfallCard.tsx @@ -49,7 +49,7 @@ export const TraceWaterfallCard: React.FC = ({ data }) Trace // {data.traceId.slice(0, 16)}...
-
+
{data.duration}ms
@@ -58,7 +58,7 @@ export const TraceWaterfallCard: React.FC = ({ data }) {data.spans.map((span, i) => (
{/* Service name */} -
+
{span.service}
@@ -74,7 +74,7 @@ export const TraceWaterfallCard: React.FC = ({ data }) }} /> = ({ data })
{/* Duration */} -
+
{span.duration}ms
@@ -99,7 +99,7 @@ export const TraceWaterfallCard: React.FC = ({ data }) href={data.url} target="_blank" rel="noopener noreferrer" - className="inline-flex items-center gap-1 text-sm font-mono text-[#4A90D9] hover:underline" + className="inline-flex items-center gap-1 text-sm font-body text-[#4A90D9] hover:underline" > View in SignOz diff --git a/apps/web/src/components/incident/thinking-terminal.tsx b/apps/web/src/components/incident/thinking-terminal.tsx index ab7d99149..0d6422381 100644 --- a/apps/web/src/components/incident/thinking-terminal.tsx +++ b/apps/web/src/components/incident/thinking-terminal.tsx @@ -8,7 +8,7 @@ * * Nothing.tech 視覺規範: * - 深色背景 (bg-black text-white) - 全站唯一深色區域 - * - 強制等寬字體 (font-mono) + * - 強制等寬字體 (font-body) * - 打字機效果展示推論步驟 * * 統帥鐵律: 禁止假數據! @@ -168,7 +168,7 @@ export function ThinkingTerminal({ {/* Title */}
- + OpenClaw Terminal
@@ -177,7 +177,7 @@ export function ThinkingTerminal({ {/* Controls */}
{incidentId && ( - + {incidentId} )} @@ -214,7 +214,7 @@ export function ThinkingTerminal({ {isExpanded && (
{/* No Data State */} @@ -291,10 +291,10 @@ export function ThinkingTerminal({ {/* Terminal Footer */}
- + {t('steps')}: {displayedSteps}/{totalSteps} - + {isPlaying ? t('streaming') : t('paused')}
diff --git a/apps/web/src/components/layout/coming-soon.tsx b/apps/web/src/components/layout/coming-soon.tsx index f8c26fdac..6a4fcbb83 100644 --- a/apps/web/src/components/layout/coming-soon.tsx +++ b/apps/web/src/components/layout/coming-soon.tsx @@ -30,11 +30,11 @@ export function ComingSoon({ icon: Icon, title, description, className }: Coming
)} -

+

{title}

{description && ( -

+

{description}

)} diff --git a/apps/web/src/components/layout/header.tsx b/apps/web/src/components/layout/header.tsx index 92824373e..4194b740a 100644 --- a/apps/web/src/components/layout/header.tsx +++ b/apps/web/src/components/layout/header.tsx @@ -95,7 +95,7 @@ export function Header({ {pendingApprovals > 0 && (
- + {pendingApprovals} {tDashboard('pendingApprovals')}
@@ -105,13 +105,13 @@ export function Header({
{connectionLabel} {mockMode && ( - + MOCK )} @@ -122,7 +122,7 @@ export function Header({ @@ -105,8 +105,8 @@ class AutoHealingErrorBoundaryInner extends Component { return (
-
{translations.detectingAnomaly}
-
{translations.autoHealingAttempt(this.state.retryCount + 1)}
+
{translations.detectingAnomaly}
+
{translations.autoHealingAttempt(this.state.retryCount + 1)}
diff --git a/apps/web/src/components/shared/language-switcher.tsx b/apps/web/src/components/shared/language-switcher.tsx index 0d20a86bd..eb1c6f4ef 100644 --- a/apps/web/src/components/shared/language-switcher.tsx +++ b/apps/web/src/components/shared/language-switcher.tsx @@ -41,7 +41,7 @@ export function LanguageSwitcher({ className }: LanguageSwitcherProps) { key={loc} onClick={() => handleSwitch(loc)} className={cn( - 'px-3 py-1.5 rounded-sm font-mono text-xs transition-all duration-200', + 'px-3 py-1.5 rounded-sm font-body text-xs transition-all duration-200', 'focus:outline-none focus:ring-2 focus:ring-nothing-gray-400', isActive ? 'bg-nothing-gray-900 text-nothing-white' @@ -81,7 +81,7 @@ export function LanguageSwitcherCompact({ className }: LanguageSwitcherProps) { className={cn( 'px-3 py-1.5 rounded-button', 'bg-nothing-gray-100 border border-nothing-gray-200', - 'font-mono text-xs text-nothing-gray-600', + 'font-body text-xs text-nothing-gray-600', 'hover:text-nothing-gray-900 hover:bg-nothing-gray-200', 'transition-all duration-200', 'focus:outline-none focus:ring-2 focus:ring-nothing-gray-400', diff --git a/apps/web/src/components/status-orb.tsx b/apps/web/src/components/status-orb.tsx index e06ef2714..539dd3035 100644 --- a/apps/web/src/components/status-orb.tsx +++ b/apps/web/src/components/status-orb.tsx @@ -83,7 +83,7 @@ export function StatusOrb({ status, size = 'md', className }: StatusOrbProps) { {/* Label */}
- + {label}
diff --git a/apps/web/src/components/terminal/OmniTerminal.tsx b/apps/web/src/components/terminal/OmniTerminal.tsx index e25800eb8..c32a9cc7c 100644 --- a/apps/web/src/components/terminal/OmniTerminal.tsx +++ b/apps/web/src/components/terminal/OmniTerminal.tsx @@ -141,7 +141,7 @@ export const OmniTerminal = () => { const result = msg.payload.result as Record | undefined return ( -
+
[{tool ?? 'unknown'}]{' '} {status ?? 'executing'} {result && ( @@ -205,12 +205,12 @@ export const OmniTerminal = () => {
- {isConnected ? t('sseLive') : t('offline')} + {isConnected ? t('sseLive') : t('offline')}
- + {current} / {total}