Visual comp v2 · anchored to stage7-direction2-drawer

The agreed Direction-2 drawer — realized in your real design system, with the shipped drift fixed.

Same tokens as the app (Inter · primary hsl(221 83% 53%) · slate-900 nav · real Button/Badge/Sheet). This is the comp we agreed on before implementation — the build shipped a drifted version. Each pin marks where the shipped UI broke from this and how the comp restores it. Sample filter throughout: CA/TX licensed · Life · (email “agency” OR has phone) → 12,431.

anchor: stage7-direction2-drawer 1 correctness bug (seeding) 9 visual drifts ~1,235 lines dead code
View
Pins map each fix to the shipped issue it resolves. Toggle “Clean” for the bare comp.
1 The list — drawer closed

Left rail gone → full-width table. One toolbar row, “Edit filters” the clear primary. Applied filters read as removable field · value chips you can actually read.

1
2
3

Agents

12,431 agents Edit filters Save segment Segments
Filters Licensed in CA, TX License Life Any of email ~ “agency” · has phone + Quick add Clear all
FirstLastPhoneEmailLic. StateCategorySource
MariaAlvarez(305) 555-0142m.alvarez@agency…CALifeFLDI
JamesBell(214) 555-0190jbell@bell-ins…TXLifeMATT_TX
AishaKhan(415) 555-0177aisha@agency…CALifeFLDI
DevonPierce(512) 555-0123devon.p@…TXLifeIADI
Showing 1–50 of 12,431
2 The builder drawer — opened on your applied filters

Source-aware field picker, an ALL/ANY tree with single-line conditions and inline NOT, a plain-language preview and the live match count beside Apply. Opens seeded with what’s applied — never empty.

Agents

12,431 agentsEdit filters
5
8
6
7
9
4
10
+ Add a filter — search 60+ fields…
Geography
Licensed statemulti
Residence statemulti
Area code → statenew
Licensing
License category
License yearn/a · 572k
NPNn/a · 528k
Demographics
Ethnicity inferred
Gender inferred
Source & quality
Data source16 sources
⑩ Source-aware field picker

Clicking Add a filter opens a searchable, categorized list. Multi-source fields are tagged multi; inferred fields labelled inferred; gap fields show how many agents have no value (n/a · 572k) so you’re never silently misled. Data source lists all 16 (the shipped build showed ~3), and the new area-code → state field is parked here for Phase B.

3 Each pin — shipped issue → how the comp fixes it
1
“Edit / Add filters” were the faintest things on the page, split across two ghost rows
One toolbar row; Edit filters is the blue primary, Save segment / Segments beside it.
2
Chips truncated mid-word (“…is any of LIFE INCL …”)
Readable field · value chips (“Licensed in CA, TX”); compound group → one purple chip.
3
Preset name truncated; “Save Preset / Presets” split from filtering
First-class Save segment / Segments actions with room to breathe.
4
Footer clustered far-right; “Filter breakdown” heavier than Apply; live count collided with the ✕
Count + plain-language live in the footer; Apply filters is the only solid button, breakdown/clear are quiet ghosts.
5
BUG: drawer opened EMPTY, silently dropping your applied filter
Drawer seeds your applied filters on open (green confirm strip).
6
Every new condition defaulted to “Email contains” → identical stub rows
Single-line conditions with the real field · operator · value.
7
A floating “NOT” pill on its own line above every row
NOT is a compact inline prefix on the condition (“NOT Phone is empty”).
8
Group header crammed “ALL · ANY · (AND) · NOT group”, redundant + low-contrast
One Match ALL / ANY ▾ dropdown per group; OR badge on nested groups. No “(AND)”.
9
No plain-language preview surfaced reliably
Persistent “In plain language” readback above the actions.
10
Data Source showed ~3 of 16; gap fields gave no source signal
Source-aware picker: all 16 sources, inferred / n/a · count tags, area-code→state.
11
Palette mishmash: indigo / rose / amber / emerald / violet hardcoded
Your token system only — Inter, --primary blue, slate neutrals, semantic accents.
12
~1,235 lines of dead filter code shipped to prod
Delete filter-sidebar + advanced-filter-drawer + base-filter-summary.
4 Shipped vs comp — the three worst drifts

The “shipped” side is the live build recreated in the same tokens, so the contrast is apples-to-apples.

Footer — shipped

Clear allFilter breakdownApply
Three actions jammed right; left ~60% dead. “Filter breakdown” is the heaviest text on screen — louder than the primary.

Footer — comp

12,431 match Filter breakdownApply filters
Live count anchors the left; Apply is the only solid button on the right; breakdown is a quiet ghost. The preview sits above it.

Condition rows — shipped

NOT
Email · Identitycontains
e.g. @agency, gmail.com
NOT
Email · Identitycontains
e.g. @agency, gmail.com
New rows default to “Email contains”, stacking up byte-identical; a bare “NOT” floats on its own line above each.

Condition rows — comp

Licensed stateis one ofCA, TX
NOTPhoneis empty
One dense line per condition — real field, operator, value — with NOT as a compact inline prefix.

Chips — shipped

License type is any of LIFE INCL … Carrier type is any of cell Data source is any of FLDI…
Verbose “is any of …” eats the width then truncates mid-word — the chip hides the value it represents.

Chips — comp

Licensed in CA, TX License Life Any of email ~ “agency” · has phone
Field · value, properly cased; a compound OR group collapses to one purple chip you can still read.
5 Complete issues ledger — every finding (review · blind · emil)

The full record so nothing is lost. In comp = shown above · Build-time = implement during the build (state / motion / cleanup) · Out of drawer = agents-page / table / global, tracked separately.

In comp 19 Build-time 6 Out of drawer 6
PinAreaFinding (shipped build)Status
5CorrectnessDrawer opened empty — silently dropped the applied filter (P0 data loss)In comp
1Filter barEdit / Add filters were the faintest things on the page, split across two ghost rowsIn comp
2Filter barChips truncated mid-word; verbose “is any of …”, lowercased valuesIn comp
3Filter barActive preset name truncated; “Save Preset / Presets” split from filteringIn comp
1Filter barFragile wrapping — “Edit filters” orphaned onto its own rowIn comp
Filter bar“Clear all” shown at rest with nothing to clearBuild-time
4Drawer footerActions clustered far-right; “Filter breakdown” heavier than Apply; Clear flush to Apply (misclick)In comp
4Drawer headerLive count collided with the ✕; showed unfiltered 1.6M, not the draftIn comp
9Drawer footerPlain-language preview not reliably surfacedIn comp
§6Drawer footerApply stayed enabled in the empty / invalid stateBuild-time
6ConditionsNew rows defaulted to “Email contains” → byte-identical stub rowsIn comp
7ConditionsFloating “NOT” pill on its own line above every rowIn comp
7ConditionsTwo undifferentiated “NOT”s — per-condition vs “NOT group”In comp
8GroupsHeader crammed ALL · ANY · (AND); redundant; weak toggle statesIn comp
ConditionsThree inconsistent “add” affordances (condition / OR group / group)In comp
8GroupsOR divider too weak for a load-bearing operatorIn comp
B/AConditionsMalformed placeholder “@agency, gmail.com”In comp
10Field pickerDropdown overlapped condition rows, weak separationIn comp
Field pickerPermanent blue focus-ring even when unfocusedBuild-time
10Fields / dataData Source showed ~3 of 16; gap fields gave no source signalIn comp
11SystemPalette mishmash — indigo / rose / amber / emerald / violet hardcodedIn comp
System10–12px micro-typography legibility throughout the builderBuild-time
12Code~1,235 lines of dead filter code shipped to prod (3 files)In comp
CodeUnused Badge import in active-filters-barBuild-time
§6MotionOrigin-aware popovers · press feedback · real disabled/loading states · <300ms easing · reduced-motionBuild-time
TableCarrier “Unknown” loud solid pill, inconsistent with Cell / VoIP / N-VOut of drawer
Presets popoverEvery row tagged “Shared” while the Mine tab is active — redundantOut of drawer
Presets popoverLow-contrast metadata; descriptions truncate mid-sentenceOut of drawer
Presets popover“AI suggestions” row clipped at the popover’s bottom edgeOut of drawer
Global headerBell badges “99+” / “9+” crowd and overlap their iconsOut of drawer
TableEmail column truncates mid-address, hiding the domainOut of drawer
6 Interaction & motion — build-time (emil pass)

A static comp can’t render motion; these are required at build time, per the emil review.

Origin-aware popovers

The field picker & value popovers scale from their trigger (Radix transform-origin), not from center.

Press feedback

scale(.97) on Apply, chips and pressable rows — instant “it heard me”, ~120–160ms ease-out.

Real disabled & loading states

Apply disabled until the draft differs & is valid; count shows “Counting…”; option lists show a loading row.

Timing & easing

Drawer ~240ms ease-drawer; popovers ~160ms ease-out; everything <300ms; honor prefers-reduced-motion.

Apply states Apply filters enabled — draft changed Apply filters disabled — no change / invalid Counting…
How to read this. Static comp on your real tokens — not wired to data. It reproduces the agreed stage7-direction2-drawer and folds in the audit fixes (pins 4–9 are where the shipped build drifted; pin 5 is the data-loss bug).