Skip to content

Commit 9c83558

Browse files
Clean up candidate evidence layout
1 parent 68c3a06 commit 9c83558

2 files changed

Lines changed: 89 additions & 45 deletions

File tree

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,21 @@
1414
- The alpha now demonstrates priority queue, evidence triage, candidate review, action guardrails, local action trail, browser-local persistence, export, and reset controls.
1515
- The workbench is suitable for portfolio demonstration but remains non-production software.
1616

17+
## 2026-05-30 — Candidate Evidence Layout Cleanup
18+
19+
### Changed
20+
21+
- Reworked the active break candidate preview into a compact candidate evidence summary.
22+
- Kept full candidate Review / Accept / Reject actions in the Related Candidate Evidence section.
23+
- Added an "Open full candidate review" control from the compact preview to the full candidate section.
24+
- Preserved the Action Panel "View candidate evidence" shortcut, candidate decision guardrails, action log preview, local action trail, queue controls, and evidence review workflow.
25+
26+
### Design Notes
27+
28+
- This milestone reduces duplicate candidate decision controls in the center and bottom sections.
29+
- The center panel now surfaces candidate evidence as a preview, while the bottom section remains the full candidate decision area.
30+
- This improves information hierarchy without changing reconciliation logic.
31+
1732
## 2026-05-30 — Action Panel Density and Hierarchy Polish
1833

1934
### Changed

frontend/components/BreakResolutionWorkbench.tsx

Lines changed: 74 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,70 @@ function candidateDecisionGuardrail(action: CandidateDecision["action"]) {
768768
};
769769
}
770770

771+
function CompactCandidatePreview({
772+
candidates,
773+
onViewFullReview,
774+
}: {
775+
candidates: Candidate[];
776+
onViewFullReview: () => void;
777+
}) {
778+
return (
779+
<div
780+
id="candidate-evidence-preview"
781+
className="mb-5 rounded-2xl border border-blue-200 bg-blue-50/60 p-4"
782+
>
783+
<div className="mb-3 flex flex-col gap-2 lg:flex-row lg:items-end lg:justify-between">
784+
<div>
785+
<div className="text-xs font-bold uppercase tracking-[0.18em] text-blue-700">
786+
Candidate evidence
787+
</div>
788+
<div className="mt-1 text-sm font-semibold text-blue-900">
789+
Candidate hypotheses are available for this break.
790+
</div>
791+
</div>
792+
<div className="text-xs font-bold text-blue-700">
793+
{candidates.length} candidate source(s)
794+
</div>
795+
</div>
796+
797+
<div className="grid gap-3 lg:grid-cols-2">
798+
{candidates.slice(0, 2).map((candidate) => (
799+
<div
800+
key={`compact-${candidate.source}`}
801+
className="rounded-xl border border-blue-100 bg-white p-3"
802+
>
803+
<div className="flex items-center justify-between gap-3">
804+
<span className="rounded-full bg-blue-50 px-2.5 py-1 text-xs font-bold text-blue-700 ring-1 ring-blue-200">
805+
{candidate.source}
806+
</span>
807+
<span className="text-xs font-bold text-slate-500">
808+
Confidence {candidate.confidence}
809+
</span>
810+
</div>
811+
<p className="mt-3 text-xs leading-5 text-slate-600">
812+
{candidate.rationale}
813+
</p>
814+
</div>
815+
))}
816+
</div>
817+
818+
<div className="mt-3 flex flex-col gap-2 rounded-xl border border-blue-100 bg-white p-3 text-xs leading-5 text-slate-600">
819+
<div>
820+
Candidate evidence is shown here as a preview. Use the full candidate review section
821+
to stage Review, Accept, or Reject actions.
822+
</div>
823+
<button
824+
type="button"
825+
onClick={onViewFullReview}
826+
className="w-fit rounded-full bg-blue-700 px-3 py-1.5 text-xs font-bold text-white"
827+
>
828+
Open full candidate review
829+
</button>
830+
</div>
831+
</div>
832+
);
833+
}
834+
771835
function CandidateCard({
772836
candidate,
773837
selectedDecision,
@@ -1341,6 +1405,12 @@ export default function BreakResolutionWorkbench() {
13411405
?.scrollIntoView({ behavior: "smooth", block: "start" });
13421406
}
13431407

1408+
function scrollToFullCandidateReview() {
1409+
document
1410+
.getElementById("related-candidate-evidence")
1411+
?.scrollIntoView({ behavior: "smooth", block: "start" });
1412+
}
1413+
13441414
const displayedRecommendedAction =
13451415
selectedPacket?.summary?.recommendedAction ?? selectedBreak.recommendedAction;
13461416
const displayedReason = selectedPacket?.summary?.reason ?? selectedBreak.reason;
@@ -1537,51 +1607,10 @@ export default function BreakResolutionWorkbench() {
15371607
/>
15381608

15391609
{relatedCandidates.length > 0 ? (
1540-
<div
1541-
id="candidate-evidence-preview"
1542-
className="mb-5 rounded-2xl border border-blue-200 bg-blue-50/60 p-4"
1543-
>
1544-
<div className="mb-3 flex flex-col gap-2 lg:flex-row lg:items-end lg:justify-between">
1545-
<div>
1546-
<div className="text-xs font-bold uppercase tracking-[0.18em] text-blue-700">
1547-
Candidate evidence
1548-
</div>
1549-
<div className="mt-1 text-sm font-semibold text-blue-900">
1550-
Review candidate hypotheses before staging a candidate decision.
1551-
</div>
1552-
</div>
1553-
<div className="text-xs font-bold text-blue-700">
1554-
{relatedCandidates.length} candidate source(s)
1555-
</div>
1556-
</div>
1557-
1558-
<div className="grid gap-3 lg:grid-cols-2">
1559-
{relatedCandidates.slice(0, 2).map((candidate) => (
1560-
<CandidateCard
1561-
key={`preview-${candidate.source}`}
1562-
candidate={candidate}
1563-
selectedDecision={
1564-
candidateDecision?.source === candidate.source
1565-
? candidateDecision
1566-
: null
1567-
}
1568-
onDecision={(action) => {
1569-
const nextCandidateDecision = {
1570-
source: candidate.source,
1571-
action,
1572-
confidence: candidate.confidence,
1573-
rationale: candidate.rationale,
1574-
};
1575-
1576-
setCandidateDecision(nextCandidateDecision);
1577-
setAnalystNote("");
1578-
setDecision(`${action} ${candidate.source} candidate`);
1579-
setDecisionTimestamp(new Date().toISOString());
1580-
}}
1581-
/>
1582-
))}
1583-
</div>
1584-
</div>
1610+
<CompactCandidatePreview
1611+
candidates={relatedCandidates}
1612+
onViewFullReview={scrollToFullCandidateReview}
1613+
/>
15851614
) : null}
15861615

15871616
<EvidenceComparison fields={evidenceFields} />

0 commit comments

Comments
 (0)