Skip to content

Fix accessibility and UX defects - #1218

Closed
slick-daddy wants to merge 6 commits into
stashapp:masterfrom
slick-daddy:audit/p1-fixes
Closed

Fix accessibility and UX defects#1218
slick-daddy wants to merge 6 commits into
stashapp:masterfrom
slick-daddy:audit/p1-fixes

Conversation

@slick-daddy

Copy link
Copy Markdown
Contributor

1. Auth redirect called during render (Login.tsx)

if (isAuthenticated) navigate("/") ran in the component body,
triggering React updates during render and risking a loop while auth
state resolves. Replaced with a declarative <Navigate to="/" replace />
returned after all hooks.

2. react-select contrast failures (App.scss, studioSelect/styles.scss)

  • Selected values and typed input text were forced to color: black on
    the dark $secondary control (~2.3:1). Now pinned explicitly to
    $text-color (~9.9:1).
  • Multi-value chips paired near-white text with a near-white chip
    background; now $dark-text on the existing $muted-gray chip (~9.6:1).
  • StudioSelect's parent-studio label used rgba(black, 0.5) inside the
    value container, rendering near-invisible; dropped the override so it
    inherits the legible $text-muted.

All select surfaces (filters, forms, search) now meet WCAG AA text contrast.

3. Deleted images invisible in edit diffs

Removed images were rendered as srcless <img alt="Deleted"> tags, which
browsers draw as zero-width boxes — edit diffs showed blank gaps where
removed images should appear. Added a shared DeletedImage fragment
(muted tile, X icon, "Deleted" label, matching the existing
empty-thumbnail language) and used it in ImageChangeRow and
AmendableImageChangeRow.

4. Global 1210px viewport lockout (theme.scss, App.scss)

body { min-width: 1210px } — carried over from the Bootstrap 5
migration — forced horizontal scrolling of the entire app on any narrower
viewport. Removed it: the navbar already wraps (react-bootstrap
defaults to .navbar-expand), grids auto-fill, and filter rows
flex-wrap. The login prompt's fixed 960px width became max-width so
auth pages no longer overflow as the first screen seen at smaller sizes.
Wide tables can still overflow their own page; a full responsive pass is
out of scope here.

Calling navigate() in the component body triggers React updates during
render and can loop while auth state resolves. Return a declarative
<Navigate to=/ replace /> after all hooks instead.

Found by /impeccable audit (P1).
- Selected value and typed input were forced to black on the dark
  $secondary control (~2.3:1); they now inherit the control's
  $text-color (~9.9:1).
- Multi-value chips paired near-white text with a near-white chip;
  use $dark-text for ~9.6:1.
- StudioSelect parent label used rgba(black, 0.5) inside the value
  container, rendering near-invisible; drop the override so it uses
  the legible $text-muted applied elsewhere.

Brings all select surfaces to WCAG AA text contrast.

Found by /impeccable audit (P1).
Deleted images were rendered as srcless <img> tags, which browsers
draw as zero-width boxes, leaving blank gaps where removed images
should appear in edit diffs.

Add a shared DeletedImage fragment (muted tile with an X icon and
Deleted label, matching the existing empty-thumbnail language) and
use it in ImageChangeRow and AmendableImageChangeRow.

Found by /impeccable audit (P1).
The hard min-width on body, carried over from the Bootstrap 5
migration, locked every viewport narrower than 1210px into permanent
horizontal scrolling of the entire app.

The navbar already wraps (react-bootstrap defaults to .navbar-expand),
grids are auto-fill, and filter rows flex-wrap, so content degrades
rather than breaking. The login prompt's fixed 960px width becomes a
max-width so the auth pages - the first screen on small viewports -
no longer overflow.

Wider tables can still overflow their page; full responsive pass is
tracked separately (/impeccable adapt).

Found by /impeccable audit (P1).
The contrast fix for selected values and input text relied on
react-select emotion defaults surviving upgrades; make the light
token explicit.

Addresses code-review deviation on audit P1-2.
The deleted-image placeholder is now a .DeletedImage element instead
of a srcless <img alt=Deleted>, so query for it directly and also
assert its label. Test intent (placeholder renders for null entries)
is unchanged.

Fixes CI failure in PR stashapp#1218.
@InfiniteStash

Copy link
Copy Markdown
Collaborator

Please split unrelated fixes up into separate PRs. Makes them much easier to review and merge.

@slick-daddy

Copy link
Copy Markdown
Contributor Author

I tried to keep the commits in atomic form. Comments are well written too but if you still find it hard to review, of course I can split. How do you want me to split?

@InfiniteStash

Copy link
Copy Markdown
Collaborator

Based on the PR description I would expect four PRs.

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.

2 participants