Spaces:
Sleeping
Sleeping
| import { useEffect, useRef } from "react"; | |
| import { X } from "lucide-react"; | |
| import type { PolicySection } from "../types"; | |
| // Side drawer (mirrors AuditHistory) that doubles as the acronym glossary + full policy reference. | |
| // Cited rule IDs in the decision card link here via `focusRule`, which scrolls to and highlights | |
| // the matching rule row with the gold "seal" accent. | |
| export function PolicyReference({ | |
| sections, | |
| focusRule, | |
| onClose, | |
| }: { | |
| sections: PolicySection[]; | |
| focusRule: string | null; | |
| onClose: () => void; | |
| }) { | |
| const rowRefs = useRef<Record<string, HTMLDivElement | null>>({}); | |
| useEffect(() => { | |
| if (focusRule) rowRefs.current[focusRule]?.scrollIntoView({ block: "center" }); | |
| }, [focusRule, sections]); | |
| return ( | |
| <aside className="w-80 shrink-0 border-l border-line bg-surface overflow-y-auto"> | |
| <div className="flex items-center justify-between px-4 py-3 border-b border-line sticky top-0 bg-surface"> | |
| <span className="text-xs font-semibold uppercase tracking-wide text-faint"> | |
| Policy reference | |
| </span> | |
| <button onClick={onClose} className="text-faint hover:text-heading"> | |
| <X size={16} /> | |
| </button> | |
| </div> | |
| {sections.length === 0 && ( | |
| <div className="p-4 text-sm text-faint">Policy not loaded.</div> | |
| )} | |
| <div className="divide-y divide-line"> | |
| {sections.map((sec) => ( | |
| <section key={sec.prefix} className="px-4 py-3"> | |
| <div className="flex items-center gap-2"> | |
| <span className="font-mono text-xs font-semibold bg-accent-soft text-accent-on rounded px-1.5 py-0.5"> | |
| {sec.prefix} | |
| </span> | |
| <span className="text-sm font-semibold text-heading">{sec.name}</span> | |
| </div> | |
| <p className="text-xs text-muted mt-1">{sec.description}</p> | |
| <div className="mt-2 space-y-1.5"> | |
| {sec.rules.map((rule) => { | |
| const focused = rule.rule_id === focusRule; | |
| return ( | |
| <div | |
| key={rule.rule_id} | |
| ref={(el) => { | |
| rowRefs.current[rule.rule_id] = el; | |
| }} | |
| className={`rounded-lg border px-3 py-2 text-sm transition ${ | |
| focused ? "border-gold ring-2 ring-gold/40 bg-gold-soft/50" : "border-line" | |
| }`} | |
| > | |
| <span className="font-mono text-xs font-semibold text-accent">{rule.rule_id}</span> | |
| <p className="text-body mt-0.5">{rule.text}</p> | |
| </div> | |
| ); | |
| })} | |
| </div> | |
| </section> | |
| ))} | |
| </div> | |
| </aside> | |
| ); | |
| } | |