Design pass: WS6 Clean — dataset select, review pair, primer, suggestions, save states - #280
Merged
Merged
Conversation
…ag suggestions, save states (Storybook only)
… + suggestions in the rail, primer as rail bar + overlay step card
…cked next to the canvas; rail untruncated with stacked save actions
…the full bottom row otherwise
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 andutils.pyare unchanged. No shared files are touched at all this round — everything lives insrc/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)
DatasetSelectandDatasetSelectWithIncompleteare single-select radio rows (no checkboxes), the "you can pick more than one" copy is gone, the rail shows one recording, and theselectedprop isstring | null— nothing models a multi-recording selection anywhere. Integration note: Clean must be single-recording; the currentCleanComponent's multi-fileLoadEpochsmust 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.)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 & analyzeas the one filled primary.Why this geometry
The real
EpochReviewerdraws in a fixed 640×426 box andLiveErpPanein 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, ResizeObserverzoom) scales the real components; integration should make the panes resize-aware and drop it.The real components rendered
Yes — the real
EpochReviewerand the realLiveErpPanerender in these stories, unmodified, wrapped only inFitPane(a story-only scaler). Both are pure-props components (no Redux, no worker, noelectronAPI); the story harness holds their state (rejected,badChannels, toggles) and feeds themEXAMPLE_EPOCH_ARRAYSfromAnalyze/fixtures.ts— the same example epochs Analyze's walkthrough uses. No second epoch generator exists; the panes run the app's owndownsampleMinMax/epochChannelSeries/meanTrace.Actions and confirmations
Apply exclusions & save→Apply exclusions;Auto-flag artifacts→Suggest noisy trials.Start cleaning,← Pick different data,Save cleaned dataset & analyze,Go to Analyze →kept.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 isdestructivestyled. Storybook has noelectronAPI.showMessageBox, so the dialog is the restyled version for integration to adopt.CleanComponentsilently adds them to the rejected set); they wait forAccept/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):Review agenda
Domain/Clean, all rendered in the real AppShell (location="clean", workspaceFaces_Houses_3, truthful badges and Next), fixture data only:Start cleaning) · DatasetSelectWithIncomplete (hidden by default — "2 ended-early recordings hidden · Show"; revealed rows are badge-marked "Ended early", not selectable, with a confirmed destructiveDelete) — interactive captures for the revealed and delete-confirm states ship alongside✓ Left out · Restore, 2 withAccept)Try again) · Saved (Go to Analyze →, shell Next flips to Analyze)WorkflowNav'sAREASmaps behavior-only workspaces to['prepare', 'collect', 'analyze'], so there is no Clean area to design.Open questions
CleanComponentadds every suggestion straight to the rejected set. Which behavior does product want?LiveErpPaneresponsive and give it more room (e.g. a collapsible panel or a hover-zoom)?Apply exclusionsas the in-place save, is the two-button pair clear enough?Constraints not met, and notes for integration
EpochReviewercan't be edited in a design pass); distinction is carried by the suggestion rows and the counts in words. Integration could giveEpochReviewerasuggestedprop.ConfirmRejectAll/ConfirmDropChannels, so they have no dedicated story.FitPanescales the real panes withzoom(Chromium-standard, fine in Electron) instead of making them responsive. Integration should ideally giveEpochReviewer/LiveErpPaneresize-aware drawing and dropFitPane.Suggest noisy trialschange fixture state only; no Pyodide dispatch.Verification
npx tsc --noEmit: 0 errors./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.