Skip to content

Commit f979ac1

Browse files
authored
Merge pull request #2275 from Akshat55/ul-li
fix: bind attributes to host instead of adding unnecessary elements
2 parents 3f98978 + 3a804b4 commit f979ac1

12 files changed

+201
-175
lines changed

src/accordion/accordion-item.component.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,26 +39,25 @@ import {
3939
<p class="cds--skeleton__text" style="width: 95%"></p>
4040
</ng-template>
4141
</div>
42-
`
42+
`,
43+
styles: [`
44+
:host {
45+
display: list-item;
46+
}
47+
`]
4348
})
4449
export class AccordionItem {
4550
static accordionItemCount = 0;
4651
@Input() title: string | TemplateRef<any>;
4752
@Input() context: Object | null = null;
48-
@Input() id = `accordion-item-${AccordionItem.accordionItemCount}`;
53+
@Input() id = `accordion-item-${AccordionItem.accordionItemCount++}`;
4954
@Input() skeleton = false;
5055
@Output() selected = new EventEmitter();
5156

5257
@HostBinding("class.cds--accordion__item") itemClass = true;
5358
@HostBinding("class.cds--accordion__item--active") @Input() expanded = false;
5459
@HostBinding("class.cds--accordion__item--disabled") @Input() disabled = false;
55-
@HostBinding("style.display") itemType = "list-item";
56-
@HostBinding("attr.role") role = "heading";
57-
@HostBinding("attr.aria-level") @Input() ariaLevel = 3;
58-
59-
constructor() {
60-
AccordionItem.accordionItemCount++;
61-
}
60+
@HostBinding("attr.role") role = "listitem";
6261

6362
public toggleExpanded() {
6463
if (!this.skeleton) {

src/accordion/accordion.component.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,17 @@ import { AccordionItem } from "./accordion-item.component";
1313
@Component({
1414
selector: "ibm-accordion",
1515
template: `
16-
<ul class="cds--accordion"
16+
<div class="cds--accordion"
1717
[ngClass]="{
1818
'cds--accordion--end': align === 'end',
1919
'cds--accordion--start': align === 'start',
2020
'cds--accordion--sm': size === 'sm',
2121
'cds--accordion--md': size ==='md',
2222
'cds--accordion--lg': size === 'lg'
23-
}">
23+
}"
24+
role="list">
2425
<ng-content></ng-content>
25-
</ul>
26+
</div>
2627
`
2728
})
2829
export class Accordion implements AfterContentInit {

src/context-menu/context-menu-group.component.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ import { ContextMenuSelectionService } from "./context-menu-selection.service";
1515
@Component({
1616
selector: "ibm-context-menu-group",
1717
template: `
18-
<ul role="group" [attr.aria-label]="label">
19-
<ng-content></ng-content>
20-
</ul>
18+
<ng-content></ng-content>
2119
`,
2220
styles: [`
2321
:host {
@@ -28,9 +26,9 @@ import { ContextMenuSelectionService } from "./context-menu-selection.service";
2826
providers: [ContextMenuSelectionService]
2927
})
3028
export class ContextMenuGroupComponent implements OnInit, OnChanges, OnDestroy {
31-
@HostBinding("attr.role") role = "none";
29+
@HostBinding("attr.role") role = "group";
3230

33-
@Input() label = null;
31+
@HostBinding("attr.aria-label") @Input() label = null;
3432
@Input() value: any[] = [];
3533
@Input() type: null | "radio" | "checkbox" = null;
3634
@Output() valueChange = new EventEmitter<any[]>();

src/context-menu/context-menu-item.component.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ export class ContextMenuItemComponent implements OnInit, AfterContentInit, OnDes
4545
@HostBinding("attr.tabindex") tabindex = -1;
4646
@HostBinding("attr.aria-haspopup") ariaHasPopup = null;
4747
@HostBinding("attr.aria-expanded") ariaExpanded = null;
48+
@HostBinding("attr.aria-checked") get ariaChecked() {
49+
return this.type === "checkbox" ?
50+
(this.checked ? true : false) : null;
51+
}
4852

4953
@Input() label = "";
5054
@Input() info = "";

src/context-menu/context-menu.component.ts

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,20 @@ import {
44
HostListener,
55
Input,
66
SimpleChanges,
7-
OnChanges
7+
OnChanges,
8+
HostBinding
89
} from "@angular/core";
910

1011
@Component({
1112
selector: "ibm-context-menu",
1213
template: `
13-
<ul
14-
class="cds--context-menu cds--menu"
15-
[ngClass]="{
16-
'cds--context-menu--root': root,
17-
'cds--menu--root': root,
18-
'cds--context-menu--open': open,
19-
'cds--menu--open': open
20-
}"
21-
role="menu"
22-
tabindex="-1"
23-
[ngStyle]="{
24-
'left.px': position.left,
25-
'top.px': position.top
26-
}">
2714
<ng-content></ng-content>
28-
</ul>
29-
`
15+
`,
16+
styles: [`
17+
:host {
18+
display: block;
19+
}
20+
`]
3021
})
3122
export class ContextMenuComponent implements OnChanges {
3223
@Input() root = true;
@@ -36,6 +27,17 @@ export class ContextMenuComponent implements OnChanges {
3627
top: 0
3728
};
3829

30+
@HostBinding("class.cds--context-menu") contextMenu = true;
31+
@HostBinding("class.cds--menu") menu = true;
32+
@HostBinding("class.cds--context-menu--root") get contextMenuRoot() { return this.root; }
33+
@HostBinding("class.cds--menu--root") get menuRoot() { return this.root; }
34+
@HostBinding("class.cds--context-menu--open") get contextMenuOpen() { return this.open; }
35+
@HostBinding("class.cds--menu--open") get menuOpen() { return this.open; }
36+
@HostBinding("attr.role") role = "menu";
37+
@HostBinding("attr.tabindex") tabindex = "-1";
38+
@HostBinding("style.left.px") get leftPosition() { return this.position.left; }
39+
@HostBinding("style.top.px") get topPosition() { return this.position.top; }
40+
3941
constructor(protected elementRef: ElementRef) { }
4042

4143
ngOnChanges(changes: SimpleChanges) {
@@ -46,7 +48,7 @@ export class ContextMenuComponent implements OnChanges {
4648

4749
focusMenu() {
4850
// wait until the next tick to let the DOM settle before changing the focus
49-
const list = this.elementRef.nativeElement.querySelector("ul") as HTMLElement;
51+
const list: HTMLElement = this.elementRef.nativeElement;
5052
setTimeout(() => {
5153
if (this.root) {
5254
list.focus();
@@ -59,8 +61,8 @@ export class ContextMenuComponent implements OnChanges {
5961

6062
@HostListener("keydown", ["$event"])
6163
handleNavigation(event: KeyboardEvent) {
62-
const list: HTMLElement = this.elementRef.nativeElement.querySelector("ul");
63-
const subMenus: HTMLElement[] = Array.from(list.querySelectorAll("ul[role=menu]"));
64+
const list: HTMLElement = this.elementRef.nativeElement;
65+
const subMenus: HTMLElement[] = Array.from(list.querySelectorAll("ibm-context-menu[role=menu]"));
6466
const menuItems: HTMLElement[] = (
6567
Array.from(list.querySelectorAll(".cds--context-menu-option, .cds--menu-option")) as HTMLElement[])
6668
.filter(menuItem => !subMenus.some(subMenu => subMenu.contains(menuItem))

src/ui-shell/header/header-item.component.ts

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import {
33
Input,
44
Optional,
55
EventEmitter,
6-
Output
6+
Output,
7+
HostBinding
78
} from "@angular/core";
89
import { DomSanitizer } from "@angular/platform-browser";
910
import { Router } from "@angular/router";
@@ -14,37 +15,37 @@ import { Router } from "@angular/router";
1415
@Component({
1516
selector: "ibm-header-item",
1617
template: `
17-
<li
18-
style="height: 100%"
19-
role="menuitem">
20-
<ng-container [ngSwitch]="useRouter">
21-
<ng-template #content><ng-content></ng-content></ng-template>
22-
<a
23-
*ngSwitchCase="false"
24-
class="cds--header__menu-item"
25-
role="menuitem"
26-
tabindex="0"
27-
[ngClass]="{'cds--header__menu-item--current' : isCurrentPage}"
28-
[href]="href"
29-
(click)="navigate($event)">
30-
<ng-container *ngTemplateOutlet="content"></ng-container>
31-
</a>
32-
<a
33-
*ngSwitchCase="true"
34-
class="cds--header__menu-item"
35-
role="menuitem"
36-
[routerLinkActive]="['cds--header__menu-item--current']"
37-
tabindex="0"
38-
[ngClass]="{'cds--header__menu-item--current' : isCurrentPage}"
39-
[routerLink]="route"
40-
[routerLinkActive]="activeLinkClass">
41-
<ng-container *ngTemplateOutlet="content"></ng-container>
42-
</a>
43-
</ng-container>
44-
</li>
45-
`
18+
<ng-container [ngSwitch]="useRouter">
19+
<ng-template #content><ng-content></ng-content></ng-template>
20+
<a
21+
*ngSwitchCase="false"
22+
class="cds--header__menu-item"
23+
tabindex="0"
24+
[ngClass]="{'cds--header__menu-item--current' : isCurrentPage}"
25+
[href]="href"
26+
(click)="navigate($event)">
27+
<ng-container *ngTemplateOutlet="content"></ng-container>
28+
</a>
29+
<a
30+
*ngSwitchCase="true"
31+
class="cds--header__menu-item"
32+
[routerLinkActive]="['cds--header__menu-item--current']"
33+
tabindex="0"
34+
[ngClass]="{'cds--header__menu-item--current' : isCurrentPage}"
35+
[routerLink]="route"
36+
[routerLinkActive]="activeLinkClass">
37+
<ng-container *ngTemplateOutlet="content"></ng-container>
38+
</a>
39+
</ng-container>
40+
`,
41+
styles: [`
42+
:host {
43+
display: list-item;
44+
}
45+
`]
4646
})
4747
export class HeaderItem {
48+
@HostBinding("attr.role") role = "listitem";
4849
@Input() set href(v: string) {
4950
// Needed when component is created dynamically with a model.
5051
if (v === undefined) {

src/ui-shell/header/header-menu.component.ts

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import {
33
Input,
44
HostListener,
55
ElementRef,
6-
TemplateRef
6+
TemplateRef,
7+
HostBinding
78
} from "@angular/core";
89
import { DomSanitizer } from "@angular/platform-browser";
910
import { HeaderItemInterface } from "./header-navigation-items.interface";
@@ -14,40 +15,43 @@ import { HeaderItemInterface } from "./header-navigation-items.interface";
1415
@Component({
1516
selector: "ibm-header-menu",
1617
template: `
17-
<li
18-
class="cds--header__submenu"
19-
style="height: 100%"
20-
role="menuitem">
21-
<a
22-
class="cds--header__menu-item cds--header__menu-title"
23-
[href]="href"
24-
tabindex="0"
25-
aria-haspopup="true"
26-
[attr.aria-expanded]="expanded"
27-
(click)="navigate($event)">
28-
{{title}}
29-
<ng-template *ngIf="icon; else defaultIcon" [ngTemplateOutlet]="icon"></ng-template>
30-
<ng-template #defaultIcon>
31-
<svg class="cds--header__menu-arrow" width="12" height="7" aria-hidden="true">
32-
<path d="M6.002 5.55L11.27 0l.726.685L6.003 7 0 .685.726 0z" />
33-
</svg>
34-
</ng-template>
35-
</a>
36-
<ul class="cds--header__menu" role="menu" [attr.aria-label]="title">
37-
<ng-content></ng-content>
38-
<ng-container *ngFor="let headerItem of headerItems">
39-
<ibm-header-item
40-
[href]="headerItem.href"
41-
[route]="headerItem.route"
42-
[routeExtras]="headerItem.routeExtras">
43-
{{ headerItem.content }}
44-
</ibm-header-item>
45-
</ng-container>
46-
</ul>
47-
</li>
48-
`
18+
<a
19+
class="cds--header__menu-item cds--header__menu-title"
20+
[href]="href"
21+
tabindex="0"
22+
aria-haspopup="menu"
23+
[attr.aria-expanded]="expanded"
24+
(click)="navigate($event)">
25+
{{title}}
26+
<ng-template *ngIf="icon; else defaultIcon" [ngTemplateOutlet]="icon"></ng-template>
27+
<ng-template #defaultIcon>
28+
<svg class="cds--header__menu-arrow" width="12" height="7" aria-hidden="true">
29+
<path d="M6.002 5.55L11.27 0l.726.685L6.003 7 0 .685.726 0z" />
30+
</svg>
31+
</ng-template>
32+
</a>
33+
<div class="cds--header__menu" [attr.aria-label]="title">
34+
<ng-content></ng-content>
35+
<ng-container *ngFor="let headerItem of headerItems">
36+
<ibm-header-item
37+
[href]="headerItem.href"
38+
[route]="headerItem.route"
39+
[routeExtras]="headerItem.routeExtras">
40+
{{ headerItem.content }}
41+
</ibm-header-item>
42+
</ng-container>
43+
</div>
44+
`,
45+
styles: [`
46+
:host {
47+
display: list-item;
48+
}
49+
`]
4950
})
5051
export class HeaderMenu {
52+
@HostBinding("class.cds--header__submenu") subMenu = true;
53+
@HostBinding("attr.role") role = "listitem";
54+
5155
@Input() title: string;
5256
@Input() set href(v: string) {
5357
// Needed when component is created dynamically with a model.

src/ui-shell/header/header-navigation.component.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { NavigationItem } from "./header-navigation-items.interface";
1111
selector: "ibm-header-navigation",
1212
template: `
1313
<nav class="cds--header__nav" [attr.aria-label]="ariaLabel">
14-
<ul class="cds--header__menu-bar" role="menubar">
14+
<div class="cds--header__menu-bar" role="list">
1515
<ng-content></ng-content>
1616
<ng-container *ngFor="let navigationItem of navigationItems">
1717
<ibm-header-item
@@ -30,7 +30,7 @@ import { NavigationItem } from "./header-navigation-items.interface";
3030
[headerItems]="navigationItem.menuItems">
3131
</ibm-header-menu>
3232
</ng-container>
33-
</ul>
33+
</div>
3434
</nav>
3535
`
3636
})

src/ui-shell/panel/switcher-list.component.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component } from "@angular/core";
1+
import { Component, HostBinding } from "@angular/core";
22

33
/**
44
* Container for switcher items.
@@ -14,9 +14,15 @@ import { Component } from "@angular/core";
1414
@Component({
1515
selector: "ibm-switcher-list",
1616
template: `
17-
<ul class="cds--switcher">
1817
<ng-content></ng-content>
19-
</ul>
20-
`
18+
`,
19+
styles: [`
20+
:host {
21+
display: block;
22+
}
23+
`]
2124
})
22-
export class SwitcherList {}
25+
export class SwitcherList {
26+
@HostBinding("class.cds--switcher") switcher = true;
27+
@HostBinding("attr.role") role = "list";
28+
}

0 commit comments

Comments
 (0)