From bc419d98b8534df93446189e7758deb22cde1154 Mon Sep 17 00:00:00 2001 From: olshansky Date: Tue, 8 Jun 2021 10:35:38 +0300 Subject: [PATCH 1/5] fix(core): styles of group popover control & a11y issues --- apps/docs/src/app/core/api-files.ts | 1 + ...ar-group-group-type-example.component.html | 17 ++++++-- ...oup-individual-type-example.component.html | 42 ++++++++++++------- .../lib/avatar-group/avatar-group.module.ts | 3 ++ ...ar-group-popover-control.directive.spec.ts | 38 +++++++++++++++++ .../avatar-group-popover-control.directive.ts | 19 +++++++++ 6 files changed, 102 insertions(+), 18 deletions(-) create mode 100644 libs/core/src/lib/avatar-group/directives/avatar-group-popover-control.directive.spec.ts create mode 100644 libs/core/src/lib/avatar-group/directives/avatar-group-popover-control.directive.ts diff --git a/apps/docs/src/app/core/api-files.ts b/apps/docs/src/app/core/api-files.ts index f909863d3ee..ac2e338bc7d 100644 --- a/apps/docs/src/app/core/api-files.ts +++ b/apps/docs/src/app/core/api-files.ts @@ -26,6 +26,7 @@ export const API_FILES = { 'AvatarGroupComponent', 'AvatarGroupItemDirective', 'AvatarGroupFocusableAvatarDirective', + 'AvatarGroupPopoverControlDirective', 'AvatarGroupOverflowBodyDirective', 'AvatarGroupOverflowItemDirective', 'AvatarGroupOverflowButtonDirective', diff --git a/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-group-type-example.component.html b/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-group-type-example.component.html index 267c0513a0f..a46ef1bde21 100644 --- a/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-group-type-example.component.html +++ b/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-group-type-example.component.html @@ -9,13 +9,16 @@ placement="bottom" maxWidth="312" #overflowPopover> -
+ [label]="personDetails.firstName + ' ' + personDetails.lastName" + [title]="personDetails.firstName + ' ' + personDetails.lastName" + [ariaLabel]="personDetails.firstName + ' ' + personDetails.lastName + ' avatar'"> {{ personDetails.firstName }} {{ personDetails.lastName }} {{ personDetails.position }} diff --git a/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-individual-type-example.component.html b/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-individual-type-example.component.html index 8728c8cb1aa..a714acb78bb 100644 --- a/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-individual-type-example.component.html +++ b/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-individual-type-example.component.html @@ -20,7 +20,8 @@ [size]="size" role="img" [title]="person.firstName + ' ' + person.lastName" - [label]="person.firstName + ' ' + person.lastName"> + [label]="person.firstName + ' ' + person.lastName" + [ariaLabel]="person.firstName + ' ' + person.lastName + ' avatar'"> + [title]="person.firstName + ' ' + person.lastName" + [ariaLabel]="person.firstName + ' ' + person.lastName + ' avatar'"> + [title]="person.firstName + ' ' + person.lastName" + [ariaLabel]="person.firstName + ' ' + person.lastName + ' avatar'">
@@ -47,23 +50,26 @@ + [label]="person.firstName + ' ' + person.lastName" + [title]="person.firstName + ' ' + person.lastName" + [ariaLabel]="person.firstName + ' ' + person.lastName + ' avatar'"> + [image]="person.imageUrl" + [title]="person.firstName + ' ' + person.lastName" + [ariaLabel]="person.firstName + ' ' + person.lastName + ' avatar'"> + [glyph]="person.glyph" + [title]="person.firstName + ' ' + person.lastName" + [ariaLabel]="person.firstName + ' ' + person.lastName + ' avatar'"> {{ person.firstName }} {{ person.lastName }} {{ person.position }} @@ -151,9 +157,10 @@ fd-avatar-group-focusable-avatar [circle]="true" size="s" - [label]="person.firstName + ' ' + person.lastName" role="img" + [label]="person.firstName + ' ' + person.lastName" [title]="person.firstName + ' ' + person.lastName" + [ariaLabel]="person.firstName + ' ' + person.lastName + ' avatar'" (click)="openOverflowDetails(idx)" (keydown.enter)="openOverflowDetails(idx)" (keydown.space)="openOverflowDetails(idx)" @@ -163,9 +170,10 @@ fd-avatar-group-focusable-avatar [circle]="true" size="s" - [image]="person.imageUrl" role="img" + [image]="person.imageUrl" [title]="person.firstName + ' ' + person.lastName" + [ariaLabel]="person.firstName + ' ' + person.lastName + ' avatar'" (click)="openOverflowDetails(idx)" (keydown.enter)="openOverflowDetails(idx)" (keydown.space)="openOverflowDetails(idx)" @@ -175,9 +183,10 @@ fd-avatar-group-focusable-avatar [circle]="true" size="s" - [glyph]="person.glyph" role="img" + [glyph]="person.glyph" [title]="person.firstName + ' ' + person.lastName" + [ariaLabel]="person.firstName + ' ' + person.lastName + ' avatar'" (click)="openOverflowDetails(idx)" (keydown.enter)="openOverflowDetails(idx)" (keydown.space)="openOverflowDetails(idx)" @@ -193,21 +202,24 @@ size="s" [label]="personDetails.firstName + ' ' + personDetails.lastName" role="img" - [title]="personDetails.firstName + ' ' + personDetails.lastName"> + [title]="personDetails.firstName + ' ' + personDetails.lastName" + [ariaLabel]="personDetails.firstName + ' ' + personDetails.lastName + ' avatar'"> + [title]="personDetails.firstName + ' ' + personDetails.lastName" + [ariaLabel]="personDetails.firstName + ' ' + personDetails.lastName + ' avatar'"> + [title]="personDetails.firstName + ' ' + personDetails.lastName" + [ariaLabel]="personDetails.firstName + ' ' + personDetails.lastName + ' avatar'"> {{ personDetails.firstName }} {{ personDetails.lastName }} {{ personDetails.position }} diff --git a/libs/core/src/lib/avatar-group/avatar-group.module.ts b/libs/core/src/lib/avatar-group/avatar-group.module.ts index 51da9a32124..a094c710ff1 100644 --- a/libs/core/src/lib/avatar-group/avatar-group.module.ts +++ b/libs/core/src/lib/avatar-group/avatar-group.module.ts @@ -8,6 +8,7 @@ import { AvatarGroupOverflowItemDirective } from './directives/avatar-group-over import { AvatarGroupOverflowButtonDirective } from './directives/avatar-group-overflow-button.directive'; import { AvatarGroupOverflowButtonTextDirective } from './directives/avatar-group-overflow-button-text.directive'; import { AvatarGroupFocusableAvatarDirective } from './directives/avatar-group-focusable-avatar.directive'; +import { AvatarGroupPopoverControlDirective } from './directives/avatar-group-popover-control.directive'; @NgModule({ imports: [CommonModule], @@ -15,6 +16,7 @@ import { AvatarGroupFocusableAvatarDirective } from './directives/avatar-group-f AvatarGroupComponent, AvatarGroupItemDirective, AvatarGroupFocusableAvatarDirective, + AvatarGroupPopoverControlDirective, AvatarGroupOverflowBodyDirective, AvatarGroupOverflowItemDirective, AvatarGroupOverflowButtonDirective, @@ -24,6 +26,7 @@ import { AvatarGroupFocusableAvatarDirective } from './directives/avatar-group-f AvatarGroupComponent, AvatarGroupItemDirective, AvatarGroupFocusableAvatarDirective, + AvatarGroupPopoverControlDirective, AvatarGroupOverflowBodyDirective, AvatarGroupOverflowItemDirective, AvatarGroupOverflowButtonDirective, diff --git a/libs/core/src/lib/avatar-group/directives/avatar-group-popover-control.directive.spec.ts b/libs/core/src/lib/avatar-group/directives/avatar-group-popover-control.directive.spec.ts new file mode 100644 index 00000000000..398392cda78 --- /dev/null +++ b/libs/core/src/lib/avatar-group/directives/avatar-group-popover-control.directive.spec.ts @@ -0,0 +1,38 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; +import { Component, ElementRef, ViewChild } from '@angular/core'; + +import { AvatarGroupModule } from '../avatar-group.module'; + +@Component({ + template: `` +}) +class TestComponent { + @ViewChild('directiveElement', { static: false }) + ref: ElementRef; +} + +describe('AvatarGroupPopoverControlDirective', () => { + let component: TestComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [TestComponent], + imports: [AvatarGroupModule] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TestComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should assign class', () => { + expect(component.ref.nativeElement).toHaveClass('fd-avatar-group__popover-control'); + }); +}); diff --git a/libs/core/src/lib/avatar-group/directives/avatar-group-popover-control.directive.ts b/libs/core/src/lib/avatar-group/directives/avatar-group-popover-control.directive.ts new file mode 100644 index 00000000000..06766ccc23a --- /dev/null +++ b/libs/core/src/lib/avatar-group/directives/avatar-group-popover-control.directive.ts @@ -0,0 +1,19 @@ +import { Directive, HostBinding, Input } from '@angular/core'; + +/** Needed to bind specific class to group type popover control. */ +@Directive({ + // tslint:disable-next-line:directive-selector + selector: '[fd-avatar-group-popover-control]', + host: { class: 'fd-avatar-group__popover-control' } +}) +export class AvatarGroupPopoverControlDirective { + /** Tabindex of the popover control. */ + @Input() + @HostBinding('attr.tabindex') + tabindex = 0; + + /** Role of the popover control. */ + @Input() + @HostBinding('attr.role') + role = 'button'; +} From e3821763dbe966ce010209f976a026090e210205 Mon Sep 17 00:00:00 2001 From: olshansky Date: Tue, 8 Jun 2021 17:40:41 +0300 Subject: [PATCH 2/5] docs(core): focus trap on individual item --- .../avatar-group/avatar-group-docs.module.ts | 2 ++ .../avatar-group-group-type-example.component.html | 6 +++--- ...ar-group-individual-type-example.component.html | 14 ++++++++------ 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/apps/docs/src/app/core/component-docs/avatar-group/avatar-group-docs.module.ts b/apps/docs/src/app/core/component-docs/avatar-group/avatar-group-docs.module.ts index 81d9dc201f0..3275188c75e 100644 --- a/apps/docs/src/app/core/component-docs/avatar-group/avatar-group-docs.module.ts +++ b/apps/docs/src/app/core/component-docs/avatar-group/avatar-group-docs.module.ts @@ -16,6 +16,7 @@ import { PopoverModule } from '@fundamental-ngx/core/popover'; import { QuickViewModule } from '@fundamental-ngx/core/quick-view'; import { BarModule } from '@fundamental-ngx/core/bar'; import { TitleModule } from '@fundamental-ngx/core/title'; +import { LinkModule } from '@fundamental-ngx/core/link'; const routes: Routes = [ { @@ -38,6 +39,7 @@ const routes: Routes = [ PopoverModule, QuickViewModule, BarModule, + LinkModule, TitleModule ], exports: [RouterModule], diff --git a/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-group-type-example.component.html b/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-group-type-example.component.html index a46ef1bde21..2f026da3e33 100644 --- a/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-group-type-example.component.html +++ b/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-group-type-example.component.html @@ -153,21 +153,21 @@ Phone - + Mobile - + Email - + diff --git a/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-individual-type-example.component.html b/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-individual-type-example.component.html index a714acb78bb..7e233c02722 100644 --- a/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-individual-type-example.component.html +++ b/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-individual-type-example.component.html @@ -8,6 +8,8 @@ [triggers]="[]" [closeOnOutsideClick]="true" [closeOnEscapeKey]="true" + [focusAutoCapture]="true" + [focusTrapped]="true" #individualPopover>
Phone - + Mobile - + Email - + @@ -229,21 +231,21 @@ Phone - + Mobile - + Email - + From ef492873c41adc73b665872a56013826cc897e08 Mon Sep 17 00:00:00 2001 From: olshansky Date: Wed, 9 Jun 2021 09:01:54 +0300 Subject: [PATCH 3/5] chore(core): export avatar-group-popover-control directive --- libs/core/src/lib/avatar-group/public_api.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/core/src/lib/avatar-group/public_api.ts b/libs/core/src/lib/avatar-group/public_api.ts index a8201a9499e..fdcf8062ff2 100644 --- a/libs/core/src/lib/avatar-group/public_api.ts +++ b/libs/core/src/lib/avatar-group/public_api.ts @@ -2,6 +2,7 @@ export * from './avatar-group.module'; export * from './avatar-group.component'; export * from './directives/avatar-group-item.directive'; export * from './directives/avatar-group-focusable-avatar.directive'; +export * from './directives/avatar-group-popover-control.directive'; export * from './directives/avatar-group-overflow-body.directive'; export * from './directives/avatar-group-overflow-item.directive'; export * from './directives/avatar-group-overflow-button.directive'; From bbe69ef0ab07016318f62571f66086a8e7dd4e2d Mon Sep 17 00:00:00 2001 From: olshansky Date: Mon, 14 Jun 2021 18:15:04 +0300 Subject: [PATCH 4/5] fix(core): fix id binding and add label for popover in Avatar Group --- .../avatar-group-group-type-example.component.html | 5 +++-- .../avatar-group-individual-type-example.component.html | 9 +++++---- libs/core/src/lib/avatar-group/avatar-group.component.ts | 2 -- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-group-type-example.component.html b/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-group-type-example.component.html index 2f026da3e33..14636c651c7 100644 --- a/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-group-type-example.component.html +++ b/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-group-type-example.component.html @@ -46,13 +46,14 @@ fd-button fd-avatar-group-overflow-button tabindex="-1" + [compact]="false" [size]="size"> +{{ avatarGroup_GroupType.overflowItemsCount }} - +
@@ -64,7 +65,7 @@ aria-label="Back" title="Back" > - + {{ isDetailStage ? 'Business Card' : 'Team Members (' + people.length + ')' }}   diff --git a/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-individual-type-example.component.html b/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-individual-type-example.component.html index 7e233c02722..bf46e8eb695 100644 --- a/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-individual-type-example.component.html +++ b/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-individual-type-example.component.html @@ -45,9 +45,9 @@
- + - Business card + Business card - +
@@ -139,7 +140,7 @@ aria-label="Back" title="Back" > - + {{ isDetailStage ? 'Business Card' : 'Team Members (' + avatarGroup_IndividualType.overflowItemsCount + ')' }}   diff --git a/libs/core/src/lib/avatar-group/avatar-group.component.ts b/libs/core/src/lib/avatar-group/avatar-group.component.ts index 1ad6ee58ec4..134f75b1c1f 100644 --- a/libs/core/src/lib/avatar-group/avatar-group.component.ts +++ b/libs/core/src/lib/avatar-group/avatar-group.component.ts @@ -5,7 +5,6 @@ import { ContentChildren, ElementRef, forwardRef, - HostBinding, Input, OnChanges, OnDestroy, @@ -37,7 +36,6 @@ let avatarGroupUniqueId = 0; export class AvatarGroupComponent implements OnChanges, OnInit, AfterViewInit, OnDestroy { /** Id of the Avatar Group. */ @Input() - @HostBinding('attr.id') id = `fd-avatar-group-${avatarGroupUniqueId++}`; /** Apply user custom class. */ From 65b000de9e0098f3657a4afcd47c57c7a8c16da1 Mon Sep 17 00:00:00 2001 From: olshansky Date: Wed, 16 Jun 2021 17:11:02 +0300 Subject: [PATCH 5/5] docs(core): corresponding labels and description for individual details --- ...vatar-group-individual-type-example.component.html | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-individual-type-example.component.html b/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-individual-type-example.component.html index bf46e8eb695..1565bb85da5 100644 --- a/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-individual-type-example.component.html +++ b/apps/docs/src/app/core/component-docs/avatar-group/examples/avatar-group-individual-type-example.component.html @@ -45,10 +45,13 @@
- + Business card - + {{ person.position }} - - Contact Details + + Contact Details Phone