-
Notifications
You must be signed in to change notification settings - Fork 140
Prevent focus in collapsed card content in CardList #2719
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| '@siemens/ix': patch | ||
| --- | ||
|
|
||
| Prevent focus from remaining inside collapsed card lists |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ import { | |
| Listen, | ||
| Prop, | ||
| State, | ||
| Watch, | ||
| } from '@stencil/core'; | ||
| import { createMutationObserver } from '../utils/mutation-observer'; | ||
| import { iconChevronUp, iconMoreMenu } from '@siemens/ix-icons/icons'; | ||
|
|
@@ -25,6 +26,7 @@ function CardListTitle(props: { | |
| labelShowLess: string; | ||
| showLess: boolean; | ||
| hideShowAll: boolean; | ||
| collapseButtonRef: (element?: HTMLIxIconButtonElement) => void; | ||
| }) { | ||
| if (!props.label) { | ||
| return null; | ||
|
|
@@ -42,6 +44,7 @@ function CardListTitle(props: { | |
| CardList__Title__Button__Collapsed: props.isCollapsed, | ||
| }} | ||
| aria-label={props.ariaLabelExpandButton} | ||
| ref={props.collapseButtonRef} | ||
| ></ix-icon-button> | ||
| <ix-typography class="CardList_Title__Label" format="body-lg"> | ||
| {props.label} | ||
|
|
@@ -178,6 +181,19 @@ export class CardList { | |
|
|
||
| private observer?: MutationObserver; | ||
|
|
||
| private collapseButton?: HTMLIxIconButtonElement; | ||
|
|
||
| @Watch('collapse') | ||
| protected handleCollapseChange(isCollapsed: boolean) { | ||
| if (isCollapsed && this.hasFocusWithinListContent()) { | ||
| this.collapseButton?.focus(); | ||
| } | ||
| } | ||
|
|
||
| private hasFocusWithinListContent() { | ||
| return this.listElement?.matches(':focus-within') ?? false; | ||
| } | ||
|
|
||
| private onCardListVisibilityToggle() { | ||
| this.collapse = !this.collapse; | ||
| this.collapseChanged.emit(this.collapse); | ||
|
|
@@ -415,6 +431,7 @@ export class CardList { | |
| <CardListTitle | ||
| isCollapsed={this.collapse} | ||
| label={this.label} | ||
| ariaLabelExpandButton={this.ariaLabelExpandButton} | ||
| showAllLabel={this.i18nShowAll} | ||
| showAllCounter={ | ||
| this.showAllCount === undefined | ||
|
|
@@ -426,6 +443,7 @@ export class CardList { | |
| onClick={() => this.onCardListVisibilityToggle()} | ||
| onShowAllClick={(e) => this.onShowAllClick(e)} | ||
| hideShowAll={this.hideShowAll} | ||
| collapseButtonRef={(element) => (this.collapseButton = element)} | ||
| ></CardListTitle> | ||
| <div | ||
| class={{ | ||
|
|
@@ -441,6 +459,7 @@ export class CardList { | |
| CardList__Style__Infinite__Scroll: this.listStyle === 'scroll', | ||
| }} | ||
| onScroll={() => this.onCardListScroll()} | ||
| inert={this.collapse} | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ๐ Maintainability & Code Quality | ๐ก Minor | โก Quick win Add a consumer-facing changeset. This changes the public accessibility behavior of As per coding guidelines, "Update tests, documentation, examples, and changesets when user-facing behavior, APIs, styling, accessibility, or package output changes." As per path instructions, "Changesets are required for public API updates, behavior changes, styling/theming changes, accessibility changes, and bug fixes with user impact." ๐ค Prompt for AI AgentsSources: Coding guidelines, Path instructions |
||
| > | ||
| <slot | ||
| onSlotchange={() => { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
๐ฏ Functional Correctness | ๐ Major | โก Quick win
Provide a focus destination when
labelis absent.labelis optional, butCardListTitlereturnsnullwithout it. In that configuration,collapseButtonis undefined. The optional call does nothing, and Line 464 then makes the focused content inert.Render a stable focus target for collapsible lists without a label, or enforce and document a label requirement before allowing collapse. Add regression coverage for this configuration.
As per coding guidelines, "Keep accessibility behavior consistent across frameworks and treat public APIs, accessibility behavior, theming tokens, and generated package output as consumer contracts." As per path instructions, "Prioritize correctness, regressions, accessibility, release impact, and missing validation."
๐ค Prompt for AI Agents
Sources: Coding guidelines, Path instructions