ionic-team / ionic-team/ionic-framework

bug: ion-segment have incorrect tab sequence order (accessibility)

Open
#30,022 0 comments 0 reactions 0 assignees View on GitHub
triage
Dominant language
TypeScript
Stars
52.7k
Forks
13.3k
Avg merge
1d 15h
Merged PRs (30d)
51

Description

### Prerequisites

- [X] I have read the [Contributing Guidelines](https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#creating-an-issue).
- [X] I agree to follow the [Code of Conduct](https://ionicframework.com/code-of-conduct).
- [X] I have searched for [existing issues](https://github.com/ionic-team/ionic-framework/issues) that already report this problem, without success.

### Ionic Framework Version

v8.x

### Current Behavior

Keyboard interaction for Tab key on `ion-segment` doesn't follow the [Tabs Pattern in the ARIA Authoring Practices Guide (APG)](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/):

- When focus moves into `ion-segment` (i.e. "tab list"), it doesn't place focus on the checked (i.e. "active") `ion-segment-button` (i.e. "tab element")
- When `ion-segment` (i.e. "tab list") contains the focus, it doesn't moves focus to the next element in the page tab sequence outside `ion-segment` (i.e. "tab list"), but focuses the next `ion-segment-button`

### Expected Behavior

I expect keyboard interaction in `ion-segment` to behave according to the [Tabs Pattern in the ARIA Authoring Practices Guide (APG)](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/).
Pressing the Tab key on a Tab List should result in:

1. When focus moves into the tab list, places focus on the active tab element
2. When the tab list contains the focus, moves focus to the next element in the page tab sequence outside the tablist [...]

_Note: rest of the keyboard interaction on ion-segment behaves as expected and according to the APG pattern 👌🏻_

### Steps to Reproduce

_Please note: selecting `MD` mode in the examples makes it easer to see the currently focused segment button_

1. Places focus on the active tab element:
1.1 Go to https://ionicframework.com/docs/api/segment#basic-usage
1.2 Select the second segment button in the playground preview under "Basic Usage"
1.3 Click outside the segment component to blur it (e.g. to the left or top of)
1.4 Press the Tab key to focus the segment component
1.5 See that the first segment contains focus (but focus should be on the checked, i.e. second, segment button)

2. Move focus to the next element in the page tab sequence:
2.1 Go to https://ionicframework.com/docs/api/segment#basic-usage
2.2 Click inside the playground preview under "Basic Usage" (e.g. to the left or top of the segment component)
2.3 Press the Tab key to focus the first segment button
2.4 Press the Tab again
2.5 See that the second segment contains focus (but focus should move to the next element in the page tab sequence outside the component)

### Code Reproduction URL

https://ionicframework.com/docs/api/segment#basic-usage

### Ionic Info

```
Ionic:
Ionic CLI : 5.4.16
Ionic Framework : @ionic/angular 8.2.7

Utility:
cordova-res : not installed
native-run (update available: 2.0.1) : 1.7.4

System:
NodeJS : v20.11.1
npm : 10.2.4
OS : macOS Unknown
```

### Additional Information

Currently each `ion-segment-button` inside `ion-segment` renders a native html button in it's shadow dom, which in turn acts as a tab stop in the page tab sequence, i.e. each button receives focus when the Tab key is pressed.

Before #26575 each `ion-segment-button` rendered with `tabindex=-1` if not checked and `tabindex=0` if checked (and not disabled). Each native button inside the shadow dom rendered with `tabindex=-1`.

This actually gave the correct tab order both when focusing the segment control (focus correctly being set on the checked segment button) as well as pressing the Tab key when the segment control contained focus (focus moved to the next element in the page tab sequence outside the control).

Maybe this can be re-introduced, but with the `tabindex` set on the native button?

To fully implement the Tabs Pattern from APG it should also implement [a Roving Tabindex ](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex), i.e. set `tabindex=0` on the currently focused button and `tabindex=-1` on all other. When the segment component looses focus it should set `tabindex=0` on the checked button (or the first button if none is checked) and `tabindex=-1` on all other.

Contributor guide

Open the contributing guide

Research direction

Start at the ion-segment and ion-segment-button entry points, then compare the current native button tabindex behavior with the previous behavior described around #26575. Reproduce the issue using the Segment basic-usage example and verify completion against the ARIA Tabs Pattern: focus should enter on the active button and Tab should leave the segment list.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
accessibility, frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.