Skip to content

Design pass: WS6 Clean — dataset select, review pair, primer, suggestions, save states - #280

Merged
jdpigeon merged 5 commits into
mainfrom
design/ws6-clean
Sep 27, 2026
Merged

jdpigeon merged 5 commits into
mainfrom
design/ws6-clean

Conversation

@jdpigeon

@jdpigeon jdpigeon commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Design pass for Workstream 6 (Clean), following docs/uxr/2026-09-25-ws6-design-brief.md (copied into this branch) and plan §1.5, §8, §10.2 "Clean" and §11 WS6. This is Storybook only; runtime behavior does not change. Engineering integrates after approval. CleanComponent/*, CleanContainer, the epics, the worker and utils.py are unchanged. No shared files are touched at all this round — everything lives in src/renderer/components/Clean/.

Round 2 applies the product feedback: cleaning is now single-recording, and the review layout was rebuilt so the Epochs panel fills the screen.

Round 2+3 changes (product feedback)

  1. Single recording only (round 2). DatasetSelect and DatasetSelectWithIncomplete are single-select radio rows (no checkboxes), the "you can pick more than one" copy is gone, the rail shows one recording, and the selected prop is string | null — nothing models a multi-recording selection anywhere. Integration note: Clean must be single-recording; the current CleanComponent's multi-file LoadEpochs must be restricted to one file at integration. (A flagged sensor belongs to one recording, so the bad-channel feature can't work across a multi-file load.)
  2. The reviewer and the Live ERP both got real room (rounds 2–3). The Epochs panel is tall again and the Live ERP is legible:
1280×720 1366×768 round 1
Epochs panel canvas 571×285 643×322 448×224 (~230px tall)
Live ERP pane (card) 440×224 440×224 448×224 side panel
Live ERP canvas 387×145 387×145 448×168

Layout: rail (left) | Epochs (top, full height of its row) with the primer panel docked beside it | bottom row: Live ERP card + auto-flag suggestions card. The Live ERP keeps its channel selector, time axis, condition legend and "Averaged over N epochs" caption at ~0.6 scale (2× the round-2 thumbnail). Suggestions sit next to the Live ERP they feed, in a wide card where nothing truncates.
3. The primer never covers the reviewer (round 3). The step card is docked in a panel beside the Epochs panel (outside the canvas), so it can never hide trials or the Prev/Next controls; the pointer chips may overlap the canvas edge. Collapsed, the panel teaches the whole loop (§8.1 definition + the five §8.2 steps) and stays available; expanded, it walks through the steps one at a time (the walkthrough idiom from Analyze) with gold pips and Back/Next/Finish.
4. Nothing truncates in the rail (round 3): the dataset is stacked (subject / full filename), suggestions and the primer moved out of the rail, and the save actions are stacked vertically with Save cleaned dataset & analyze as the one filled primary.

  1. The suggestions card only renders when it's relevant (round 4): only when there is at least one suggestion to review or an accepted suggestion to restore (AutoFlagSuggestions, ReviewWithSelections). The "No suggestions yet" empty state is gone, and when the card is absent the Live ERP takes the full bottom row (a full-width Live ERP band, chart centered). Chosen over "the Epochs panel grows" because the freed space is horizontal in the bottom row: the Epochs row's height is budgeted by the Live ERP's 224px row, and shrinking that row would drop the ERP below the ~340×200 legibility floor. Keeping both panes' dimensions identical across states also means nothing resizes when suggestions arrive.

Why this geometry

The real EpochReviewer draws in a fixed 640×426 box and LiveErpPane in 640×344. A full-width Epochs panel fills the working area's height only when it takes almost all the width (the aspects match), which starves the Live ERP; any side column makes the reviewer width-bound and leaves dead space. The chosen split budgets the row heights so both panes hit their targets with no empty regions: the Epochs row fills its box at both sizes (285/322px tall), and the 224px bottom row is exactly what the Live ERP needs to be ≥340×200 and legible. FitPane (story-only, ResizeObserver zoom) scales the real components; integration should make the panes resize-aware and drop it.

The real components rendered

Yes — the real EpochReviewer and the real LiveErpPane render in these stories, unmodified, wrapped only in FitPane (a story-only scaler). Both are pure-props components (no Redux, no worker, no electronAPI); the story harness holds their state (rejected, badChannels, toggles) and feeds them EXAMPLE_EPOCH_ARRAYS from Analyze/fixtures.ts — the same example epochs Analyze's walkthrough uses. No second epoch generator exists; the panes run the app's own downsampleMinMax / epochChannelSeries / meanTrace.

Actions and confirmations

  • Renamed to describe their effect (§8.3): Apply exclusions & save → Apply exclusions; Auto-flag artifacts → Suggest noisy trials. Start cleaning, ← Pick different data, Save cleaned dataset & analyze, Go to Analyze → kept.
  • Confirmations restyled as in-app shadcn Dialogs with the existing wording and button contract (reject-all wins over everything; remove-selected before saving a selection; apply-bad-channels before analysis; the "more than one bad channel on a 4-channel recording" caution). The reject-all confirm is destructive styled. Storybook has no electronAPI.showMessageBox, so the dialog is the restyled version for integration to adopt.
  • Auto-flag suggestions are not auto-applied (today's CleanComponent silently adds them to the rejected set); they wait for Accept/Restore, and the counts say "(4 by you, 1 suggested)". See open questions.

Measurements (round 3)

Every story loaded in Chromium at both sizes; every story's own copy was asserted in the DOM before its capture (raw numbers in /tmp/ws6-design/measurements.json):

  • Document scroll: 0 · Horizontal overflow: 0 · AppShell headers: 1 · Console errors: 0 · Scrolling elements inside the story root: none — the rail never overflows at either size, including the suggestion states.
  • Epochs panel canvas: 571×285 at 1280×720, 643×322 at 1366×768 (original ~230px tall → +24% / +40%).
  • Live ERP pane: 440×224 at both sizes (canvas 387×145) — ≥340×200 with readable axis, legend and caption.
  • Rule A (review family, both sizes): reviewer, Live ERP, rail and the current instruction (primer panel and suggestion card) are all visible with no page scroll; nothing overlaps the reviewer's canvas except the pointer callouts.

Review agenda

Domain/Clean, all rendered in the real AppShell (location="clean", workspace Faces_Houses_3, truthful badges and Next), fixture data only:

  • Selection (single-recording): DatasetSelect (radio rows, one primary Start cleaning) · DatasetSelectWithIncomplete (hidden by default — "2 ended-early recordings hidden · Show"; revealed rows are badge-marked "Ended early", not selectable, with a confirmed destructive Delete) — interactive captures for the revealed and delete-confirm states ship alongside
  • Review: Review (full-area Epochs + Live ERP rail + collapsed primer bar) · Primer (step 1 card overlaid near its pointer target, chip pointing at the trial columns) · ReviewWithSelections (4 trials out + 1 accepted suggestion, AF7 flagged, Live ERP recomputed to 75 trials, counts in words) · AutoFlagSuggestions (3 suggestion rows: 1 accepted with ✓ Left out · Restore, 2 with Accept)
  • States: Loading (explicit) · NoEpochs (why + what to do) · Saving · SaveFailed (Try again) · Saved (Go to Analyze →, shell Next flips to Analyze)
  • Confirmations: ConfirmRejectAll (destructive) · ConfirmDropChannels
  • Behavior-only note (not a story): confirmed — WorkflowNav's AREAS maps behavior-only workspaces to ['prepare', 'collect', 'analyze'], so there is no Clean area to design.

Open questions

  • Suggestions should not auto-apply? These stories treat auto-flag output as suggestions the student accepts one by one. Today CleanComponent adds every suggestion straight to the rejected set. Which behavior does product want?
  • The Live ERP is small in the rail (160×60). That is the price of a full-area reviewer with the real fixed-size panes. Acceptable, or should integration make LiveErpPane responsive and give it more room (e.g. a collapsible panel or a hover-zoom)?
  • Delete for ended-early recordings lives in Clean's picker here (per the brief) but is arguably Collect's job. Keep or move?
  • The primer's step-3 chip points at the rail's auto-flag/suggestions block; confirm that's the right target once the suggestions placement is approved.
  • "Save cleaned dataset & analyze" also saves, like today. With Apply exclusions as the in-place save, is the two-button pair clear enough?

Constraints not met, and notes for integration

  • Suggested trials are not highlighted inside the canvas (EpochReviewer can't be edited in a design pass); distinction is carried by the suggestion rows and the counts in words. Integration could give EpochReviewer a suggested prop.
  • The remove-selected and apply-bad-channels confirmations exist in the components and are reachable interactively (click Save with a selection; flag a second sensor), but the brief's story table names only ConfirmRejectAll / ConfirmDropChannels, so they have no dedicated story.
  • The real panes' own microcopy still says "epochs"/"marked for rejection" (unchanged components); the new copy says "trials" per the plan's student-facing language.
  • FitPane scales the real panes with zoom (Chromium-standard, fine in Electron) instead of making them responsive. Integration should ideally give EpochReviewer/LiveErpPane resize-aware drawing and drop FitPane.
  • The threshold slider and Suggest noisy trials change fixture state only; no Pyodide dispatch.

Verification

  • npx tsc --noEmit: 0 errors.
  • All 13 stories screenshotted at 1366×768 and 1280×720 (26 PNGs) plus 4 interaction captures (incomplete revealed + delete confirm, both sizes) in /tmp/ws6-design/{1366x768,1280x720}/. Each story's own copy was asserted in the DOM before capture; 0 console errors, 0 document scroll, 0 horizontal overflow, 1 header, rail overflow 0, no inner scrollers on every story at both sizes. Raw numbers: /tmp/ws6-design/measurements.json.
  • Storybook: http://127.0.0.1:6011/?path=/story/domain-clean--review

@jdpigeon
jdpigeon merged commit 1423c7b into main Sep 27, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant