Skip to content

Fix carousel tab indexing and improve mobile responsiveness - #178

Open
milindmore22 wants to merge 7 commits into
developfrom
fix/tabs-mobile
Open

Fix carousel tab indexing and improve mobile responsiveness#178
milindmore22 wants to merge 7 commits into
developfrom
fix/tabs-mobile

Conversation

@milindmore22

Copy link
Copy Markdown
Contributor

Summary

This pull request improves accessibility and responsiveness for the carousel tab list component, making keyboard navigation clearer and ensuring better behavior on mobile devices. It also fixes logic around tab selection and focus, especially when the selected index is uninitialized.

Accessibility improvements:

  • Updated the tab outline style in carousel-tab-list/style.scss to use a high-contrast color for better visibility during keyboard navigation.
  • Fixed the logic in getTabTabIndex and related selection checks to ensure the first tab is focusable when selectedIndex is uninitialized or negative, improving keyboard navigation. [1] [2] [3]

Responsiveness improvements:

  • Added a media query to carousel-tab-list/style.scss to make the tab list horizontally scrollable on screens smaller than 1024px, preventing overflow and improving mobile usability.

Default state fixes:

  • Changed the initial selectedIndex from -1 to 0 in save.tsx so the first tab is selected by default, avoiding uninitialized state issues.

Type of change

  • Bug fix
  • New feature
  • Enhancement/refactor
  • Documentation update
  • Test update
  • Build/CI/tooling

Related issue(s)

Closes #176

What changed

  • Fixes issues with tab indexing for better accessibility, user can navigate using arrow keys when user is focused on tabs
  • Improved mobile and tab layout using horizontal scrolling.

Breaking changes

Does this introduce a breaking change? If yes, describe the impact and migration path below.

  • Yes — migration path:
  • No

Testing

Describe how this was tested.

  • Unit tests
  • Manual testing
  • Cross-browser testing (if UI changes)

Test details:

Screenshots / recordings

If applicable, add screenshots or short recordings.

Checklist

  • I have self-reviewed this PR
  • I have added/updated tests where needed
  • I have updated docs where needed
  • I have checked for breaking changes

Copilot AI review requested due to automatic review settings July 31, 2026 11:52

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.

Pull request overview

Note

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Improves carousel tab accessibility and mobile responsiveness by normalizing the selected tab index and updating tab list styling for clear keyboard focus and small-screen overflow handling.

Changes:

  • Normalize selectedIndex handling so the first tab/dot is treated as selected when the index is uninitialized/negative.
  • Update tab focus outline to a high-contrast style for clearer keyboard navigation.
  • Add mobile (≤1024px) horizontal scrolling behavior for the tab list and add a unit test for the selectedIndex = -1 case.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/blocks/carousel/view.ts Normalizes selectedIndex before comparing to snap index for “selected” behavior.
src/blocks/carousel/save.tsx Sets default selectedIndex to 0 to avoid uninitialized selection state.
src/blocks/carousel/carousel-tab-list/view.ts Updates roving tabindex logic to handle uninitialized/negative selectedIndex.
src/blocks/carousel/carousel-tab-list/style.scss Improves focus outline contrast and adds mobile horizontal scrolling.
src/blocks/carousel/carousel-tab-list/tests/view.test.ts Adds test coverage for selectedIndex = -1 roving tabindex behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/blocks/carousel/carousel-tab-list/view.ts
Comment thread src/blocks/carousel/carousel-tab-list/style.scss Outdated
Comment thread src/blocks/carousel/carousel-tab-list/style.scss Outdated
Comment thread src/blocks/carousel/carousel-tab-list/__tests__/view.test.ts Outdated
Copilot AI review requested due to automatic review settings July 31, 2026 13:16

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.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Suppressed comments (4)

src/blocks/carousel/carousel-tab-list/view.ts:105

  • The “normalize selectedIndex to 0 when uninitialized/negative” logic is duplicated (also added in src/blocks/carousel/view.ts). Consider extracting this into a shared helper (e.g., normalizeSelectedIndex(selectedIndex) or similar) to prevent the two implementations from drifting over time.
			const selectedIndex =
				typeof context.selectedIndex === 'number' && context.selectedIndex >= 0
					? context.selectedIndex
					: 0;
			const isActive = selectedIndex === snapIndex;

src/blocks/carousel/carousel-tab-list/style.scss:74

  • With overflow-x: auto on the tab-list container, focus outlines on child tabs can get clipped (in many browsers, non-visible overflow on one axis can cause the other axis to become non-visible/scrollable as well). To ensure the new outline-offset focus ring remains fully visible, add sufficient padding on the container (top/inline as well, not just bottom), or wrap the scrollable region in a padded outer container so keyboard focus is never visually cut off.
@media (max-width: 1024px) {

	.wp-block-rt-carousel-carousel-tab-list,
	.wp-block-rt-carousel-carousel-tab-list.is-layout-flex {
		max-width: 100%;
		flex-wrap: nowrap;
		overflow-x: auto;
		-webkit-overflow-scrolling: touch;
		scrollbar-width: thin;
		scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
		padding-bottom: 4px;

src/blocks/carousel/carousel-tab-list/tests/view.test.ts:234

  • This test name claims it covers both snap undefined and snap.index undefined, but the setup only covers snap: undefined. Either rename the test to match the scenario it actually covers, or add an additional test case for { snap: { index: undefined } } to align with the title.
	it( 'returns "-1" when snap or snap.index is undefined', () => {
		( getContext as jest.Mock ).mockReturnValue( {
			carouselId: 'c1',
			selectedIndex: 0,
			snap: undefined,
		} );
		expect( storeConfig!.callbacks.getTabTabIndex() ).toBe( '-1' );
	} );

src/blocks/carousel/carousel-tab-list/tests/view.test.ts:225

  • The undefined as unknown as number double-cast is brittle and obscures the intent of the test. Prefer adjusting the test helper/types to allow selectedIndex to be undefined in tests (or use a narrower one-off cast like as any) so the test remains readable and doesn’t encode misleading type assumptions.
	it( 'returns "0" for the first tab when selectedIndex is undefined (uninitialized)', () => {
		( getContext as jest.Mock ).mockReturnValue(
			mockContext( { selectedIndex: undefined as unknown as number, snap: { index: 0 } } ),
		);
		expect( storeConfig!.callbacks.getTabTabIndex() ).toBe( '0' );
	} );

@milindmore22
milindmore22 requested a review from danish17 July 31, 2026 13:34
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.

[Bug]: rtCarousel tabs fail to stack in mobile view and are not accessible using keyboard

2 participants