Skip to content

UI/UX polish for 0.1.4: colormaps, error dialogs, affordances - #36

Merged
LiukDiihMieu merged 8 commits into
mainfrom
feature/ui-ux-enhancements
Jun 27, 2026
Merged

UI/UX polish for 0.1.4: colormaps, error dialogs, affordances#36
LiukDiihMieu merged 8 commits into
mainfrom
feature/ui-ux-enhancements

Conversation

@LiukDiihMieu

Copy link
Copy Markdown
Owner

Pre-0.1.4 UI/UX improvements. Each commit is one self-contained change; all 321 tests pass and every GUI-facing change was verified manually in the real app.

Colormaps (b7815bc)

  • Add Twilight (the menu's first cyclic map) so phase/angle data no longer shows a seam artifact at ±π under a sequential/diverging map.
  • Add a global Reverse toggle that applies on top of any base map (toggling matplotlib's _r suffix) instead of duplicating an _r entry per colormap. Base name and reverse flag persist separately.

Hard failures become dialogs

  • Load failures → dialog (48c1d0d): a failed file open or .npz member selection now raises a modal QMessageBox instead of a status-bar line that gets overwritten by canvas hover readouts. load_file is the shared path, so File > Open, drag-and-drop and Reload all benefit. A failed member pick also snaps the dropdown back to the still-loaded array (new NpyDataModel.selected_key).
  • Export/copy failures → dialog (2305170): savefig had no error handling, so a full disk / missing permission / unwritable path failed silently from the Qt slot (and could abort the process). Both saves are now wrapped; last_export_dir is recorded only on success.
  • Invalid vmin/vmax → status hint (92042fb): _apply_clim swallowed a non-numeric value with a bare pass; it now reports vmin/vmax must be numbers (a dialog would be too heavy for input validation).

Discoverability & theming

  • Cross-section endpoint affordance (74189be): the draggable profile endpoints had no hint. Hovering one now shows a grab cursor + status hint, dragging shows a closed-hand cursor; elsewhere the default cursor and live pixel readout are untouched, so value-scanning is undisturbed. Reuses the existing _hit() hit-test.
  • Theme-aware placeholder text (18e5083): the empty-state and table message labels hardcoded #888 in a stylesheet, which suited only one theme and didn't follow a runtime light/dark switch. They now use the PlaceholderText foreground role (font via setFont, padding via setContentsMargins) so the muted text tracks the active theme like body text.

Docs (19073b7)

  • Add Twilight + Reverse to the colormap list in behavior.md, and fix the stated table cap to 2,000 (matching TABLE_MAX_PER_AXIS; it said 10,000).

🤖 Generated with Claude Code

LiukDiihMieu and others added 7 commits June 27, 2026 16:33
Twilight is the menu's first cyclic map, so phase/angle data (whose
values wrap at ±π) no longer shows a seam artifact under a sequential
or diverging map.

Reverse applies on top of whichever base map is selected instead of
duplicating an "_r" entry per colormap, keeping the menu short. It
toggles matplotlib's "_r" suffix, so a base that is already reversed
(RdBu_r) maps back to its forward form. The base name and the reverse
flag persist separately in QSettings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A failed open or .npz member selection is a hard failure the user just
triggered, but the status-bar message was easily missed and got
overwritten by canvas hover readouts. Raise a modal QMessageBox instead;
load_file is the shared path, so File > Open, drag-and-drop and Reload
all benefit.

A failed member pick also left the dropdown parked on the array that
never loaded, out of sync with the still-loaded member. The model keeps
the prior selection (materialize raises before it commits state), so
expose it via a selected_key property and snap the combo back to it.

Tests intercept QMessageBox (a modal dialog blocks the offscreen test
platform) and assert on the captured message.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
savefig had no error handling, so a full disk, missing permissions or an
unwritable path failed silently from the export/copy Qt slot — the
success status never showed (and an unhandled exception could abort the
process), leaving the user thinking the export worked. Wrap both saves:
export failure raises QMessageBox.critical, copy raises a warning, and
last_export_dir is recorded only after a successful save.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
_apply_clim swallowed a non-numeric vmin/vmax with a bare pass, so a
mistyped value did nothing with no explanation. Surface a status-bar
hint instead; a modal dialog would be too heavy for routine input
validation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The two profile-line endpoints were draggable with no affordance, so
the gesture was undiscoverable. Resting on an endpoint now swaps in a
grab cursor and a status-bar hint, and dragging shows a closed-hand
cursor; anywhere else keeps the default cursor and the live pixel
readout untouched, so value-scanning is undisturbed. Reuses the
existing _hit() hit-test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The empty-state and table message labels hardcoded a #888 grey in a
stylesheet, which only suited one theme and (being a stylesheet colour
frozen at construction) did not follow a runtime light/dark switch the
way body text does. Drive them from the PlaceholderText foreground role
instead — set the font via setFont and padding via contentsMargins so no
stylesheet colour overrides the palette — so the muted text tracks the
active theme automatically.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add the new Twilight colormap and the Reverse option to the colormap
list, and correct the table preview cap to 2,000 rows/columns to match
TABLE_MAX_PER_AXIS (the doc said 10,000).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread src/npyquick/app.py Outdated
("twilight", "Twilight (cyclic)"),
("hot", "Hot"),
("coolwarm", "Coolwarm"),
("RdBu_r", "RdBu (diverging)"),

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we have dedicated "reverse" option, we should no longer use RdBu_r here.

Suggested change
("RdBu_r", "RdBu (diverging)"),
("RdBu", "RdBu (diverging)"),

With the global Reverse toggle in place, the diverging entry no longer
needs to ship pre-reversed: use matplotlib's canonical "RdBu" base name
(consistent with every other entry, and matching the menu label) and
drop the now-needless "_r" un-toggling branch from _effective_colormap.
Reverse simply appends "_r". The default RdBu orientation is now red-low
/ blue-high; flip it with Reverse.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@LiukDiihMieu
LiukDiihMieu merged commit 1afbda1 into main Jun 27, 2026
8 checks passed
@LiukDiihMieu
LiukDiihMieu deleted the feature/ui-ux-enhancements branch June 27, 2026 09:49
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