Skip to content

Fix export format select keyboard focus#2366

Open
web3blind wants to merge 3 commits into
suitenumerique:mainfrom
web3blind:fix/export-format-select-focus
Open

Fix export format select keyboard focus#2366
web3blind wants to merge 3 commits into
suitenumerique:mainfrom
web3blind:fix/export-format-select-focus

Conversation

@web3blind
Copy link
Copy Markdown

Summary

  • remove the decorative export format select arrow from the tab order
  • hide the arrow button from assistive technologies

Why

In the export modal, keyboard and screen reader users currently encounter a separate focus stop for the dropdown arrow even though the combobox itself is the interactive control. This adds noise and makes the modal harder to navigate.

Fixes #2342.

Checks

  • npx -y prettier@3.8.3 --check apps/impress/src/features/docs/doc-export/components/ModalExport.tsx
  • static assertion that the patch sets aria-hidden="true" and tabindex="-1"

Note: I did not run the full app test suite because dependencies are not installed in this checkout.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c33ad69f-3253-4094-8c56-f64c965445c4

📥 Commits

Reviewing files that changed from the base of the PR and between 35a296d and bd1b73e.

📒 Files selected for processing (1)
  • src/frontend/apps/e2e/__tests__/app-impress/doc-export.spec.ts

Walkthrough

The ModalExport component now imports useEffect and useRef, wraps the format Select in a ref-bound container, and adds a useEffect that finds the select's internal open/toggle button and sets aria-hidden="true" and tabindex="-1". The e2e test was extended to assert the toggle is hidden from assistive tech and removed from the tab order.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: fixing the keyboard focus behavior of the export format select component.
Description check ✅ Passed The description is directly related to the changeset, explaining why the arrow should be hidden from keyboard/screen-reader navigation and linking to issue #2342.
Linked Issues check ✅ Passed The code changes fully satisfy issue #2342's requirements: aria-hidden and tabindex=-1 are added to the format select's arrow button to remove it from tab order and hide it from assistive technologies.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the keyboard focus issue in the export format select; no unrelated modifications are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e40f7840-29f4-43bc-9e7e-9b19bb347f15

📥 Commits

Reviewing files that changed from the base of the PR and between 4841d95 and 35a296d.

📒 Files selected for processing (1)
  • src/frontend/apps/impress/src/features/docs/doc-export/components/ModalExport.tsx

Comment on lines +70 to +77
useEffect(() => {
const toggleButton = formatSelectRef.current?.querySelector<HTMLElement>(
'.c__select__inner__actions__open',
);

toggleButton?.setAttribute('aria-hidden', 'true');
toggleButton?.setAttribute('tabindex', '-1');
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find export-modal tests and any assertions on the arrow/select attributes
fd -t f . | rg -i 'export' | rg -i 'spec|test|e2e'
rg -nP -C3 'c__select__inner__actions__open|aria-hidden|tabindex' \
  --glob '*.spec.*' --glob '*.test.*' --glob '*e2e*' --glob '*cypress*' --glob '*playwright*'

Repository: suitenumerique/docs

Length of output: 3831


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Check whether the internal Cunningham class is referenced anywhere in tests/code
rg -n --hidden --no-ignore-vcs 'c__select__inner__actions__open' . || true

# 2) Check for aria-hidden/tabindex assertions specifically in doc-export related e2e tests
rg -n --hidden --no-ignore-vcs \
  'doc-export|utils-export|app-impress/doc-export|ModalExport|Export' \
  src/frontend/apps/e2e/__tests__ || true

rg -n --hidden --no-ignore-vcs \
  'aria-hidden\s*=\s*["'\'']true["'\'']|aria-hidden|toHaveAttribute\(.+aria-hidden|tabindex\s*=\s*["'\'']-1["'\'']|toHaveAttribute\(.+tabindex' \
  src/frontend/apps/e2e/__tests__/app-impress/*.spec.* || true

# 3) Also check in app-impress tests/utils-export (if any)
rg -n --hidden --no-ignore-vcs \
  'aria-hidden\s*=\s*["'\'']true["'\'']|toHaveAttribute\(.+aria-hidden|tabindex\s*=\s*["'\'']-1["'\'']|toHaveAttribute\(.+tabindex' \
  src/frontend/apps/e2e/__tests__/app-impress/** || true

Repository: suitenumerique/docs

Length of output: 4640


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n --hidden --no-ignore-vcs \
  "toHaveAttribute\\(.+aria-hidden|aria-hidden\\s*=\\s*['\"]true['\"]|toHaveAttribute\\(.+tabindex\\s*,\\s*['\"]-1['\"]|tabindex\\s*=\\s*['\"]-1['\"]" \
  src/frontend/apps/e2e/__tests__/app-impress/**/*.spec.* \
  || true

rg -n --hidden --no-ignore-vcs \
  "aria-hidden|tabindex" \
  src/frontend/apps/e2e/__tests__/app-impress/**/*.spec.* \
  || true

Repository: suitenumerique/docs

Length of output: 255


🏁 Script executed:

#!/bin/bash
set -euo pipefail

base="src/frontend/apps/e2e/__tests__/app-impress"

rg -n --hidden --no-ignore-vcs \
  --glob '*.spec.*' --glob '*.test.*' --glob '*e2e*' --glob '*cypress*' --glob '*playwright*' \
  'toHaveAttribute\(.+aria-hidden|aria-hidden\s*=\s*['\'']true['\'']|toHaveAttribute\(.+tabindex\s*,\s*['\'']-1['\'']|tabindex\s*=\s*['\'']-1['\'']' \
  "$base" || true

rg -n --hidden --no-ignore-vcs \
  --glob '*.spec.*' --glob '*.test.*' --glob '*e2e*' --glob '*cypress*' --glob '*playwright*' \
  '(aria-hidden|tabindex)' \
  "$base" || true

Repository: suitenumerique/docs

Length of output: 603


Guard Cunningham internal Select class + add a11y regression test

ModalExport.tsx sets aria-hidden="true" and tabindex="-1" by querying Cunningham’s internal DOM node via .c__select__inner__actions__open. If Cunningham changes the markup/class, both setAttribute calls will silently no-op and the toggle can re-enter the accessibility/focus flow.

  • Add an e2e/RTL regression test that asserts the toggle element has aria-hidden="true" and tabindex="-1" in the export modal.
  • Prefer a supported Cunningham Select API/prop to hide the toggle from a11y (or add a guard/fallback), rather than relying on the internal class.

Keeping the effect without a dependency array is reasonable so the attributes are re-applied across Cunningham re-renders.

@web3blind
Copy link
Copy Markdown
Author

Updated after review feedback:

  • merged the current upstream/main into the PR branch;
  • added a Playwright regression assertion that the export format select internal toggle remains aria-hidden="true" and tabindex="-1".

Local validation: Prettier check passed for the updated e2e spec. GitHub checks are currently green.

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.

Export modal: combobox arrow button independently focusable

1 participant