Skip to content

Commit

Permalink
Fix: (CXSPA-1128) - Ng-select screen reader double stop on mobile dev…
Browse files Browse the repository at this point in the history
…ices fix. (#19065)

Co-authored-by: Miguel Estrada <[email protected]>
  • Loading branch information
Pio-Bar and developpeurweb authored Aug 2, 2024
1 parent f715ba4 commit 10910dc
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,11 @@ export interface FeatureTogglesInterface {
*/
a11yLinkBtnsToTertiaryBtns?: boolean;

/**
* Modifies the 'NgSelectA11yDirective' to improve the sorting dropdown screen reader experience on mobile devices.
*/
a11yNgSelectMobileReadout?: boolean;

/**
* In OCC cart requests, it puts parameters of a cart name and cart description
* into a request body, instead of query params.
Expand Down Expand Up @@ -471,6 +476,7 @@ export const defaultFeatureToggles: Required<FeatureTogglesInterface> = {
a11yCxMessageFocus: false,
a11yLinkBtnsToTertiaryBtns: false,
a11yDeliveryModeRadiogroup: false,
a11yNgSelectMobileReadout: false,
occCartNameAndDescriptionInHttpRequestBody: false,
cmsBottomHeaderSlotUsingFlexStyles: false,
};
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import { WishListFeatureModule } from './features/cart/wish-list-feature.module'
import { CdcFeatureModule } from './features/cdc/cdc-feature.module';
import { CdsFeatureModule } from './features/cds/cds-feature.module';
import { CheckoutFeatureModule } from './features/checkout/checkout-feature.module';
import { CpqQuoteFeatureModule } from './features/cpq-quote/cpq-quote-feature.module';
import { CustomerTicketingFeatureModule } from './features/customer-ticketing/customer-ticketing-feature.module';
import { DigitalPaymentsFeatureModule } from './features/digital-payments/digital-payments-feature.module';
import { EpdVisualizationFeatureModule } from './features/epd-visualization/epd-visualization-feature.module';
Expand All @@ -95,14 +96,13 @@ import { QualtricsFeatureModule } from './features/qualtrics/qualtrics-feature.m
import { QuoteFeatureModule } from './features/quote-feature.module';
import { OrganizationUserRegistrationFeatureModule } from './features/registration-feature.module';
import { RequestedDeliveryDateFeatureModule } from './features/requested-delivery-date/requested-delivery-date-feature.module';
import { S4ServiceFeatureModule } from './features/s4-service/s4-service-feature.module';
import { S4OMFeatureModule } from './features/s4om/s4om-feature.module';
import { SegmentRefsFeatureModule } from './features/segment-refs/segment-refs-feature.module';
import { SmartEditFeatureModule } from './features/smartedit/smartedit-feature.module';
import { StorefinderFeatureModule } from './features/storefinder/storefinder-feature.module';
import { TrackingFeatureModule } from './features/tracking/tracking-feature.module';
import { UserFeatureModule } from './features/user/user-feature.module';
import { S4ServiceFeatureModule } from './features/s4-service/s4-service-feature.module';
import { CpqQuoteFeatureModule } from './features/cpq-quote/cpq-quote-feature.module';

const featureModules = [];

Expand Down Expand Up @@ -340,6 +340,7 @@ if (environment.cpq) {
occCartNameAndDescriptionInHttpRequestBody: true,
a11yLinkBtnsToTertiaryBtns: true,
a11yDeliveryModeRadiogroup: true,
a11yNgSelectMobileReadout: true,
cmsBottomHeaderSlotUsingFlexStyles: true,
};
return appFeatureToggles;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { Component, DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NgSelectA11yModule } from './ng-select-a11y.module';
import { NgSelectA11yDirective } from './ng-select-a11y.directive';
import { NgSelectModule } from '@ng-select/ng-select';
import { By } from '@angular/platform-browser';
import { NgSelectModule } from '@ng-select/ng-select';
import { FeatureConfigService } from '@spartacus/core';
import { NgSelectA11yDirective } from './ng-select-a11y.directive';
import { NgSelectA11yModule } from './ng-select-a11y.module';

@Component({
template: `
<ng-select
[searchable]="isSearchable"
[cxNgSelectA11y]="{ ariaLabel: 'Size', ariaControls: 'size-results' }"
>
<ng-option *ngFor="let val of [1, 2, 3]" [value]="val">{{
Expand All @@ -17,8 +19,15 @@ import { By } from '@angular/platform-browser';
<div id="size-results"></div>
`,
})
class MockComponent {}
class MockComponent {
isSearchable: boolean = false;
}

class MockFeatureConfigService {
isEnabled() {
return true;
}
}
describe('NgSelectA11yDirective', () => {
let component: MockComponent;
let fixture: ComponentFixture<MockComponent>;
Expand All @@ -27,6 +36,9 @@ describe('NgSelectA11yDirective', () => {
TestBed.configureTestingModule({
imports: [NgSelectA11yModule, NgSelectModule],
declarations: [MockComponent],
providers: [
{ provide: FeatureConfigService, useClass: MockFeatureConfigService },
],
}).compileComponents();

fixture = TestBed.createComponent(MockComponent);
Expand All @@ -41,13 +53,14 @@ describe('NgSelectA11yDirective', () => {
it('should create ng-select and bind aria attributes', () => {
fixture.detectChanges();
expect(component).toBeTruthy();
const select = getNgSelect().nativeElement;

const select = getNgSelect().nativeElement;
const innerDiv = select.querySelector("[role='combobox']");
const inputElement = select.querySelector('input');

expect(innerDiv).toBeTruthy();

expect(innerDiv.getAttribute('aria-controls')).toEqual('size-results');
expect(innerDiv.getAttribute('aria-label')).toEqual('Size');
expect(inputElement.getAttribute('aria-hidden')).toEqual('true');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import {
AfterViewInit,
Directive,
ElementRef,
inject,
Input,
Renderer2,
} from '@angular/core';
import { FeatureConfigService } from '@spartacus/core';

@Directive({
selector: '[cxNgSelectA11y]',
Expand All @@ -23,6 +25,8 @@ export class NgSelectA11yDirective implements AfterViewInit {
*/
@Input() cxNgSelectA11y: { ariaLabel?: string; ariaControls?: string };

private featureConfigService = inject(FeatureConfigService);

constructor(
private renderer: Renderer2,
private elementRef: ElementRef
Expand All @@ -31,6 +35,7 @@ export class NgSelectA11yDirective implements AfterViewInit {
ngAfterViewInit(): void {
const divCombobox =
this.elementRef.nativeElement.querySelector('[role="combobox"]');
const inputElement = divCombobox.querySelector('input');

const ariaLabel = this.cxNgSelectA11y.ariaLabel;
const elementId = this.elementRef.nativeElement.id;
Expand All @@ -43,5 +48,12 @@ export class NgSelectA11yDirective implements AfterViewInit {
if (ariaControls) {
this.renderer.setAttribute(divCombobox, 'aria-controls', ariaControls);
}

if (
this.featureConfigService.isEnabled('a11yNgSelectMobileReadout') &&
inputElement.readOnly
) {
this.renderer.setAttribute(inputElement, 'aria-hidden', 'true');
}
}
}

0 comments on commit 10910dc

Please sign in to comment.