From 540602fd63df45d149998f6048d009eabd169a57 Mon Sep 17 00:00:00 2001 From: OG T Date: Thu, 26 Mar 2026 13:26:05 +0800 Subject: [PATCH] =?UTF-8?q?fix(web):=20Phase=2017=20=E5=AF=A9=E6=A0=B8?= =?UTF-8?q?=E5=8D=A1=E7=89=87=20UI/UX=20=E4=BF=AE=E5=BE=A9=20-=20SlidePane?= =?UTF-8?q?l=20=E2=86=92=20ApprovalModal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 問題: - SlidePanel 側邊滑入與右側 OpenClaw 固定面板衝突 - 480px 寬度不足,內容被擠壓截斷 - 標題「審核詳情」只顯示「情」 解決方案: - 新建 ApprovalModal 全屏 Modal 組件 - 居中對話框 (max-width: 672px) - 深色遮罩 (60%) 強制用戶聚焦 - 符合 Nothing.tech「一次專注一件事」設計哲學 設計參考: GitHub PR Review, AWS IAM Console Co-Authored-By: Claude Opus 4.5 --- .../components/ai/openclaw-state-machine.tsx | 11 +- apps/web/src/components/ui/approval-modal.tsx | 153 ++++++++++++++++++ apps/web/src/components/ui/index.ts | 3 + 3 files changed, 161 insertions(+), 6 deletions(-) create mode 100644 apps/web/src/components/ui/approval-modal.tsx diff --git a/apps/web/src/components/ai/openclaw-state-machine.tsx b/apps/web/src/components/ai/openclaw-state-machine.tsx index 1630eb272..3e2bec026 100644 --- a/apps/web/src/components/ai/openclaw-state-machine.tsx +++ b/apps/web/src/components/ai/openclaw-state-machine.tsx @@ -22,7 +22,7 @@ import { cn } from '@/lib/utils' import { OpenClawPanel, type OpenClawStatus } from './openclaw-panel' import { ThinkingStream, DEFAULT_THINKING_MESSAGES } from './thinking-stream' import { ApprovalCard, type ApprovalRequest } from '@/components/approval/approval-card' -import { SlidePanel } from '@/components/ui/slide-panel' +import { ApprovalModal } from '@/components/ui/approval-modal' import { RefreshCw, AlertCircle, CheckCircle2, AlertTriangle, Shield, XCircle, ChevronRight } from 'lucide-react' // ============================================================================= @@ -410,8 +410,8 @@ export function OpenClawStateMachine({ )} - {/* Slide Panel - 詳情面板 */} - setSelectedIndex(null)} title="審核詳情" @@ -419,10 +419,9 @@ export function OpenClawStateMachine({ onNext={handleNextApproval} current={selectedIndex !== null ? selectedIndex + 1 : undefined} total={pendingApprovals.length} - width="lg" > {selectedApproval && ( -
+
{ @@ -442,7 +441,7 @@ export function OpenClawStateMachine({ />
)} - + {/* Idle state - no pending approvals */} {machineState === 'idle' && pendingApprovals.length === 0 && !isLoading && ( diff --git a/apps/web/src/components/ui/approval-modal.tsx b/apps/web/src/components/ui/approval-modal.tsx new file mode 100644 index 000000000..2987c3cfe --- /dev/null +++ b/apps/web/src/components/ui/approval-modal.tsx @@ -0,0 +1,153 @@ +'use client' + +/** + * ApprovalModal - 全屏審核 Modal + * =============================== + * Phase 17: UI/UX 修復 - 取代 SlidePanel + * + * 設計決策: + * - 審核是關鍵決策,需要用戶全神貫注 + * - 全屏遮罩強制用戶注意,防止誤操作 + * - 居中對話框提供足夠空間顯示所有資訊 + * - 符合 Nothing.tech「一次專注一件事」設計哲學 + * + * 參考: GitHub PR Review, AWS IAM Console + */ + +import { useEffect, useCallback } from 'react' +import { cn } from '@/lib/utils' +import { X, ChevronLeft, ChevronRight, Shield } from 'lucide-react' + +interface ApprovalModalProps { + open: boolean + onClose: () => void + children: React.ReactNode + title?: string + /** 上一個/下一個導航 */ + onPrev?: () => void + onNext?: () => void + /** 當前位置 (1-based) */ + current?: number + total?: number +} + +export function ApprovalModal({ + open, + onClose, + children, + title = '審核詳情', + onPrev, + onNext, + current, + total, +}: ApprovalModalProps) { + // ESC 關閉 + 方向鍵導航 + const handleKeyDown = useCallback((e: KeyboardEvent) => { + if (e.key === 'Escape') onClose() + if (e.key === 'ArrowLeft' && onPrev) onPrev() + if (e.key === 'ArrowRight' && onNext) onNext() + }, [onClose, onPrev, onNext]) + + // 鎖定背景滾動 + useEffect(() => { + if (open) { + document.body.style.overflow = 'hidden' + document.addEventListener('keydown', handleKeyDown) + } + return () => { + document.body.style.overflow = '' + document.removeEventListener('keydown', handleKeyDown) + } + }, [open, handleKeyDown]) + + if (!open) return null + + return ( +
+ {/* Backdrop - 深色遮罩,強調聚焦 */} +
+ + {/* Modal Container */} +
+ {/* Header */} +
+
+
+ +
+
+

+ {title} +

+

+ Multi-Sig Authorization Required +

+
+
+ +
+ {/* 導航控制 */} + {(onPrev || onNext) && current && total && total > 1 && ( +
+ + + {current} / {total} + + +
+ )} + + {/* 關閉按鈕 */} + +
+
+ + {/* Content - 可滾動 */} +
+ {children} +
+
+
+ ) +} diff --git a/apps/web/src/components/ui/index.ts b/apps/web/src/components/ui/index.ts index 20219d211..cd6e24069 100644 --- a/apps/web/src/components/ui/index.ts +++ b/apps/web/src/components/ui/index.ts @@ -34,3 +34,6 @@ export { GridLinesBg, type DotMatrixBgProps, } from './dot-matrix-bg' + +// Approval Modal (Phase 17 UI/UX 修復) +export { ApprovalModal } from './approval-modal'