feat: GUI accessibility - text zoom, high-contrast resize lines, per-mode transmission #224

Merged
perl_d merged 4 commits from feat/gui-accessibility into main 2026-09-14 13:23:33 +02:00
Owner

Usability changes for operators who cannot read the current GUI comfortably, each as its own commit.

  1. Text zoom (accessibility)
  • Ctrl+plus / Ctrl+minus / Ctrl+0, also in the View menu, scale every UI text: the QSS FONT_* ladder and the application default font together, clamped to 0.8-1.6x and persisted in QSettings.
  • Why: the fixed 11-14px text was too small for some operators and there was no way to enlarge it.
  1. High-contrast resize lines and controls (WCAG)
  • Dock/splitter gutters keep a 5px grab area but draw a 2px line with a 1px shadow instead of an invisible fill; separators measured 1.0-1.2:1 against every theme background, now >=3.25:1 (dark theme gold at 70 percent). Scrollbar handle 1.17:1 -> 3.38:1. Unselected tab text on the sky gradient 2.07:1 -> 4.71:1.
  • Why: resize lines, scrollbar handles and unselected tabs were below the WCAG floors (3:1 for UI components, 4.5:1 for text) and effectively invisible.
  1. Mounted sample on the camera view
  • A "Currently mounted: <sample_name>" HUD line in the top-left of the sample camera, driven by the DAQ status; clears when nothing is mounted, follows the text zoom.
  • Why: the operator at the camera had no direct read of which sample is on the gonio.
  1. Per-mode transmission placement
  • The shared "Rotation transmission" row sat at the top of BOTH the Gridscan and Rotation tabs. Now the Gridscan tab has its own "Transmission" row, and the Rotation tab moves "Rotation transmission" below the Screening block and its Run button, as the first row of the Rotation section. Screening keeps its separate "Screening transmission". Same field and value handling, only label and placement changed.
  • Why: one top-level row labelled "Rotation transmission" read as applying to screening too, and made no sense in the Gridscan tab.
  1. Tooltips on the glyph count columns
  • The sample list's Mount/Gridscan/Screening/Rotation count column headers are glyphs to save width; hovering now shows the full name.
  • Why: the icons do not explain themselves.

Verified by rendering the GUI in the RHEL9 container (screenshots, xdotool-driven), WCAG contrast ratio calculations, and unit tests. Gates: ruff clean, basedpyright diff 100 percent, unit tests green, diff coverage 92 percent.

