Skip to content

a11y improvements, inital axe tests - #400

Open
Bohreromir wants to merge 11 commits into
mainfrom
feat/a11y
Open

Bohreromir wants to merge 11 commits into
mainfrom
feat/a11y

Conversation

@Bohreromir

@Bohreromir Bohreromir commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

Description

  • Resolve the biggest a11y offenders and adds inital axe tests.
  • Merges the two tabbars into a single component
  • Unifies the text-base-content/{30,40,50} into a new text-muted
    • Looks like a lot, but most files are only css class renames

Docs

Release note

Checklist

Author

  • AI review done, findings addressed
  • Tests added or updated
  • Changelog updated (if the repo keeps one)

Reviewer

  • Useful comments and logging
  • Docs added or updated per the style guide

Acceptance

  • Check for release notes and docs

`role="none"` on `<li>` elements inside plain lists stripped their
listitem semantics, so axe reported links as invalid direct children
of the list (aria-required-children). Affects the pinned locations and
bucket lists in the sidebar and the active/history lists in the
operations panel.
A tablist may only own tabs (axe aria-required-children), but both tab
bars put per-tab close buttons inside it, and the storage bar also the
New Tab button.

- Storage: wrap only the tabs in the tablist; New Tab sits next to it
- Close buttons are a mouse-only affordance (tabindex=-1, aria-hidden);
  keyboard and screen-reader users close tabs with the existing Delete
  shortcut, now announced via aria-keyshortcuts
- Storage: after Delete, focus the tab that closeTab activates instead
  of the one after it
- Scan both tab bars with two tabs open in the accessibility spec
Switching explorer tabs navigates via goto(), and SvelteKit's
post-navigation focus reset moved focus to <body>. After clicking a
tab, keyboard shortcuts on it (arrow keys, Delete) did nothing.
The storage explorer and the Trino editor had separate tab bars with
the same ARIA pattern and keyboard handling, which had drifted apart.
The generic TabBar is now the only implementation; the storage one is
a thin wrapper that adds its context menu and drop-files-onto-tab.

User-visible changes:
- Both: F2 renames the focused tab; aria-keyshortcuts announces
  Delete and F2
- Both: the rename input replaces the tab instead of being nested in
  it, so Delete/arrow keys while renaming no longer close or switch tabs
- Trino: labelled tablist ("Query tabs"), Home/End, middle-click close,
  overflow fades instead of a visible scrollbar
- Storage: Trino visual style
- Overflow fades scale down on narrow strips and follow resizes; a
  focused tab is kept clear of them
- Fast repeated arrow presses no longer skip tabs
- Closing a tab with the mouse no longer moves focus
Run at cursor does nothing until the dynamically imported Monaco
editor has loaded, so clicking Run right after hydration sometimes
started no query and the test timed out. Click into the editor first,
like the other Trino specs do.
Run at cursor needs the Monaco editor, which is imported dynamically.
Clicking Run or pressing Ctrl+Enter before it had loaded silently did
nothing. MonacoEditor now exposes its ready state as a bindable prop,
and the page keeps Run disabled and ignores Ctrl+Enter until then.
The run mode dropdown used DaisyUI's CSS dropdown, which opened
whenever the Run button got focus, could not be closed with Escape,
had no expanded state and showed the selected mode by colour only.

Move the split button into RunButton, following the WAI-ARIA menu
button pattern: the toggle opens the menu (click, Enter, Space,
ArrowDown/ArrowUp) and reports aria-expanded; the modes are
menuitemradio items with aria-checked and a check mark; arrows,
Home/End, Escape, Tab and outside clicks behave as expected. Raise
the shortcut label opacity to meet the 4.5:1 contrast ratio.
Secondary text used text-base-content at 20-60% opacity. In the light
theme that is 1.9:1 to 4.6:1 (4.4:1 at 60% on base-300), below the
4.5:1 WCAG AA minimum; axe reported 25 violations.

- Add a text-muted colour token: 70% base-content in the light theme
  (6.1:1 or more), 60% in the dark theme (6.2:1 or more)
- Use it for all secondary text, visible aria-hidden text and state
  icons such as expand chevrons; only aria-hidden icon components that
  duplicate adjacent text keep a lower opacity
- Override DaisyUI's 50% colour for inactive tabs
- Enforce the rule with an architecture test and document it in
  AGENTS.md
@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

⚠️ Coverage report too large to inline, see the workflow summary.

@Bohreromir Bohreromir moved this to Development: Waiting for Review in Stackable Engineering Oct 22, 2026
@Bohreromir
Bohreromir marked this pull request as ready for review October 22, 2026 15:08
lfrancke
lfrancke previously approved these changes Oct 23, 2026

@lfrancke lfrancke left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I have one comment - up to you whether you want to do it here or not.
I brought up a portal with the changes, looked at the run button, the tab bars and text, it all looks good. Thank you.

I also skimmed through the files but most edits are mechanical so....

Comment thread e2e/accessibility.spec.ts Outdated
import { setTabSql, setTabState, waitForHydration, waitForQueryComplete } from './support/helpers';
import { connectAndOpenPrefix, connectToStorage } from './storage/helpers.js';

const WCAG_TAGS = ['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'];

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we should also go for wcag22a and wcag22aa here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I added them

# Conflicts:
#	src/routes/(app)/trino/+page.svelte
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Development: Waiting for Review

Development

Successfully merging this pull request may close these issues.

2 participants