Bug/accessibility - Focus related issues (#6859)

* fix for https://github.com/microsoft/azuredatastudio/issues/6798

* fix for https://github.com/microsoft/azuredatastudio/issues/6851
This commit is contained in:
Udeesha Gautam
2019-08-22 10:29:27 -07:00
committed by GitHub
parent 09552c5f15
commit 854508e940
7 changed files with 40 additions and 8 deletions

View File

@@ -376,9 +376,11 @@ export class SchemaCompareDialog {
// if source is currently a db, show it in the server and db dropdowns // if source is currently a db, show it in the server and db dropdowns
if (this.schemaCompareResult.sourceEndpointInfo && this.schemaCompareResult.sourceEndpointInfo.endpointType === mssql.SchemaCompareEndpointType.Database) { if (this.schemaCompareResult.sourceEndpointInfo && this.schemaCompareResult.sourceEndpointInfo.endpointType === mssql.SchemaCompareEndpointType.Database) {
databaseRadioButton.checked = true; databaseRadioButton.checked = true;
databaseRadioButton.focused = true;
this.sourceIsDacpac = false; this.sourceIsDacpac = false;
} else { } else {
dacpacRadioButton.checked = true; dacpacRadioButton.checked = true;
dacpacRadioButton.focused = true;
this.sourceIsDacpac = true; this.sourceIsDacpac = true;
} }
let flexRadioButtonsModel = view.modelBuilder.flexContainer() let flexRadioButtonsModel = view.modelBuilder.flexContainer()

1
src/sql/azdata.d.ts vendored
View File

@@ -2970,6 +2970,7 @@ declare module 'azdata' {
label?: string; label?: string;
value?: string; value?: string;
checked?: boolean; checked?: boolean;
focused?: boolean;
} }
export interface TextComponentProperties { export interface TextComponentProperties {

View File

@@ -84,4 +84,11 @@ export class RadioButton extends Widget {
this.inputElement.setAttribute('aria-label', val); this.inputElement.setAttribute('aria-label', val);
} }
public focus(): void {
this.inputElement.focus();
}
public blur(): void {
this.inputElement.blur();
}
} }

View File

@@ -130,14 +130,22 @@ export class DialogPane extends Disposable implements IThemable {
}); });
} }
public show(): void { public show(focus: boolean = false): void {
this._body.classList.remove('dialogModal-hidden'); this._body.classList.remove('dialogModal-hidden');
if (focus) {
this.focus();
}
} }
public hide(): void { public hide(): void {
this._body.classList.add('dialogModal-hidden'); this._body.classList.add('dialogModal-hidden');
} }
private focus(): void {
let focusedElement = <HTMLElement>this._body.querySelector('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled])');
focusedElement ? focusedElement.focus() : this._body.focus();
}
/** /**
* Called by the theme registry on theme change to style the component * Called by the theme registry on theme change to style the component
*/ */

View File

@@ -82,7 +82,7 @@ export class WizardModal extends Modal {
} }
this._previousButton = this.addDialogButton(this._wizard.backButton, () => this.showPage(this._wizard.currentPage - 1)); this._previousButton = this.addDialogButton(this._wizard.backButton, () => this.showPage(this._wizard.currentPage - 1));
this._nextButton = this.addDialogButton(this._wizard.nextButton, () => this.showPage(this._wizard.currentPage + 1), true, true); this._nextButton = this.addDialogButton(this._wizard.nextButton, () => this.showPage(this._wizard.currentPage + 1, true, true), true, true);
this._generateScriptButton = this.addDialogButton(this._wizard.generateScriptButton, () => undefined); this._generateScriptButton = this.addDialogButton(this._wizard.generateScriptButton, () => undefined);
this._doneButton = this.addDialogButton(this._wizard.doneButton, () => this.done(), false, true); this._doneButton = this.addDialogButton(this._wizard.doneButton, () => this.done(), false, true);
this._wizard.doneButton.registerClickEvent(this._onDone.event); this._wizard.doneButton.registerClickEvent(this._onDone.event);
@@ -164,7 +164,7 @@ export class WizardModal extends Modal {
page.onUpdate(() => this.setButtonsForPage(this._wizard.currentPage)); page.onUpdate(() => this.setButtonsForPage(this._wizard.currentPage));
} }
private async showPage(index: number, validate: boolean = true): Promise<void> { private async showPage(index: number, validate: boolean = true, focus: boolean = false): Promise<void> {
let pageToShow = this._wizard.pages[index]; let pageToShow = this._wizard.pages[index];
if (!pageToShow) { if (!pageToShow) {
this.done(validate); this.done(validate);
@@ -175,7 +175,7 @@ export class WizardModal extends Modal {
} }
this._dialogPanes.forEach((dialogPane, page) => { this._dialogPanes.forEach((dialogPane, page) => {
if (page === pageToShow) { if (page === pageToShow) {
dialogPane.show(); dialogPane.show(focus);
} else { } else {
dialogPane.hide(); dialogPane.hide();
} }
@@ -227,14 +227,14 @@ export class WizardModal extends Modal {
'wizard-navigation', 'wizard-navigation',
{ {
wizard: this._wizard, wizard: this._wizard,
navigationHandler: (index: number) => this.showPage(index, index > this._wizard.currentPage) navigationHandler: (index: number) => this.showPage(index, index > this._wizard.currentPage, true)
}, },
undefined, undefined,
() => undefined); () => undefined);
} }
public open(): void { public open(): void {
this.showPage(0, false); this.showPage(0, false, true);
this.show(); this.show();
} }
@@ -292,7 +292,7 @@ export class WizardModal extends Modal {
this.done(); this.done();
} else { } else {
if (this._nextButton.enabled) { if (this._nextButton.enabled) {
this.showPage(this._wizard.currentPage + 1); this.showPage(this._wizard.currentPage + 1, true, true);
} }
} }
} }

View File

@@ -1066,6 +1066,12 @@ class RadioButtonWrapper extends ComponentWrapper implements azdata.RadioButtonC
public set checked(v: boolean) { public set checked(v: boolean) {
this.setProperty('checked', v); this.setProperty('checked', v);
} }
public get focused(): boolean {
return this.properties['focused'];
}
public set focused(v: boolean) {
this.setProperty('focused', v);
}
public get onDidClick(): vscode.Event<any> { public get onDidClick(): vscode.Event<any> {
let emitter = this._emitterMap.get(ComponentEventType.onDidClick); let emitter = this._emitterMap.get(ComponentEventType.onDidClick);

View File

@@ -74,8 +74,8 @@ export default class RadioButtonComponent extends ComponentBase implements IComp
this._input.value = this.value; this._input.value = this.value;
this._input.label = this.label; this._input.label = this.label;
this._input.enabled = this.enabled; this._input.enabled = this.enabled;
this._input.checked = this.checked; this._input.checked = this.checked;
this.focused ? this._input.focus() : this._input.blur();
} }
// CSS-bound properties // CSS-bound properties
@@ -115,4 +115,12 @@ export default class RadioButtonComponent extends ComponentBase implements IComp
public set name(newValue: string) { public set name(newValue: string) {
this.setPropertyFromUI<azdata.RadioButtonProperties, string>((properties, label) => { properties.name = label; }, newValue); this.setPropertyFromUI<azdata.RadioButtonProperties, string>((properties, label) => { properties.name = label; }, newValue);
} }
public get focused(): boolean {
return this.getPropertyOrDefault<azdata.RadioButtonProperties, boolean>((props) => props.focused, false);
}
public set focused(newValue: boolean) {
this.setPropertyFromUI<azdata.RadioButtonProperties, boolean>((properties, value) => { properties.focused = value; }, newValue);
}
} }