Skip to content

Commit 01360cd

Browse files
Polish candidate and action section visuals
1 parent 9c83558 commit 01360cd

2 files changed

Lines changed: 65 additions & 29 deletions

File tree

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,22 @@
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 and Action Section Visual Polish
18+
19+
### Changed
20+
21+
- Added a shared candidate source badge component.
22+
- Unified source badge styling across compact candidate preview, full candidate cards, and selected candidate context.
23+
- Refined candidate card visual hierarchy.
24+
- Refined selected-candidate context in the Action Panel.
25+
- Preserved candidate decision workflow, action log preview, local action trail, queue controls, evidence triage, and persistence behavior.
26+
27+
### Design Notes
28+
29+
- This milestone improves visual consistency across candidate-related workflow areas.
30+
- Candidate evidence remains review support, not final reconciliation authority.
31+
- The workbench continues to move toward a Salt-inspired institutional finance UI.
32+
1733
## 2026-05-30 — Candidate Evidence Layout Cleanup
1834

1935
### Changed

frontend/components/BreakResolutionWorkbench.tsx

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

771+
function candidateSourceClass(source: Candidate["source"]) {
772+
if (source === "Splink") {
773+
return "bg-blue-50 text-blue-700 ring-blue-200";
774+
}
775+
776+
if (source === "Split-payment") {
777+
return "bg-amber-50 text-amber-700 ring-amber-200";
778+
}
779+
780+
return "bg-slate-100 text-slate-700 ring-slate-200";
781+
}
782+
783+
function CandidateSourceBadge({ source }: { source: Candidate["source"] }) {
784+
return (
785+
<span
786+
className={`rounded-full px-2.5 py-1 text-xs font-bold ring-1 ${candidateSourceClass(
787+
source,
788+
)}`}
789+
>
790+
{source}
791+
</span>
792+
);
793+
}
794+
771795
function CompactCandidatePreview({
772796
candidates,
773797
onViewFullReview,
@@ -786,7 +810,7 @@ function CompactCandidatePreview({
786810
Candidate evidence
787811
</div>
788812
<div className="mt-1 text-sm font-semibold text-blue-900">
789-
Candidate hypotheses are available for this break.
813+
Candidate hypotheses are available for review.
790814
</div>
791815
</div>
792816
<div className="text-xs font-bold text-blue-700">
@@ -801,9 +825,7 @@ function CompactCandidatePreview({
801825
className="rounded-xl border border-blue-100 bg-white p-3"
802826
>
803827
<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>
828+
<CandidateSourceBadge source={candidate.source} />
807829
<span className="text-xs font-bold text-slate-500">
808830
Confidence {candidate.confidence}
809831
</span>
@@ -817,8 +839,7 @@ function CompactCandidatePreview({
817839

818840
<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">
819841
<div>
820-
Candidate evidence is shown here as a preview. Use the full candidate review section
821-
to stage Review, Accept, or Reject actions.
842+
This preview surfaces candidate evidence early. Use the full candidate review section to stage Review, Accept, or Reject actions.
822843
</div>
823844
<button
824845
type="button"
@@ -841,31 +862,29 @@ function CandidateCard({
841862
selectedDecision: CandidateDecision | null;
842863
onDecision: (action: CandidateDecision["action"]) => void;
843864
}) {
844-
const sourceStyle =
845-
candidate.source === "Splink"
846-
? "bg-blue-50 text-blue-700 ring-blue-200"
847-
: candidate.source === "Split-payment"
848-
? "bg-amber-50 text-amber-700 ring-amber-200"
849-
: "bg-slate-100 text-slate-700 ring-slate-200";
850-
851865
return (
852866
<div
853867
className={`rounded-2xl border p-4 transition ${
854868
selectedDecision
855869
? "border-blue-300 bg-blue-50/60 ring-2 ring-blue-100"
856-
: "border-slate-200 bg-slate-50"
870+
: "border-slate-200 bg-white"
857871
}`}
858872
>
859873
<div className="flex items-center justify-between gap-3">
860-
<span className={`rounded-full px-2.5 py-1 text-xs font-bold ring-1 ${sourceStyle}`}>
861-
{candidate.source}
862-
</span>
874+
<CandidateSourceBadge source={candidate.source} />
863875
<span className="text-xs font-bold uppercase tracking-[0.14em] text-slate-400">
864876
Review only
865877
</span>
866878
</div>
867879

868-
<div className="mt-4 text-2xl font-black">{candidate.confidence}</div>
880+
<div className="mt-4 flex items-end justify-between gap-3">
881+
<div>
882+
<div className="text-xs font-bold uppercase tracking-[0.14em] text-slate-400">
883+
Confidence
884+
</div>
885+
<div className="mt-1 text-2xl font-black">{candidate.confidence}</div>
886+
</div>
887+
</div>
869888
<p className="mt-3 text-sm leading-6 text-slate-600">{candidate.rationale}</p>
870889

871890
<div className="mt-4 rounded-xl border border-slate-200 bg-white p-3 text-xs leading-5 text-slate-500">
@@ -1637,26 +1656,27 @@ export default function BreakResolutionWorkbench() {
16371656
</div>
16381657

16391658
{candidateDecision ? (
1640-
<div className="mt-4 rounded-xl border border-blue-200 bg-blue-50 p-3 text-sm leading-5 text-blue-800">
1641-
<div className="text-xs font-bold uppercase tracking-[0.16em] text-blue-600">
1642-
Selected candidate
1643-
</div>
1644-
<div className="mt-2 grid gap-1">
1645-
<div className="flex justify-between gap-3">
1646-
<span>Source</span>
1647-
<span className="font-bold">{candidateDecision.source}</span>
1659+
<div className="mt-4 rounded-xl border border-blue-200 bg-blue-50/70 p-3 text-sm leading-5 text-blue-800">
1660+
<div className="flex items-center justify-between gap-3">
1661+
<div className="text-xs font-bold uppercase tracking-[0.16em] text-blue-600">
1662+
Selected candidate
16481663
</div>
1664+
<CandidateSourceBadge source={candidateDecision.source} />
1665+
</div>
1666+
1667+
<div className="mt-3 grid gap-2 text-xs">
16491668
<div className="flex justify-between gap-3">
1650-
<span>Action</span>
1669+
<span className="text-blue-700">Action</span>
16511670
<span className="font-bold">{candidateDecision.action}</span>
16521671
</div>
16531672
<div className="flex justify-between gap-3">
1654-
<span>Confidence</span>
1673+
<span className="text-blue-700">Confidence</span>
16551674
<span className="font-bold">{candidateDecision.confidence}</span>
16561675
</div>
16571676
</div>
1677+
16581678
<p className="mt-3 text-xs leading-5 text-blue-700">
1659-
Candidate decisions are staged as analyst actions. They do not automatically
1679+
Candidate decisions are staged as analyst actions and do not automatically
16601680
confirm reconciliation.
16611681
</p>
16621682
</div>

0 commit comments

Comments
 (0)