mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-13 03:28:33 -05:00
Add aria role and selected properties (#8405)
* Add aria role and selected properties * Add img role fix * Add title to text
This commit is contained in:
@@ -121,12 +121,21 @@ export class BdcDashboard extends BdcDashboardPage {
|
||||
width: navWidth,
|
||||
height: '100%'
|
||||
}
|
||||
).component();
|
||||
).withProperties({
|
||||
ariaRole: 'tablist'
|
||||
}).component();
|
||||
|
||||
this.mainAreaContainer.addItem(this.navContainer, { flex: `0 0 ${navWidth}`, CSSStyles: { 'padding': '0 20px 0 20px', 'border-right': 'solid 1px #ccc' } });
|
||||
|
||||
// Overview nav item - this will be the initial page
|
||||
const overviewNavItemDiv = modelView.modelBuilder.divContainer().withLayout({ width: navWidth, height: '30px' }).withProperties({ clickable: true }).component();
|
||||
const overviewNavItemDiv = modelView.modelBuilder
|
||||
.divContainer()
|
||||
.withLayout({ width: navWidth, height: '30px' })
|
||||
.withProperties<azdata.DivContainerProperties>({
|
||||
clickable: true,
|
||||
ariaRole: 'tab',
|
||||
ariaSelected: true
|
||||
}).component();
|
||||
const overviewNavItemText = modelView.modelBuilder.text().withProperties({ value: localize('bdc.dashboard.overviewNavTitle', "Big Data Cluster overview") }).component();
|
||||
overviewNavItemText.updateCssStyles(selectedTabCss);
|
||||
overviewNavItemDiv.addItem(overviewNavItemText, { CSSStyles: { 'user-select': 'text' } });
|
||||
@@ -139,12 +148,14 @@ export class BdcDashboard extends BdcDashboardPage {
|
||||
overviewNavItemDiv.onDidClick(() => {
|
||||
if (this.currentTab) {
|
||||
this.currentTab.text.updateCssStyles(unselectedTabCss);
|
||||
this.currentTab.div.ariaSelected = false;
|
||||
}
|
||||
this.mainAreaContainer.removeItem(this.currentPage);
|
||||
this.mainAreaContainer.addItem(overviewContainer, { flex: '0 0 100%', CSSStyles: { 'margin': '0 20px 0 20px' } });
|
||||
this.currentPage = overviewContainer;
|
||||
this.currentTab = { serviceName: undefined, div: overviewNavItemDiv, dot: undefined, text: overviewNavItemText };
|
||||
this.currentTab.text.updateCssStyles(selectedTabCss);
|
||||
this.currentTab.div.ariaSelected = true;
|
||||
});
|
||||
this.navContainer.addItem(overviewNavItemDiv, { flex: '0 0 auto' });
|
||||
|
||||
@@ -198,12 +209,14 @@ export class BdcDashboard extends BdcDashboardPage {
|
||||
}
|
||||
if (this.currentTab) {
|
||||
this.currentTab.text.updateCssStyles(unselectedTabCss);
|
||||
this.currentTab.div.ariaSelected = false;
|
||||
}
|
||||
this.mainAreaContainer.removeItem(this.currentPage);
|
||||
this.mainAreaContainer.addItem(tabPageMapping.servicePage, { CSSStyles: { 'margin': '0 20px 0 20px' } });
|
||||
this.currentPage = tabPageMapping.servicePage;
|
||||
this.currentTab = tabPageMapping.navTab;
|
||||
this.currentTab.text.updateCssStyles(selectedTabCss);
|
||||
this.currentTab.div.ariaSelected = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -233,7 +246,15 @@ export class BdcDashboard extends BdcDashboardPage {
|
||||
}
|
||||
|
||||
function createServiceNavTab(modelBuilder: azdata.ModelBuilder, serviceStatus: ServiceStatusModel): NavTab {
|
||||
const div = modelBuilder.divContainer().withLayout({ width: navWidth, height: '30px', }).withProperties({ clickable: true }).component();
|
||||
const div = modelBuilder.divContainer()
|
||||
.withLayout({
|
||||
width: navWidth,
|
||||
height: '30px',
|
||||
})
|
||||
.withProperties<azdata.DivContainerProperties>({
|
||||
clickable: true,
|
||||
ariaRole: 'tab'
|
||||
}).component();
|
||||
const innerContainer = modelBuilder.flexContainer().withLayout({ width: navWidth, height: '30px', flexFlow: 'row' }).component();
|
||||
const dot = modelBuilder.text().withProperties({ value: getHealthStatusDot(serviceStatus.healthStatus), CSSStyles: { 'color': 'red', 'font-size': '40px', 'width': '20px', ...cssStyles.nonSelectableText } }).component();
|
||||
innerContainer.addItem(dot, { flex: '0 0 auto' });
|
||||
|
||||
@@ -294,7 +294,13 @@ export class BdcDashboardOverviewPage extends BdcDashboardPage {
|
||||
|
||||
private createServiceStatusRow(container: azdata.FlexContainer, serviceStatus: ServiceStatusModel, isLastRow: boolean): void {
|
||||
const serviceStatusRow = this.modelBuilder.flexContainer().withLayout({ flexFlow: 'row', alignItems: 'center', height: '30px' }).component();
|
||||
const statusIconCell = this.modelBuilder.text().withProperties({ value: getHealthStatusIcon(serviceStatus.healthStatus), CSSStyles: { 'user-select': 'none' } }).component();
|
||||
const statusIconCell = this.modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({
|
||||
value: getHealthStatusIcon(serviceStatus.healthStatus),
|
||||
ariaRole: 'img',
|
||||
title: getHealthStatusDisplayText(serviceStatus.healthStatus),
|
||||
CSSStyles: { 'user-select': 'none' }
|
||||
}).component();
|
||||
serviceStatusRow.addItem(statusIconCell, { CSSStyles: { 'width': `${overviewIconColumnWidthPx}px`, 'min-width': `${overviewIconColumnWidthPx}px` } });
|
||||
const nameCell = this.modelBuilder.text().withProperties({ value: getServiceNameDisplayText(serviceStatus.serviceName), CSSStyles: { ...cssStyles.text, ...cssStyles.hyperlink } }).component();
|
||||
nameCell.onDidClick(() => {
|
||||
|
||||
@@ -168,6 +168,8 @@ function createInstanceHealthStatusRow(modelBuilder: azdata.ModelBuilder, instan
|
||||
const statusIconCell = modelBuilder.text()
|
||||
.withProperties<azdata.TextComponentProperties>({
|
||||
value: getHealthStatusIcon(instanceStatus.healthStatus),
|
||||
ariaRole: 'img',
|
||||
title: getHealthStatusDisplayText(instanceStatus.healthStatus),
|
||||
CSSStyles: { 'user-select': 'none' }
|
||||
}).component();
|
||||
instanceHealthStatusRow.addItem(statusIconCell, { CSSStyles: { 'width': `${healthAndStatusIconColumnWidth}px`, 'min-width': `${healthAndStatusIconColumnWidth}px` } });
|
||||
|
||||
@@ -46,7 +46,9 @@ export class BdcServiceStatusPage extends BdcDashboardPage {
|
||||
width: '100%',
|
||||
height: '25px'
|
||||
}
|
||||
).component();
|
||||
).withProperties({
|
||||
ariaRole: 'tablist'
|
||||
}).component();
|
||||
|
||||
this.rootContainer.addItem(this.resourceHeader, { CSSStyles: { 'padding-top': '15px' } });
|
||||
|
||||
@@ -96,12 +98,14 @@ export class BdcServiceStatusPage extends BdcDashboardPage {
|
||||
}
|
||||
if (this.currentTab) {
|
||||
this.currentTab.tab.text.updateCssStyles(cssStyles.unselectedResourceHeaderTab);
|
||||
this.currentTab.tab.div.ariaSelected = false;
|
||||
this.resourceHeader.removeItem(this.currentTab.tab.div);
|
||||
this.resourceHeader.insertItem(this.currentTab.tab.div, this.currentTab.index, { flex: '0 0 auto', CSSStyles: cssStyles.unselectedTabDiv });
|
||||
}
|
||||
this.changeSelectedTabPage(resourceStatusPage);
|
||||
this.currentTab = { tab: resourceHeaderTab, index: currentIndex };
|
||||
this.currentTab.tab.text.updateCssStyles(cssStyles.selectedResourceHeaderTab);
|
||||
this.currentTab.tab.div.ariaSelected = true;
|
||||
this.resourceHeader.removeItem(this.currentTab.tab.div);
|
||||
this.resourceHeader.insertItem(this.currentTab.tab.div, this.currentTab.index, { flex: '0 0 auto', CSSStyles: cssStyles.selectedTabDiv });
|
||||
});
|
||||
@@ -110,6 +114,7 @@ export class BdcServiceStatusPage extends BdcDashboardPage {
|
||||
this.changeSelectedTabPage(resourceStatusPage);
|
||||
this.currentTab = { tab: resourceHeaderTab, index: currentIndex };
|
||||
this.currentTab.tab.text.updateCssStyles(cssStyles.selectedResourceHeaderTab);
|
||||
this.currentTab.tab.div.ariaSelected = true;
|
||||
this.resourceHeader.addItem(resourceHeaderTab.div, { flex: '0 0 auto', CSSStyles: cssStyles.selectedTabDiv });
|
||||
}
|
||||
else {
|
||||
@@ -127,7 +132,16 @@ export class BdcServiceStatusPage extends BdcDashboardPage {
|
||||
* @param resourceStatus The status of the resource we're creating
|
||||
*/
|
||||
function createResourceHeaderTab(modelBuilder: azdata.ModelBuilder, resourceStatus: ResourceStatusModel): ServiceTab {
|
||||
const resourceHeaderTab = modelBuilder.divContainer().withLayout({ width: '100px', height: '25px' }).withProperties({ clickable: true }).component();
|
||||
const resourceHeaderTab = modelBuilder
|
||||
.divContainer()
|
||||
.withLayout({
|
||||
width: '100px',
|
||||
height: '25px'
|
||||
})
|
||||
.withProperties({
|
||||
clickable: true,
|
||||
ariaRole: 'tab'
|
||||
}).component();
|
||||
const innerContainer = modelBuilder.flexContainer().withLayout({ width: '100px', height: '25px', flexFlow: 'row' }).component();
|
||||
const statusDot = modelBuilder.text().withProperties({ value: getHealthStatusDot(resourceStatus.healthStatus), CSSStyles: { 'color': 'red', 'font-size': '40px', 'width': '20px', 'text-align': 'right', ...cssStyles.nonSelectableText } }).component();
|
||||
innerContainer.addItem(statusDot, { flex: '0 0 auto' });
|
||||
|
||||
9
src/sql/azdata.d.ts
vendored
9
src/sql/azdata.d.ts
vendored
@@ -3019,6 +3019,14 @@ declare module 'azdata' {
|
||||
* Corresponds to the aria-label accessibility attribute for this component
|
||||
*/
|
||||
ariaLabel?: string;
|
||||
/**
|
||||
* Corresponds to the role accessibility attribute for this component
|
||||
*/
|
||||
ariaRole?: string;
|
||||
/**
|
||||
* Corresponds to the aria-selected accessibility attribute for this component
|
||||
*/
|
||||
ariaSelected?: boolean;
|
||||
/**
|
||||
* Matches the CSS style key and its available values.
|
||||
*/
|
||||
@@ -3092,7 +3100,6 @@ declare module 'azdata' {
|
||||
title?: string;
|
||||
ariaRowCount?: number;
|
||||
ariaColumnCount?: number;
|
||||
ariaRole?: string;
|
||||
updateCells?: TableCell[];
|
||||
moveFocusOutWithTab?: boolean; //accessibility requirement for tables with no actionable cells
|
||||
}
|
||||
|
||||
@@ -566,6 +566,22 @@ class ComponentWrapper implements azdata.Component {
|
||||
this.setProperty('ariaLabel', v);
|
||||
}
|
||||
|
||||
public get ariaRole(): string {
|
||||
return this.properties['ariaRole'];
|
||||
}
|
||||
|
||||
public set ariaRole(v: string) {
|
||||
this.setProperty('ariaRole', v);
|
||||
}
|
||||
|
||||
public get ariaSelected(): boolean {
|
||||
return this.properties['ariaSelected'];
|
||||
}
|
||||
|
||||
public set ariaSelected(v: boolean) {
|
||||
this.setProperty('ariaSelected', v);
|
||||
}
|
||||
|
||||
public get CSSStyles(): { [key: string]: string } {
|
||||
return this.properties['CSSStyles'];
|
||||
}
|
||||
|
||||
@@ -184,6 +184,22 @@ export abstract class ComponentBase extends Disposable implements IComponent, On
|
||||
this.setPropertyFromUI<azdata.ComponentProperties, string>((props, value) => props.ariaLabel = value, newValue);
|
||||
}
|
||||
|
||||
public get ariaRole(): string {
|
||||
return this.getPropertyOrDefault<azdata.ComponentProperties, string>((props) => props.ariaRole, '');
|
||||
}
|
||||
|
||||
public set ariaRole(newValue: string) {
|
||||
this.setPropertyFromUI<azdata.ComponentProperties, string>((props, value) => props.ariaRole = value, newValue);
|
||||
}
|
||||
|
||||
public get ariaSelected(): boolean {
|
||||
return this.getPropertyOrDefault<azdata.ComponentProperties, boolean>((props) => props.ariaSelected, false);
|
||||
}
|
||||
|
||||
public set ariaSelected(newValue: boolean) {
|
||||
this.setPropertyFromUI<azdata.ComponentProperties, boolean>((props, value) => props.ariaSelected = value, newValue);
|
||||
}
|
||||
|
||||
public get CSSStyles(): { [key: string]: string } {
|
||||
return this.getPropertyOrDefault<azdata.ComponentProperties, { [key: string]: string }>((props) => props.CSSStyles, {});
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ class DivItem {
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<div #divContainer *ngIf="items" class="divContainer" [style.height]="height" [style.width]="width" [style.display]="display" (click)="onClick()" (keyup)="onKey($event)">
|
||||
<div #divContainer *ngIf="items" class="divContainer" [style.height]="height" [style.width]="width" [style.display]="display" (click)="onClick()" (keyup)="onKey($event)" [attr.role]="ariaRole" [attr.aria-selected]="ariaSelected">
|
||||
<div *ngFor="let item of items" [style.order]="getItemOrder(item)" [ngStyle]="getItemStyles(item)">
|
||||
<model-component-wrapper [descriptor]="item.descriptor" [modelStore]="modelStore">
|
||||
</model-component-wrapper>
|
||||
|
||||
@@ -21,7 +21,7 @@ export class FlexItem {
|
||||
@Component({
|
||||
template: `
|
||||
<div *ngIf="items" class="flexContainer" [style.display]="display" [style.flexFlow]="flexFlow" [style.justifyContent]="justifyContent" [style.position]="position"
|
||||
[style.alignItems]="alignItems" [style.alignContent]="alignContent" [style.height]="height" [style.width]="width" [style.flex-wrap]="flexWrap">
|
||||
[style.alignItems]="alignItems" [style.alignContent]="alignContent" [style.height]="height" [style.width]="width" [style.flex-wrap]="flexWrap" [attr.role]="ariaRole">
|
||||
<div *ngFor="let item of items" [style.flex]="getItemFlex(item)" [style.textAlign]="textAlign" [style.order]="getItemOrder(item)" [ngStyle]="getItemStyles(item)">
|
||||
<model-component-wrapper [descriptor]="item.descriptor" [modelStore]="modelStore">
|
||||
</model-component-wrapper>
|
||||
|
||||
@@ -352,10 +352,6 @@ export default class TableComponent extends ComponentBase implements IComponent,
|
||||
return this.getPropertyOrDefault<azdata.TableComponentProperties, number>((props) => props.ariaColumnCount, -1);
|
||||
}
|
||||
|
||||
public get ariaRole(): string {
|
||||
return this.getPropertyOrDefault<azdata.TableComponentProperties, string>((props) => props.ariaRole, undefined);
|
||||
}
|
||||
|
||||
public set moveFocusOutWithTab(newValue: boolean) {
|
||||
this.setPropertyFromUI<azdata.TableComponentProperties, boolean>((props, value) => props.moveFocusOutWithTab = value, newValue);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import { TitledComponent } from 'sql/workbench/browser/modelComponents/titledCom
|
||||
</div>
|
||||
</div>
|
||||
<ng-template #noDiv>
|
||||
<p [innerHTML]="getValue()" [style.display]="display" [style.width]="getWidth()" [style.height]="getHeight()" [title]="title" [ngStyle]="this.CSSStyles" (click)="onClick()"></p>
|
||||
<p [innerHTML]="getValue()" [style.display]="display" [style.width]="getWidth()" [style.height]="getHeight()" [title]="title" [attr.role]="ariaRole" [ngStyle]="this.CSSStyles" (click)="onClick()"></p>
|
||||
</ng-template>`
|
||||
})
|
||||
export default class TextComponent extends TitledComponent implements IComponent, OnDestroy, AfterViewInit {
|
||||
|
||||
Reference in New Issue
Block a user