Skip to content

Show keyboard focus indicator on carousel flippers - #5876

Merged
Eugene (OEvgeny) merged 2 commits into
mainfrom
OEvgeny/fix-5704-carousel-flipper-focus
Oct 17, 2026
Merged

Eugene (OEvgeny) merged 2 commits into
mainfrom
OEvgeny/fix-5704-carousel-flipper-focus

Conversation

@OEvgeny

@OEvgeny Eugene (OEvgeny) commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #5704
Fixes #5744

Changelog Entry

Fixed

  • Fixed the keyboard focus indicator of the "Previous" and "Next" flipper buttons in carousel layout: they now show a visible focus ring, and the focused flipper is shown even at the start or end of the carousel, fixes #5704 and #5744, in PR #5876, by @OEvgeny

Description

The carousel flippers had outline: 0. On focus they only got a slightly darker background, the same as on hover, so keyboard users could not tell when a flipper had focus. Also, the flipper at the edge (for example "Previous" at the start) stayed in the tab order but was slid out of view, so its focus was invisible.

On :focus-visible, the flipper now has a two-tone ring and is always shown. This applies to both the default theme and the Fluent theme. The ring has an inner band in the flipper foreground color (white) and an outer outline that uses the transcript keyboard indicator style options (2px solid black by default). It has at least 3:1 contrast against the flipper and against the content behind it.

Design

react-film 4.0.0 renders the flipper <button> itself and does not let Web Chat set tabIndex, disabled, or aria-disabled. So the flipper at the edge stays focusable. Hiding it with CSS would make things worse: when a keyboard user presses "Next" until the end, the focused button would disappear and focus would drop to <body>. Instead, the focused flipper is kept visible. The proper follow-up is in react-film: set aria-disabled="true" on the flipper at the edge. CarouselLayout.module.css already styles that state.

Open question: should the Fluent theme map the ring color to its focus token (--webchat-colorStrokeFocus2) instead of transcriptVisualKeyboardIndicatorColor?

Specific Changes

  • CarouselLayout.module.css: added :focus-visible styles to .react-film__flipper: a ring on the flipper body (box-shadow + outline), and the slider is moved into view with no transition delay
  • Added __tests__/html2/carousel/flipperButton.focusVisible.html and a .fluent.html variant: they Tab to "Next", then to the hidden "Previous", and assert focus, visibility, and the computed ring. Snapshots are taken after the flippers settle.
  • I have added tests and executed them locally
  • I have updated CHANGELOG.md
  • I have updated documentation

Review Checklist

This section is for contributors to review your work.

  • Accessibility reviewed (tab order, content readability, alt text, color contrast)
  • Browser and platform compatibilities reviewed
  • CSS styles reviewed (minimal rules, no z-index)
  • Documents reviewed (docs, samples, live demo)
  • Internationalization reviewed (strings, unit formatting)
  • package.json and package-lock.json reviewed
  • Security reviewed (no data URIs, check for nonce leak)
  • Tests reviewed (coverage, legitimacy)

Eugene Olonov added 2 commits October 16, 2026 17:48
The "Previous" and "Next" flippers in carousel layout had `outline: 0` and
only darkened their background on focus, the same as on hover. The flipper
at the edge of the carousel (e.g. "Previous" at the start) stayed in the tab
order but was slid out of view, so keyboard focus on it was invisible.

- On `:focus-visible`, draw a two-tone ring around the flipper: a band in the
  flipper foreground color and an outline using the transcript keyboard
  indicator style options (2px solid black by default)
- Always show the focused flipper, including the one hidden at the edge
- Add html2 test for the default and Fluent themes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

Static review found no blocking defects in the focused CSS change and regression coverage; browser tests were not executed during review.

No open issues 🎉

What changed in this PR

Improves keyboard focus visibility for carousel navigation in the default and Fluent themes, addressing #5704 and #5744.

Changes:

  • Adds a two-tone focus ring and reveals focused flippers at carousel edges.
  • Adds regression tests for focus styling, visibility, and hiding after focus leaves.
  • Documents the accessibility fix in the changelog.
File Description
packages/​component/​src/​Activity/​CarouselLayout.module.css Adds focus rings and reveals focused flippers.
CHANGELOG.md Records the carousel accessibility fix.
tests/​html2/​carousel/​flipperButton.focusVisible.html Tests keyboard focus styling and flipper visibility.
tests/​html2/​carousel/​flipperButton.focusVisible.fluent.html Runs the regression test with the Fluent theme.

Review effort: Balanced

@OEvgeny
Eugene (OEvgeny) merged commit a191a10 into main Oct 17, 2026
33 checks passed
@OEvgeny
Eugene (OEvgeny) deleted the OEvgeny/fix-5704-carousel-flipper-focus branch October 17, 2026 01:55
Eugene (OEvgeny) added a commit that referenced this pull request Oct 17, 2026
* Show focus indicator on suggested actions flipper buttons

The "Previous" and "Next" flipper buttons of suggested actions in carousel
layout had no keyboard focus indicator: react-film and the style set remove
the outline, and focus only darkens the background like hover does.

Add a two-tone focus ring on :focus-visible (2px band in the flipper
foreground color, then the suggested actions visual keyboard indicator as
outline at 2px offset), consistent with the carousel flipper fix in #5876.
Document that the suggestedActionsVisualKeyboardIndicator* style options
also apply to the flipper buttons.

Fixes #5725.

* Add PR number to changelog

* Rely on snapshots in suggested actions flipper focus test

---------

Co-authored-by: Eugene Olonov <eugeneolonov@microsoft.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: OEvgeny <2841858+OEvgeny@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants