fix(ui): 對齊 figma-v2 設計稿 — IncidentCard + OpenClawPanel 視覺修正
Some checks failed
CD Pipeline / build-and-deploy (push) Failing after 35s

IncidentCard:
- 背景 #fff、圓角 12px、頂邊條 4px(對齊設計稿)
- P1 嚴重度色修正為 #F59E0B(amber,非 orange)
- Severity badge 改為 4px 圓角 uppercase 樣式
- Impact 指標列移除灰底方塊,改為細邊框分隔線
- AI 提案按鈕改為全寬居中橙色風格

OpenClawPanel:
- 移除多餘 rounded-xl/backdrop/border(由父層卡片容器提供)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OG T
2026-04-02 23:36:59 +08:00
parent 97d86861ed
commit e9a1ac6276
2 changed files with 39 additions and 47 deletions

View File

@@ -182,13 +182,8 @@ export function OpenClawPanel({
return (
<div
className={cn(
'relative overflow-hidden rounded-xl',
// awoooi-glass effect
'bg-white/70 backdrop-blur-[20px]',
// 骨架細框線
'border border-nothing-gray-200/50',
// 輕柔陰影
'shadow-[0_4px_24px_rgba(0,0,0,0.06)]',
'relative overflow-hidden',
'bg-white',
'p-4',
className
)}

View File

@@ -39,10 +39,10 @@ export interface IncidentCardProps {
// =============================================================================
const SEV_CONFIG = {
P0: { barColor: '#cc2200', label: 'P0', labelBg: '#ffeaea', labelColor: '#cc2200' },
P1: { barColor: '#d97757', label: 'P1', labelBg: '#fff0ea', labelColor: '#b05030' },
P2: { barColor: '#4A90D9', label: 'P2', labelBg: '#eaf4ff', labelColor: '#2a6cb0' },
P3: { barColor: '#22C55E', label: 'P3', labelBg: '#eafff2', labelColor: '#166534' },
P0: { barColor: '#cc2200', label: 'P0', labelBg: 'rgba(204,34,0,0.1)', labelColor: '#cc2200' },
P1: { barColor: '#F59E0B', label: 'P1', labelBg: 'rgba(245,158,11,0.12)', labelColor: '#d97000' },
P2: { barColor: '#4A90D9', label: 'P2', labelBg: 'rgba(74,144,217,0.12)', labelColor: '#4A90D9' },
P3: { barColor: '#22C55E', label: 'P3', labelBg: 'rgba(34,197,94,0.1)', labelColor: '#16a34a' },
} as const
/** 根據 incident status 對應 FlowStage */
@@ -282,37 +282,38 @@ export function IncidentCard({ incident, decision, onApprovalChange }: IncidentC
return (
<div style={{
background: '#faf9f3',
background: '#fff',
border: '0.5px solid #e0ddd4',
borderRadius: 8,
borderRadius: 12,
overflow: 'hidden',
marginBottom: 8,
boxShadow: '0 1px 4px rgba(0,0,0,0.05)',
}}>
{/* 頂邊條 3px */}
<div style={{ height: 3, background: sevCfg.barColor, borderRadius: '8px 8px 0 0' }} />
{/* 頂邊條 4px */}
<div style={{ height: 4, background: sevCfg.barColor }} />
{/* 標頭列:嚴重度 + 服務標籤 + 時間 */}
<div style={{ display: 'flex', alignItems: 'center', gap: 6, padding: '8px 10px 4px' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '10px 14px 4px' }}>
<span style={{
fontSize: 12, fontWeight: 700, padding: '2px 8px',
fontSize: 10, fontWeight: 700, padding: '2px 7px',
background: sevCfg.labelBg, color: sevCfg.labelColor,
borderRadius: 10, flexShrink: 0,
borderRadius: 4, flexShrink: 0, textTransform: 'uppercase', letterSpacing: '1px',
}}>
{sevCfg.label}
</span>
<span style={{
fontSize: 12, color: '#87867f', background: '#ece9e0',
border: '0.5px solid #dedad0', padding: '2px 7px', borderRadius: 10,
fontSize: 10, color: '#87867f',
border: '0.5px solid #e0ddd4', padding: '2px 7px', borderRadius: 4,
background: '#fff',
}}>
{serviceName}
</span>
<span style={{ marginLeft: 'auto', fontSize: 12, color: '#b0ad9f' }}>
<span style={{ marginLeft: 'auto', fontSize: 11, color: '#b0ad9f' }}>
{duration}
</span>
</div>
{/* 事件標題 — 從 decision action 或 affected_services 組合 */}
<div style={{ padding: '2px 10px 4px', fontSize: 14, fontWeight: 600, color: '#141413', lineHeight: 1.4 }}>
<div style={{ padding: '4px 14px 2px', fontSize: 15, fontWeight: 600, color: '#141413', lineHeight: 1.3, fontFamily: 'var(--font-body), monospace' }}>
{incident.decision?.proposal_data?.action
?? (incident.affected_services?.length
? `${incident.affected_services.join(', ')} ${t('anomaly')}`
@@ -320,7 +321,7 @@ export function IncidentCard({ incident, decision, onApprovalChange }: IncidentC
</div>
{/* INC-ID */}
<div style={{ padding: '0 10px 4px', fontSize: 12, color: '#b0ad9f', fontFamily: 'var(--font-body), monospace' }}>
<div style={{ padding: '0 14px 6px', fontSize: 12, color: '#b0ad9f', fontFamily: 'var(--font-body), monospace' }}>
{incident.incident_id}
</div>
@@ -329,22 +330,20 @@ export function IncidentCard({ incident, decision, onApprovalChange }: IncidentC
{/* Impact 指標列 */}
<div style={{
margin: '0 10px 6px',
padding: '5px 8px',
background: '#f0efe8',
border: '0.5px solid #e0ddd4',
borderRadius: 6,
margin: '0 14px 8px',
padding: '6px 0',
borderTop: '0.5px solid #e0ddd4',
borderBottom: '0.5px solid #e0ddd4',
display: 'flex',
gap: 12,
flexWrap: 'wrap' as const,
gap: 16,
}}>
<span style={{ fontSize: 13, color: '#87867f' }}>
<span style={{ fontSize: 11, color: '#87867f' }}>
{t('affectedServices')} <strong style={{ color: '#141413' }}>{incident.affected_services?.length ?? 0}</strong>
</span>
<span style={{ fontSize: 13, color: '#87867f' }}>
<span style={{ fontSize: 11, color: '#87867f' }}>
{t('signalCount')} <strong style={{ color: '#141413' }}>{incident.signal_count ?? '--'}</strong>
</span>
<span style={{ fontSize: 13, color: '#87867f' }}>
<span style={{ fontSize: 11, color: '#87867f' }}>
{t('statusLabel')} <strong style={{ color: '#141413' }}>{incident.status}</strong>
</span>
</div>
@@ -355,26 +354,24 @@ export function IncidentCard({ incident, decision, onApprovalChange }: IncidentC
<button
onClick={() => setAiExpanded(v => !v)}
style={{
margin: '0 10px 6px',
padding: '5px 8px',
background: '#f0efe8',
border: '0.5px solid #e0ddd4',
borderLeft: '3px solid rgba(217,119,87,0.5)',
margin: '0 14px 10px',
padding: '7px 0',
background: 'rgba(217,119,87,0.08)',
border: '0.5px solid rgba(217,119,87,0.3)',
borderRadius: 6,
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: 5,
fontSize: 13,
color: '#87867f',
width: 'calc(100% - 20px)',
textAlign: 'left' as const,
fontSize: 12,
color: '#d97757',
width: 'calc(100% - 28px)',
textAlign: 'center' as const,
fontFamily: 'inherit',
}}
>
<span style={{ color: '#d97757' }}></span>
<span>{t('aiProposal')}: {decisionAction.slice(0, 50)}{decisionAction.length > 50 ? '...' : ''}</span>
<span style={{ marginLeft: 'auto' }}>{aiExpanded ? '▲' : '▼'}</span>
<span> {t('aiProposal')}: {decisionAction.slice(0, 50)}{decisionAction.length > 50 ? '...' : ''}</span>
</button>
{aiExpanded && (
<div style={{
@@ -400,7 +397,7 @@ export function IncidentCard({ incident, decision, onApprovalChange }: IncidentC
{/* 授權按鈕(僅 waiting_approval 狀態)*/}
{isWaitingApproval && (
<div style={{ padding: '6px 10px 10px', display: 'flex', justifyContent: 'flex-end' }}>
<div style={{ padding: '6px 14px 12px', display: 'flex', justifyContent: 'flex-end' }}>
{renderApproveButtons()}
{errorMessage && (
<span style={{ fontSize: 12, color: '#cc2200', marginLeft: 6, maxWidth: 160, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} title={errorMessage}>