From d1abd3782ca277ba41dba4b5811e5c9d6b6d885f Mon Sep 17 00:00:00 2001 From: coutin Date: Sat, 3 Dec 2016 03:24:39 +0100 Subject: [PATCH] feat(accordion): add aria-selected Closes #1109 --- src/accordion/accordion.spec.ts | 39 +++++++++++++++++++++++++++- src/accordion/accordion.ts | 45 +++++++++++++++++++-------------- 2 files changed, 64 insertions(+), 20 deletions(-) diff --git a/src/accordion/accordion.spec.ts b/src/accordion/accordion.spec.ts index 20ca20704b..4a1239be53 100644 --- a/src/accordion/accordion.spec.ts +++ b/src/accordion/accordion.spec.ts @@ -1,4 +1,5 @@ import {TestBed, ComponentFixture, inject} from '@angular/core/testing'; +import {By} from '@angular/platform-browser'; import {createGenericTestComponent} from '../test/common'; import {Component} from '@angular/core'; @@ -30,6 +31,14 @@ function expectOpenPanels(nativeEl: HTMLElement, openPanelsDef: boolean[]) { expect(result).toEqual(openPanelsDef); } +function expectAriaSelected(nativeEl: HTMLElement, ariaSelectedPanelsDef: boolean[]) { + const panels = getPanels(nativeEl); + expect(panels.length).toBe(ariaSelectedPanelsDef.length); + + const result = panels.map(panel => (panel.getAttribute('aria-selected') === 'true')); + expect(result).toEqual(ariaSelectedPanelsDef); +} + describe('ngb-accordion', () => { let html = ` { it('should have no open panels', () => { const fixture = TestBed.createComponent(TestComponent); const accordionEl = fixture.nativeElement.children[0]; + const el = fixture.nativeElement; fixture.detectChanges(); - expectOpenPanels(fixture.nativeElement, [false, false, false]); + expectOpenPanels(el, [false, false, false]); + expectAriaSelected(el, [false, false, false]); expect(accordionEl.getAttribute('role')).toBe('tablist'); expect(accordionEl.getAttribute('aria-multiselectable')).toBe('true'); }); @@ -318,6 +329,32 @@ describe('ngb-accordion', () => { expect(el[2]).toHaveCssClass('card-warning'); }); + it('should toggle aria-selected attribute of the focused panel', () => { + const fixture = TestBed.createComponent(TestComponent); + fixture.detectChanges(); + + const headingLinks = fixture.debugElement.queryAll(By.css('.card-header a')); + + headingLinks[0].triggerEventHandler('focus', {}); + fixture.detectChanges(); + expectAriaSelected(fixture.nativeElement, [true, false, false]); + + headingLinks[0].triggerEventHandler('blur', {}); + headingLinks[1].triggerEventHandler('focus', {}); + fixture.detectChanges(); + expectAriaSelected(fixture.nativeElement, [false, true, false]); + + headingLinks[1].triggerEventHandler('blur', {}); + headingLinks[2].triggerEventHandler('focus', {}); + fixture.detectChanges(); + expectAriaSelected(fixture.nativeElement, [false, false, true]); + + headingLinks[2].triggerEventHandler('blur', {}); + headingLinks[1].triggerEventHandler('focus', {}); + fixture.detectChanges(); + expectAriaSelected(fixture.nativeElement, [false, true, false]); + }); + describe('Custom config', () => { let config: NgbAccordionConfig; diff --git a/src/accordion/accordion.ts b/src/accordion/accordion.ts index 3e3f7c08ce..270e9c5a8d 100644 --- a/src/accordion/accordion.ts +++ b/src/accordion/accordion.ts @@ -1,16 +1,18 @@ import { + AfterContentChecked, Component, - Input, - QueryList, + ContentChild, ContentChildren, Directive, - TemplateRef, - ContentChild, - Output, EventEmitter, - AfterContentChecked + Input, + Output, + QueryList, + TemplateRef } from '@angular/core'; + import {isString} from '../util/util'; + import {NgbAccordionConfig} from './accordion-config'; let nextId = 0; @@ -37,6 +39,11 @@ export class NgbPanelContent { */ @Directive({selector: 'ngb-panel'}) export class NgbPanel { + /** + * Defines if the tab control is focused + */ + focused: boolean = false; + /** * A flag determining whether the panel is disabled or not. * When disabled, the panel cannot be toggled. @@ -95,9 +102,10 @@ export interface NgbPanelChangeEvent { template: `