Skip to content

feat(chip): improve accessibility #IX-3654#2420

Open
alexkaduk wants to merge 1 commit intomainfrom
feature/IX-3654-chip-a11y
Open

feat(chip): improve accessibility #IX-3654#2420
alexkaduk wants to merge 1 commit intomainfrom
feature/IX-3654-chip-a11y

Conversation

@alexkaduk
Copy link
Collaborator

💡 What is the current behavior?

The chip component has several accessibility issues:

  1. Shadow DOM barrier: ARIA attributes on host element don't transfer to internal elements
  2. False affordances: Visual cues (cursor:pointer, hover) suggest full interactivity, but only close button is clickable
  3. Missing semantic structure: No roles for screen readers, icons not hidden
  4. Disconnected elements: In closable chips without aria-label, text and button appear unrelated in accessibility tree

GitHub Issue Number: #3654 | Jira: IX-3654

🆕 What is the new behavior?

Interactive Behavior

Type Role Tab Cursor Click Handler
Non-closable button ✅ (tabIndex="0") pointer Native onClick
Closable group ❌ (only close button) default N/A

Key Features

1. Auto-generated labels (PatternFly-inspired, Shadow DOM adapted)

<!-- Before: disconnected elements -->
- text: "Designer"
- button "Close"

<!-- After: semantic grouping -->
<ix-chip closable>Designer</ix-chip>
→ role="group" aria-label="Designer"

2. ARIA support via a11yHostAttributes utility

  • Standard attributes transfer from host to container
  • aria-disabled="true" for inactive state

3. Close button labels via new ariaLabelCloseButton prop

  • React: ariaLabelCloseButton="Remove tag" (camelCase)
  • HTML/Angular/Vue: aria-label-close-button="Remove tag" (kebab-case)

4. Fixed visual affordances

  • Non-closable: Interactive button with hover
  • Closable: Contextual hover only when close button hovered (:has())

5. Screen reader improvements

  • Icons always decorative (aria-hidden="true")
  • Tight focus outline (1px offset)

🏁 Checklist

A pull request can only be merged if all of these conditions are met (where applicable):

  • 🦮 Accessibility (a11y) features were implemented
    • ARIA attribute support via a11yHostAttributes
    • Auto-generated labels for closable chips
    • Icons always decorative
    • Interactive button behavior for non-closable chips
    • Proper semantic roles and tabindex
    • Tested with VoiceOver (macOS)
  • 🗺️ Internationalization (i18n) - no hard coded strings
    • All labels provided by users via props/attributes
  • 📲 Responsiveness - components handle viewport changes and content overflow gracefully
    • No changes to responsive behavior (existing behavior preserved)
  • 📕 Add or update a Storybook story
  • 📄 Documentation was reviewed/updated siemens/ix-docs
    • Needs docs team review - New ariaLabelCloseButton prop and auto-generation feature require documentation
  • 🧪 Unit tests were added/updated and pass (pnpm test)
    • Added 3 component tests for button role, group role, and auto-generated labels
    • Added accessibility tree snapshot test (toMatchAriaSnapshot)
    • All tests passing
  • 📸 Visual regression tests were added/updated and pass
    • Visual snapshots updated (cursor/hover changes expected)
  • 🧐 Static code analysis passes (pnpm lint)
    • Linter clean
  • 🏗️ Successful compilation (pnpm build, changes pushed)
    • Build successful

@changeset-bot
Copy link

changeset-bot bot commented Mar 4, 2026

🦋 Changeset detected

Latest commit: 07ebf70

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@siemens/ix Patch
@siemens/ix-angular Patch
@siemens/ix-docs Patch
@siemens/ix-react Patch
@siemens/ix-vue Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the accessibility of the ix-chip component by addressing several long-standing issues related to ARIA attributes, semantic structure, and interactive behavior. The changes ensure that chips are more usable and understandable for users relying on assistive technologies, while also refining visual feedback for all users.

Highlights

  • Enhanced ARIA Support: Implemented a11yHostAttributes utility to transfer standard ARIA attributes from the host element to the internal container, improving screen reader compatibility for ix-chip.
  • Auto-generated Labels for Closable Chips: Introduced logic to automatically generate aria-label from the chip's text content for closable chips if no explicit label is provided, ensuring semantic grouping for screen readers.
  • Improved Interactive Behavior and Visual Affordances: Non-closable chips now correctly behave as interactive buttons with appropriate role and tabIndex. Visual cues (cursor, hover, active states) are refined to accurately reflect interactivity, using CSS :has() for contextual feedback on closable chips.
  • Dedicated Close Button Label Prop: Added a new ariaLabelCloseButton prop to allow explicit labeling of the close button, enhancing clarity for assistive technologies.
  • Screen Reader Optimizations: Ensured all icons within chips are decorative by setting aria-hidden="true" and refined focus outlines for better visibility.
  • Comprehensive Testing and Documentation: Added new component tests for ARIA roles and labels, updated accessibility tree snapshots, and introduced a new Storybook file with accessibility-focused examples.
Changelog
  • .changeset/chip-a11y-improvements.md
    • Added a new changeset file for chip accessibility improvements.
  • packages/angular-standalone-test-app/src/preview-examples/chip.ts
    • Updated chip examples to include new aria-label and aria-label-close-button attributes and adjusted variant and color properties.
  • packages/angular-test-app/src/preview-examples/chip.ts
    • Updated chip examples to include new aria-label and aria-label-close-button attributes and adjusted variant and color properties.
  • packages/core/src/components/chip/chip-mixin.scss
    • Modified CSS to apply distinct cursor styles for closable and non-closable chips.
    • Adjusted hover and active background styles to differentiate between closable and non-closable chips, utilizing :has() for contextual close button interactions.
  • packages/core/src/components/chip/chip.tsx
    • Imported a11yHostAttributes utility for ARIA attribute handling.
    • Added componentWillLoad lifecycle hook to remove aria-label-close-button from the host element.
    • Integrated a11yHostAttributes into the render method to apply host ARIA attributes to the internal container.
    • Implemented logic to auto-generate aria-label for closable chips based on text content if not explicitly provided.
    • Dynamically determined the role attribute for the chip container, setting it to button for non-closable chips and group for closable chips with an effective label.
    • Set aria-disabled attribute based on the inactive prop.
    • Conditionally set tabIndex to 0 for non-closable chips.
    • Added aria-hidden="true" to icons within the chip to hide them from screen readers.
  • packages/core/src/components/chip/test/chip.ct.ts
    • Reordered imports for consistency.
    • Added regression tests to verify aria-label transfer from host to container.
    • Added regression tests to confirm role="button" for non-closable chips.
    • Added regression tests to confirm role="group" for closable chips with aria-label.
    • Added regression tests to verify auto-generation of aria-label for closable chips without explicit labels.
    • Added regression tests to check aria-disabled attribute when the chip is inactive.
  • packages/html-test-app/src/preview-examples/chip.html
    • Updated HTML examples to include new aria-label and aria-label-close-button attributes and adjusted variant and color properties.
  • packages/react-test-app/src/preview-examples/chip.tsx
    • Updated React examples to include new aria-label and ariaLabelCloseButton props and adjusted variant and color properties.
  • packages/storybook-docs/src/stories/chip/accessibility/a11y-chip.stories.ts
    • Added a new Storybook file dedicated to chip accessibility examples.
    • Included stories demonstrating basic chips with aria-label, closable chips with accessible close buttons, icons with and without labels, inactive states, and full accessibility features.
  • packages/vue-test-app/src/preview-examples/chip.vue
    • Updated Vue examples to include new aria-label and aria-label-close-button attributes and adjusted variant and color properties.
  • testing/framework-tests/snapshots/chip-aria-snapshot.yaml
    • Updated the accessibility tree snapshot to reflect the new ARIA roles and labels for chip components.
  • testing/framework-tests/tests/working-with-axe.spec.ts
    • Imported the generated chip-axe.spec for accessibility testing.
  • testing/framework-tests/tests/working.spec.ts
    • Imported the generated chip.spec for component testing.
Activity
  • Accessibility (a11y) features were implemented, including ARIA attribute support, auto-generated labels, decorative icons, interactive button behavior, and proper semantic roles/tabindex.
  • Internationalization (i18n) was considered, ensuring no hard-coded strings and all labels are provided via props/attributes.
  • Responsiveness was maintained, preserving existing behavior.
  • A new Storybook story (chip/accessibility/a11y-chip.stories.ts) was created with 7 accessibility-focused stories.
  • Unit tests were added/updated, including 3 component tests for roles and labels, and an accessibility tree snapshot test.
  • Visual regression tests were updated to account for cursor/hover changes.
  • Static code analysis passed without issues.
  • The project successfully compiled after changes.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request significantly improves the accessibility of the chip component by addressing several key issues. It correctly implements roles (button or group), manages ARIA attributes by transferring them from the host to the internal container, and introduces auto-generated labels for closable chips to create a more semantic structure for screen readers. The changes to interaction styles, such as adjusting the cursor and hover effects based on whether the chip is closable, fix false affordances and provide better user feedback. The addition of comprehensive accessibility tests and Storybook stories is also a great enhancement. I've found one area for improvement in the SCSS regarding code duplication, which I've commented on.

private closeButtonLabel?: string;

componentWillLoad() {
// Save the value BEFORE removing the attribute
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

pls suggest if it might make sense? how it can be imroved?
comments will be deleted after discussing.

@alexkaduk alexkaduk force-pushed the feature/IX-3654-chip-a11y branch from 03f51d9 to 07ebf70 Compare March 5, 2026 12:17
@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 5, 2026

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.

1 participant