fix(tag tag-list): Improve tag-list accessibility#3214
Conversation
🦋 Changeset detectedLatest commit: f19371c The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
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 |
There was a problem hiding this comment.
Pull request overview
This PR aims to improve accessibility for the sl-tag component (particularly when tags are removable) by shifting removal interaction to an explicit, labeled remove button and updating related localization, styles, stories, and tests.
Changes:
- Replaced the previous “press Backspace/Delete” ARIA instruction with an explicit remove button
aria-label(localized) and updated NL locale resources accordingly. - Updated
sl-tagfocus handling and styling to support a host-level focus outline via custom states anddelegatesFocus. - Adjusted Storybook stories and component tests to reflect the new removable/disabled behaviors.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/locales/src/nl.xlf | Removes old removal-instructions string; adds new sl.tag.remove translation. |
| packages/locales/src/nl.ts | Removes old key and adds a new remove-label entry (currently mismatched vs XLF/component id). |
| packages/components/tag/src/tag.ts | Implements accessible remove button labeling and new focus handling; removes old ARIA description logic. |
| packages/components/tag/src/tag.stories.ts | Simplifies max-width styling and adds a removable+disabled story. |
| packages/components/tag/src/tag.spec.ts | Updates/extends tests for reflectable removable, focus delegation, and remove button labeling/disabled behavior. |
| packages/components/tag/src/tag.scss | Switches focus styling to :state(focus-visible) and tweaks button outline/disabled interaction behavior. |
🕸 Website previewYou can view a preview here (commit |
🕸 Storybook previewYou can view a preview here (commit |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
packages/components/tag/src/tag-list.ts:346
tag.role = 'listitem'andtag.setAttribute('role', 'listitem')are redundant because the IDLroleproperty reflects to theroleattribute. Keeping only one avoids duplication and makes it clearer where the role is set.
tag.role = 'listitem';
tag.size = this.size;
tag.variant = this.variant;
tag.setAttribute('role', 'listitem');
});
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
packages/components/tag/src/tag.ts:184
- Tooltip visibility is only recalculated from the
ResizeObservercallback. If the slotted label text changes (slotchange) without affecting the host element's size,ResizeObservermay not fire andthis.tooltipcan become stale. Consider recalculating overflow (or scheduling#onResize()) after updatingthis.labelin#onSlotChange.
#onSlotChange(event: Event & { target: HTMLSlotElement }): void {
this.label = event.target
.assignedNodes({ flatten: true })
.filter(node => node.nodeType === Node.TEXT_NODE)
.map(node => node.textContent?.trim())
.join('');
}
michal-sanoma
left a comment
There was a problem hiding this comment.
suggestion: Small a11y/UX concern: because #onFocus() always adds focus-visible, the host behaves like :focus instead of native :focus-visible. Would it make sense to track input source and apply the ring only for keyboard interaction?
a11ymiko
left a comment
There was a problem hiding this comment.
For Stacked variants keyboard user cannot set focus on tag with tooltip. sl-tag has tabindex=0 but keyboard focus cannot be place on this tag.
a11ymiko
left a comment
There was a problem hiding this comment.
For Stacked Removable variant user cannot place focus on any tag. This happens on Safari, Chrome and Firefox on macOS and Edge and Chrome on Win11. On Firefox on Win11 user can place focus on some removable tag, but it's not the first one in the list.
Screen.Recording.2026-04-22.at.08.48.35.mov
a11ymiko
left a comment
There was a problem hiding this comment.
Minor issue but on Chrome on macOS tag with Overflow has it's content announced twice (once from tag text and once from tooltip text). Not adding 'aria-describedby' to div in Overflow sl-tag will fix that issue in Chrome without making an issue for other OSes and browsers.
What changed
This PR improves the accessibility of
<sl-tag>and<sl-tag-list>, especially for removable tags, disabled removable tags, keyboard navigation, and screen reader users.Closes #2868 #2869
<sl-tag><button>instead of the host tag.Remove tag '<label>'.aria-hidden="true"from the remove button.type="button"to prevent accidental form submissions.aria-disabled="true"instead of nativedisabled, so the action remains discoverable to assistive technologies.focus()override:<div part="label">.@csspart labeland@csspart buttondocumentation.removableproperty to support CSS selectors.aria-describedbyon the label part.<sl-tag-list>role="list"on the tag list androle="listitem"on slotted tags.aria-disabled.@customElement sl-tag-listJSDoc.<sl-combobox>integration with removable tags<sl-tag-list>so keyboard focus uses the real remove buttons from the tag list instead of competing with the combobox's older fake tag focus state.focusedTagstate when focus enters the tag list, avoiding two visible focus indicators at once.Locales
sl.tag.removalInstructionskey.sl.tag.remove.sl.tagList.navigationInstructions.es-ES,it,nl, andpl.Stories and docs
OverflowRemovablestory.RemovableDisabledstories.Website accessibility follow-ups
aria-current="page".sl-tabpage navigation issue so page content remains covered.Tests
Updated and expanded
<sl-tag>tests for:Updated and expanded
<sl-tag-list>tests for: