Skip to content

Conversation

@FireRedNinja
Copy link
Contributor

@FireRedNinja Noel Rajan (FireRedNinja) commented Dec 10, 2025

Changes

This pull request introduces significant improvements to the BpkSegmentedControl component, focusing on accessibility, API, and documentation. The most notable changes are the addition of a new useSegmentedControlPanels hook for managing tab panels with proper ARIA relationships, enhancements to keyboard navigation and activation modes, and updates to documentation and examples to reflect these improvements.

Accessibility and API Improvements

  • Added useSegmentedControlPanels hook and supporting types: Provides an easy-to-use API for managing tab panels, automatically generating IDs and ARIA relationships for accessibility. Also exports new types such as TabPanelProps for better type safety. (packages/bpk-component-segmented-control/src/BpkSegmentedControl.tsx [1] [2]; packages/bpk-component-segmented-control/index.ts [3]
  • Enhanced keyboard navigation and activation modes: Implements full ARIA tabs pattern, supporting arrow keys, Home/End, and both automatic and manual activation modes for tabs, improving usability for keyboard and assistive technology users. (packages/bpk-component-segmented-control/src/BpkSegmentedControl.tsx [1] [2]
  • Updated accessibility tests: Adds tests for both tab-only and tab-with-panel usage, ensuring no accessibility violations are introduced. (packages/bpk-component-segmented-control/src/accessibility-test.tsx packages/bpk-component-segmented-control/src/accessibility-test.tsxL22-R73)

Documentation and Examples

  • Expanded and improved README: Updates documentation to explain the new hook, tab panel usage, accessibility features, and keyboard navigation, making it easier for developers to implement accessible segmented controls. (packages/bpk-component-segmented-control/README.md packages/bpk-component-segmented-control/README.mdL1-R93)
  • Added new usage examples and Storybook stories: Demonstrates recommended hook-based tab panel pattern and conditional rendering approaches, helping users adopt best practices. (examples/bpk-component-segmented-control/examples.tsx [1] [2] [3]; examples/bpk-component-segmented-control/stories.tsx [4] [5]

Remember to include the following changes:

  • Ensure the PR title includes the name of the component you are changing so it's clear in the release notes for consumers of the changes in the version e.g [Clover-123][BpkButton] Updating the colour
  • README.md (If you have created a new component)
  • Component README.md
  • Tests
  • Accessibility tests
    • The following checks were performed:
      • Ability to navigate using a keyboard only
      • Zoom functionality (Deque University explanation):
        • The page SHOULD be functional AND readable when only the text is magnified to 200% of its initial size
        • Pages must reflow as zoom increases up to 400% so that content continues to be presented in only one column i.e. Content MUST NOT require scrolling in two directions (both vertically and horizontally)
      • Ability to navigate using a screen reader only
  • Storybook examples created/updated
  • For breaking changes or deprecating components/properties, migration guides added to the description of the PR. If the guide has large changes, consider creating a new Markdown page inside the component's docs folder and link it here

@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4079 to see this build running in a browser.

@skyscanner-backpack-bot
Copy link

skyscanner-backpack-bot bot commented Dec 10, 2025

Warnings
⚠️

Package source files (e.g. packages/package-name/src/Component.js) were updated, but snapshots weren't. Have you checked that the tests still pass?

Browser support

If this is a visual change, make sure you've tested it in multiple browsers.

Generated by 🚫 dangerJS against 43a9643

@FireRedNinja Noel Rajan (FireRedNinja) added the minor Non breaking change label Dec 10, 2025
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4079 to see this build running in a browser.

@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4079 to see this build running in a browser.

@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4079 to see this build running in a browser.

@FireRedNinja Noel Rajan (FireRedNinja) marked this pull request as ready for review December 11, 2025 15:42
Copilot AI review requested due to automatic review settings December 11, 2025 15:42
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request converts the BpkSegmentedControl component to implement the ARIA tabs interaction pattern, enhancing accessibility and usability. The changes introduce keyboard navigation, support for tab panels with proper ARIA relationships, and a new hook for simplified implementation.

Key Changes:

  • Implemented full ARIA tabs pattern with keyboard navigation (arrow keys, Home/End) and RTL support
  • Added useSegmentedControlPanels hook for automatic ID generation and ARIA relationship management
  • Introduced activation modes (automatic/manual) to control tab selection behavior

Reviewed changes

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

Show a summary per file
File Description
packages/bpk-component-segmented-control/src/BpkSegmentedControl.tsx Core component changes: added keyboard navigation, tab roles, ARIA attributes, and useSegmentedControlPanels hook
packages/bpk-component-segmented-control/index.ts Exported new useSegmentedControlPanels hook and TabPanelProps type
packages/bpk-component-segmented-control/src/accessibility-test.tsx Added accessibility tests for both tab-only and tab-with-panel usage scenarios
packages/bpk-component-segmented-control/src/BpkSegmentedControl-test.tsx Comprehensive test coverage for keyboard navigation, RTL support, and activation modes
packages/bpk-component-segmented-control/README.md Updated documentation with usage examples, accessibility guidelines, and keyboard navigation details
examples/bpk-component-segmented-control/examples.tsx Added example implementations demonstrating hook-based and conditional rendering patterns
examples/bpk-component-segmented-control/stories.tsx Added Storybook stories for new example components

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

Comment on lines +143 to 145
// TODO: Consider removing internal state - component is controlled via selectedIndex prop.
// Internal state may cause sync issues if selectedIndex changes externally.
const [selectedButton, setSelectedButton] = useState(selectedIndex);
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

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

The component maintains internal state that duplicates the selectedIndex prop, which can lead to synchronization issues. The component should either be fully controlled (no internal state) or the internal state should sync with prop changes via useEffect. Consider using the prop value directly or adding a useEffect to sync state when selectedIndex changes.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is up for discussion for backpack owners.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hi, good point — duplicated state can cause sync issues. Switching to a fully controlled API would be a breaking change, so we can’t do that immediately. As a pragmatic step, we’ll create a ticket to discuss deprecating internal state

@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4079 to see this build running in a browser.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4079 to see this build running in a browser.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4079 to see this build running in a browser.

@skyscanner-backpack-bot
Copy link

Visit https://backpack.github.io/storybook-prs/4079 to see this build running in a browser.

Copy link
Contributor

@IrinaWei IrinaWei left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

Choose a reason for hiding this comment

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

Hi Noel Rajan (@FireRedNinja)!
Thanks for contributing, really appreciated.

Considering all our consumers, we might want to consider to support both tab/non-tab behaviours for this component, is there a way to keep the original segmented control interaction pattern without forcing our consumers to implement tab panel?

(In the case of flight results, this component is used as a radio button to apply filters)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor Non breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants