51 lines
1.9 KiB
TypeScript
51 lines
1.9 KiB
TypeScript
import { useState } from 'react';
|
|
import { ChevronDown, TriangleAlert, X } from 'lucide-react';
|
|
import type { AppDiagnostic } from '../../stores/useAppStore';
|
|
import { IconButton } from '../../components/ui';
|
|
export function DiagnosticNotice({
|
|
value,
|
|
onClose,
|
|
}: {
|
|
value: AppDiagnostic;
|
|
onClose: () => void;
|
|
}) {
|
|
const [expanded, setExpanded] = useState(false);
|
|
return (
|
|
<section
|
|
role="alert"
|
|
className="absolute bottom-4 left-1/2 z-30 w-[min(42rem,calc(100%-2rem))] -translate-x-1/2 overflow-hidden rounded-xl border border-danger-border bg-panel shadow-2xl"
|
|
>
|
|
<div className="flex items-start gap-3 p-3">
|
|
<span className="mt-0.5 grid h-7 w-7 shrink-0 place-items-center rounded-full bg-danger-soft text-danger">
|
|
<TriangleAlert className="h-4 w-4" />
|
|
</span>
|
|
<div className="min-w-0 flex-1">
|
|
<h2 className="text-sm font-semibold text-text-primary">{value.summary}</h2>
|
|
{value.path && (
|
|
<p className="mt-0.5 break-all text-xs text-text-tertiary" title={value.path}>
|
|
路径:{value.path}
|
|
</p>
|
|
)}
|
|
<button
|
|
type="button"
|
|
aria-expanded={expanded}
|
|
className="mt-1 flex items-center gap-1 text-xs text-danger hover:underline"
|
|
onClick={() => setExpanded((v) => !v)}
|
|
>
|
|
技术详情
|
|
<ChevronDown className={`h-3 w-3 ${expanded ? 'rotate-180' : ''}`} />
|
|
</button>
|
|
</div>
|
|
<IconButton aria-label="关闭错误" tooltip="关闭" onClick={onClose}>
|
|
<X className="h-4 w-4" />
|
|
</IconButton>
|
|
</div>
|
|
{expanded && (
|
|
<pre className="max-h-36 overflow-auto whitespace-pre-wrap break-words border-t border-danger-border bg-danger-soft p-3 text-xs text-danger">
|
|
{value.detail}
|
|
</pre>
|
|
)}
|
|
</section>
|
|
);
|
|
}
|