Generated with Claude Code (https://claude.com/claude-code)

Usability changes for operators who cannot read the current GUI comfortably, each as its own commit. 1. Text zoom (accessibility) - Ctrl+plus / Ctrl+minus / Ctrl+0, also in the View menu, scale every UI text: the QSS FONT_* ladder and the application default font together, clamped to 0.8-1.6x and persisted in QSettings. - Why: the fixed 11-14px text was too small for some operators and there was no way to enlarge it. 2. High-contrast resize lines and controls (WCAG) - Dock/splitter gutters keep a 5px grab area but draw a 2px line with a 1px shadow instead of an invisible fill; separators measured 1.0-1.2:1 against every theme background, now >=3.25:1 (dark theme gold at 70 percent). Scrollbar handle 1.17:1 -> 3.38:1. Unselected tab text on the sky gradient 2.07:1 -> 4.71:1. - Why: resize lines, scrollbar handles and unselected tabs were below the WCAG floors (3:1 for UI components, 4.5:1 for text) and effectively invisible. 3. Mounted sample on the camera view - A "Currently mounted: <sample_name>" HUD line in the top-left of the sample camera, driven by the DAQ status; clears when nothing is mounted, follows the text zoom. - Why: the operator at the camera had no direct read of which sample is on the gonio. 4. Per-mode transmission placement - The shared "Rotation transmission" row sat at the top of BOTH the Gridscan and Rotation tabs. Now the Gridscan tab has its own "Transmission" row, and the Rotation tab moves "Rotation transmission" below the Screening block and its Run button, as the first row of the Rotation section. Screening keeps its separate "Screening transmission". Same field and value handling, only label and placement changed. - Why: one top-level row labelled "Rotation transmission" read as applying to screening too, and made no sense in the Gridscan tab. 5. Tooltips on the glyph count columns - The sample list's Mount/Gridscan/Screening/Rotation count column headers are glyphs to save width; hovering now shows the full name. - Why: the icons do not explain themselves. Verified by rendering the GUI in the RHEL9 container (screenshots, xdotool-driven), WCAG contrast ratio calculations, and unit tests. Gates: ruff clean, basedpyright diff 100 percent, unit tests green, diff coverage 92 percent. Generated with Claude Code (https://claude.com/claude-code)
duan_j added 3 commits 2026-09-14 10:34:01 +02:00
feat: text zoom shortcuts and high-contrast resize lines
CI / lint (push) Skipped
CI / test (3.12) (push) Skipped
CI / test (3.13) (push) Skipped
CI / test-with-beamline-plugins (pxi_bec) (push) Skipped
CI / test-with-beamline-plugins (pxii_bec) (push) Skipped
CI / test-with-beamline-plugins (pxiii_bec) (push) Skipped
CI / lint (pull_request) Successful in 1m0s
CI / test (3.12) (pull_request) Successful in 1m27s
CI / test (3.14) (pull_request) Successful in 1m24s
CI / test (3.13) (pull_request) Successful in 1m36s
CI / test-with-beamline-plugins (pxi_bec) (pull_request) Successful in 1m34s
CI / test-with-beamline-plugins (pxiii_bec) (pull_request) Successful in 1m35s
CI / test-with-beamline-plugins (pxii_bec) (pull_request) Successful in 1m39s
CI / test-with-coverage (pull_request) Successful in 1m53s
CI / coverage-analysis (pull_request) Successful in 4s
bd74ac47bc
- Ctrl+plus / Ctrl+minus / Ctrl+0 (and View menu entries) scale the QSS
  FONT_* ladder and the application default font together; the scale is
  clamped to 0.8-1.6 and persisted in QSettings appearance/font_scale.
- Resize gutters keep a 5px hover/drag region but paint only a 2px line
  with a 1px shadow (hard-stop gradients per orientation).
- WCAG contrast fixes: separators were 1.0-1.2:1 against every theme
  background, now >=3.25:1 (dark theme gold @70%); scrollbar handle
  1.17:1 -> 3.38:1; unselected tab text on the sky gradient 2.07:1 ->
  4.71:1 via TAB_IDLE_TEXT.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A "Currently mounted: <sample_name>" HUD line in the top-left corner of
the sample camera, driven by the DAQ status (clears when nothing is
mounted). Painted like the other camera HUDs and sized through the text
zoom, which QSS cannot reach here.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
refactor: transmission is a per-mode setting, placed in its section
CI / lint (push) Skipped
CI / test (3.12) (push) Skipped
CI / test (3.13) (push) Skipped
CI / test-with-beamline-plugins (pxi_bec) (push) Skipped
CI / test-with-beamline-plugins (pxii_bec) (push) Skipped
CI / test-with-beamline-plugins (pxiii_bec) (push) Skipped
CI / lint (pull_request) Successful in 59s
CI / test (3.12) (pull_request) Successful in 1m15s
CI / test (3.14) (pull_request) Successful in 1m17s
CI / test (3.13) (pull_request) Successful in 1m21s
CI / test-with-beamline-plugins (pxi_bec) (pull_request) Successful in 1m22s
CI / test-with-beamline-plugins (pxii_bec) (pull_request) Successful in 1m25s
CI / test-with-beamline-plugins (pxiii_bec) (pull_request) Successful in 1m37s
CI / test-with-coverage (pull_request) Successful in 1m51s
CI / coverage-analysis (pull_request) Successful in 4s
6b34fd80bb
The shared "Rotation transmission" row sat in the top rows of BOTH the
Gridscan and Rotation tabs, where it read as one setting for everything
(and as nonsense in the Gridscan tab). Now each tab places its own row:
Gridscan keeps "Transmission" with the shared resolution/distance rows,
and the Rotation tab moves "Rotation transmission" below the Screening
block and its Run button, as the first row of the Rotation section -
next to the fields it actually applies to. Screening keeps its separate
"Screening transmission". No behavior change: same field, same
spreadsheet/user-value handling, only the label and the placement.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Coverage report (automated)

Total line + branch coverage: 51%
Diff coverage vs main: 93% (minimum 80%)

Full report: coverage artifact on this run.

Coverage report (automated) Total line + branch coverage: 51% Diff coverage vs main: 93% (minimum 80%) Full report: coverage artifact on this run.
duan_j added 1 commit 2026-09-14 10:38:58 +02:00
feat: full-name tooltips on the glyph count column headers
CI / lint (push) Skipped
CI / test-with-beamline-plugins (pxiii_bec) (push) Skipped
CI / test (3.13) (push) Skipped
CI / test-with-beamline-plugins (pxi_bec) (push) Skipped
CI / test-with-beamline-plugins (pxii_bec) (push) Skipped
CI / test (3.12) (push) Skipped
CI / lint (pull_request) Successful in 57s
CI / test (3.12) (pull_request) Successful in 1m18s
CI / test (3.14) (pull_request) Successful in 1m18s
CI / test (3.13) (pull_request) Successful in 1m25s
CI / test-with-beamline-plugins (pxi_bec) (pull_request) Successful in 1m25s
CI / test-with-beamline-plugins (pxii_bec) (pull_request) Successful in 1m28s
CI / test-with-beamline-plugins (pxiii_bec) (pull_request) Successful in 1m37s
CI / test-with-coverage (pull_request) Successful in 1m48s
CI / coverage-analysis (pull_request) Successful in 4s
27fa6cb260
The sample list's Mount/Gridscan/Screening/Rotation count columns show
only a glyph in the header to save width; hovering now shows the full
name via ToolTipRole. Text headers stay tooltip-free.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
perl_d merged commit f1f932bc7c into main 2026-09-14 13:23:33 +02:00
Sign in to join this conversation.