import { useEffect, useState } from 'react'; import { useAI } from '../hooks/useAI'; import { markdownToHtml } from '../lib/markdown'; export interface ModalIssue { title: string; severity: string; wcag?: string; selector?: string; element?: string; description: string; count?: number; ai_fixable?: boolean; help_url?: string; } interface Props { issue: ModalIssue | null; onClose: () => void; } /** Renders AI response with full markdown formatting. */ function AiSuggestion({ text }: { text: string }) { return (

Suggested fix

AI suggestions are based on automated analysis. Please review before applying.

); } export default function IssueDetailModal({ issue, onClose }: Props) { const { run, hasProvider } = useAI(); const [aiOutput, setAiOutput] = useState(null); const [aiError, setAiError] = useState(null); const [activeAction, setActiveAction] = useState(null); // Reset AI state when switching issues useEffect(() => { setAiOutput(null); setAiError(null); }, [issue?.title, issue?.selector]); // Scroll lock + Escape key useEffect(() => { if (!issue) return; const prev = document.body.style.overflow; document.body.style.overflow = 'hidden'; const handler = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); }; document.addEventListener('keydown', handler); return () => { document.body.style.overflow = prev; document.removeEventListener('keydown', handler); }; }, [issue, onClose]); if (!issue) return null; const sevColor = issue.severity === 'critical' ? '#ef4444' : issue.severity === 'warning' ? '#f59e0b' : '#3b82f6'; const callAI = async (task: string) => { setAiOutput(null); setAiError(null); setActiveAction(task); try { const result = await run.mutateAsync({ task, params: { title: issue.title, wcag: issue.wcag ?? '', html: issue.element ?? '', context: issue.description, }, }); if (result.error) setAiError(result.error); else setAiOutput(result.text ?? ''); } catch (e) { setAiError((e as Error).message); } finally { setActiveAction(null); } }; return (
e.stopPropagation()} > {/* Top border accent + header */}
{issue.severity} {issue.wcag && WCAG {issue.wcag}}
{/* Scrollable body */}

{issue.title}

{issue.description}

This issue may affect accessibility for some users and should be reviewed.

{(issue.selector || issue.count !== undefined) && (
{issue.selector && ( <>
Selector
{issue.selector}
)} {issue.count !== undefined && ( <>
Instances
{issue.count}
)}
)} {issue.element && (

Affected element

{issue.element}
)} {issue.help_url && ( {issue.wcag ? `WCAG ${issue.wcag} — ` : ''}View guidance ↗ )} {/* AI actions */}
{!hasProvider && (

Configure an AI provider in Settings to enable fix suggestions.

)} {aiError &&

{aiError}

} {aiOutput !== null && !aiError && }
); }