Skip to content

Commit

Permalink
Fixed an a11y issue with VoiceOver & keyboard focus synchronization. (#…
Browse files Browse the repository at this point in the history
…1995)

* fix textfield sync voiceover behavior

* Fix bot url text field focus sync

Fixes the bot url text field inside the openBotDialog focus sync with voiceover

* fix browse button voiceover coursor

fix the position of the browse button in openBotDialog so voiceover position it's coursor in the right place

* fix howToBuildABot voiceover navigation

Fix the navigation with voiceover throught the links in the howToBuildABot section

* fix voiceover navigation for links in dialogs

Fixes the voiceover navigation  of the links in the dialogs to add services, add services manually and login to azure

* Add changelog entry

* Update changelog entry

* Apply feedback for textfield and openBotDialog

* Update autocompleted component to follow the aria combobox pattern

* Revert autocomplete dom changes.

* Spacing fix.
  • Loading branch information
denscollo authored and tonyanziano committed Dec 2, 2019
1 parent 7019832 commit 553d64a
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 34 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [1992](https://github.com/microsoft/BotFramework-Emulator/pull/1992)
- [1993](https://github.com/microsoft/BotFramework-Emulator/pull/1993)
- [1994](https://github.com/microsoft/BotFramework-Emulator/pull/1994)
- [1995](https://github.com/microsoft/BotFramework-Emulator/pull/1995)
- [1997](https://github.com/microsoft/BotFramework-Emulator/pull/1997)
- [1999](https://github.com/microsoft/BotFramework-Emulator/pull/1999)
- [2000](https://github.com/microsoft/BotFramework-Emulator/pull/2000)
Expand Down
Expand Up @@ -46,7 +46,7 @@ export class AzureLoginPromptDialog extends Component<AzureLoginPromptDialogProp
public render() {
return (
<Dialog cancel={this.props.cancel} title="Sign in with an Azure account" className={styles.dialogMedium}>
<p>
<p role="presentation">
{'Use your Azure account to sign in to all your Azure services, ' +
'such as Azure Bot Service, Dispatch, LUIS, and QnA Maker. '}
<LinkButton className={styles.dialogLink} linkRole={true} onClick={this.onSignUpLinkClick}>
Expand All @@ -57,7 +57,7 @@ export class AzureLoginPromptDialog extends Component<AzureLoginPromptDialogProp
{'By signing in to your services, you can register any app in that ' +
'service with your bot without having to enter in credentials manually.'}
</p>
<p>
<p role="presentation">
<LinkButton className={styles.dialogLink} linkRole={true} onClick={this.onRegisterServicesLinkClick}>
Learn more about registering services
</LinkButton>
Expand Down
Expand Up @@ -112,13 +112,13 @@ export class ConnectServicePromptDialog extends Component<ConnectServicePromptDi
private get luisContent(): ReactNode {
return (
<>
<p>
<p role="presentation">
{`Sign in to your Azure account to select the LUIS applications you'd like to associate with this bot. `}
<LinkButton linkRole={true} onClick={this.onLuisDocsClick}>
Learn more about LUIS.
</LinkButton>
</p>
<p>
<p role="presentation">
{`Alternatively, you can `}
<LinkButton onClick={this.props.addServiceManually}>add a LUIS app manually</LinkButton>
{` with the app ID, version, and authoring key.`}
Expand All @@ -130,14 +130,14 @@ export class ConnectServicePromptDialog extends Component<ConnectServicePromptDi
private get qnaContent(): JSX.Element {
return (
<>
<p>
<p role="presentation">
{'Sign in to your Azure account to select the QnA ' +
"Maker knowledge bases you'd like to associate with this bot. "}
<LinkButton linkRole={true} onClick={this.onQnADocsClick}>
Learn more about QnA Maker.
</LinkButton>
</p>
<p>
<p role="presentation">
{`Alternatively, you can `}{' '}
<LinkButton onClick={this.props.addServiceManually}>
connect to a QnA Maker knowledge base manually
Expand All @@ -151,13 +151,13 @@ export class ConnectServicePromptDialog extends Component<ConnectServicePromptDi
private get dispatchContent(): JSX.Element {
return (
<>
<p>
<p role="presentation">
{`Sign in to your Azure account to select the Dispatch model you'd like to associate with this bot. `}
<LinkButton linkRole={true} onClick={this.onDispatchDocsClick}>
Learn more about Dispatch models.
</LinkButton>
</p>
<p>
<p role="presentation">
{`Alternatively, you can `}
<LinkButton onClick={this.props.addServiceManually}>connect to a Dispatch model manually</LinkButton>
{` with the app ID, version, and authoring key.`}
Expand All @@ -169,14 +169,14 @@ export class ConnectServicePromptDialog extends Component<ConnectServicePromptDi
private get appInsightsContent(): JSX.Element {
return (
<>
<p>
<p role="presentation">
{'Sign in to your Azure account to select the Azure Application ' +
"Insights you'd like to associate with this bot. "}
<LinkButton linkRole={true} onClick={this.onAppInsightsClick}>
Learn more about Azure Application Insights.
</LinkButton>
</p>
<p>
<p role="presentation">
{`Alternatively, you can `}
<LinkButton onClick={this.props.addServiceManually}>
connect to a Azure Application Insights manually
Expand All @@ -190,14 +190,14 @@ export class ConnectServicePromptDialog extends Component<ConnectServicePromptDi
private get blobStorageContent(): ReactNode {
return (
<>
<p>
<p role="presentation">
{'Sign in to your Azure account to select the Azure Storage ' +
"accounts you'd like to associate with this bot. "}
<LinkButton linkRole={true} onClick={this.onAzureStorageDocsClick}>
Learn more about Azure Storage.
</LinkButton>
</p>
<p>
<p role="presentation">
{`Alternatively, you can `}
<LinkButton onClick={this.props.addServiceManually}>connect to a Azure Storage account manually.</LinkButton>
</p>
Expand All @@ -208,14 +208,14 @@ export class ConnectServicePromptDialog extends Component<ConnectServicePromptDi
private get cosmosDbContent(): ReactNode {
return (
<>
<p>
<p role="presentation">
{'Sign in to your Azure account to select the Azure Cosmos DB ' +
"accounts you'd like to associate with this bot. "}
<LinkButton linkRole={true} onClick={this.onAzureCosmosDbDocsClick}>
Learn more about Azure Cosmos DB.
</LinkButton>
</p>
<p>
<p role="presentation">
{`Alternatively, you can `}
<LinkButton onClick={this.props.addServiceManually}>
connect to a Azure Cosmos DB account manually.
Expand Down
Expand Up @@ -32,6 +32,7 @@
//

.browse-button {
position: relative;
margin-left: 8px;
bottom: 1px;
}
Expand Down
Expand Up @@ -130,8 +130,8 @@ export class OpenBotDialog extends Component<OpenBotDialogProps, OpenBotDialogSt

return (
<Dialog cancel={this.props.onDialogCancel} className={openBotStyles.themeOverrides} title="Open a bot">
<form id="open-bot-dialog" onSubmit={this.onSubmit}>
<div className={openBotStyles.autoCompleteBar}>
<form id="open-bot-dialog" role="presentation" onSubmit={this.onSubmit}>
<div className={openBotStyles.autoCompleteBar} role="presentation">
<AutoComplete
autoFocus={true}
errorMessage={errorMessage}
Expand Down Expand Up @@ -239,7 +239,9 @@ export class OpenBotDialog extends Component<OpenBotDialogProps, OpenBotDialogSt
return (
<div className={openBotStyles.browseButton}>
<input accept=".bot" id="openBotBrowse" name="botUrl" onChange={this.onInputChange} type="file" />
<label htmlFor="openBotBrowse">Browse</label>
<label htmlFor="openBotBrowse" aria-hidden="true">
Browse
</label>
</div>
);
}
Expand Down
24 changes: 12 additions & 12 deletions packages/app/client/src/ui/editor/welcomePage/howToBuildABot.tsx
Expand Up @@ -50,13 +50,13 @@ export class HowToBuildABot extends React.Component<HowToBuildABotProps, {}> {
<div className={styles.section}>
<div className={styles.howToBuildSection}>
<SmallHeader className={styles.howToTitle}>How to build a bot</SmallHeader>
<div className={styles.stepContainer}>
<div className={styles.stepContainer} role="presentation">
<div className={styles.stepIcon}>
<div className={styles.buildPlan01} />
</div>
<div className={styles.stepSection}>
<p className={styles.stepHeader}>Plan:</p>
<p className={styles.stepContent}>
<p className={styles.stepContent} role="presentation">
Review the bot&nbsp;
<LinkButton
ariaLabel={'Learn more about design guidelines.'}
Expand All @@ -69,13 +69,13 @@ export class HowToBuildABot extends React.Component<HowToBuildABotProps, {}> {
</p>
</div>
</div>
<div className={styles.stepContainer}>
<div className={styles.stepContainer} role="presentation">
<div className={styles.stepIcon}>
<div className={styles.buildPlan02} />
</div>
<div className={styles.stepSection}>
<p className={styles.stepHeader}>Build:</p>
<p className={styles.stepContent}>
<p className={styles.stepContent} role="presentation">
<LinkButton linkRole={true} onClick={this.onEmulatorToolsLinkClick}>
Download Command Line tools
</LinkButton>
Expand Down Expand Up @@ -117,13 +117,13 @@ export class HowToBuildABot extends React.Component<HowToBuildABotProps, {}> {
</p>
</div>
</div>
<div className={styles.stepContainer}>
<div className={styles.stepContainer} role="presentation">
<div className={styles.stepIcon}>
<div className={styles.buildPlan03} />
</div>
<div className={styles.stepSection}>
<p className={`${styles.stepHeader} ${styles.testBullet}`}>Test:</p>
<p className={styles.stepContent}>
<p className={styles.stepContent} role="presentation">
Test with the&nbsp;
<LinkButton
ariaLabel={'Test your bot on the Emulator.'}
Expand All @@ -144,13 +144,13 @@ export class HowToBuildABot extends React.Component<HowToBuildABotProps, {}> {
</p>
</div>
</div>
<div className={styles.stepContainer}>
<div className={styles.stepContainer} role="presentation">
<div className={styles.stepIcon}>
<div className={styles.buildPlan04} />
</div>
<div className={styles.stepSection}>
<p className={styles.stepHeader}>Publish:</p>
<p className={styles.stepContent}>
<p className={styles.stepContent} role="presentation">
Publish directly to Azure or
<br />
Use&nbsp;
Expand All @@ -165,13 +165,13 @@ export class HowToBuildABot extends React.Component<HowToBuildABotProps, {}> {
</p>
</div>
</div>
<div className={styles.stepContainer}>
<div className={styles.stepContainer} role="presentation">
<div className={styles.stepIcon}>
<div className={styles.buildPlan05} />
</div>
<div className={styles.stepSection}>
<p className={styles.stepHeader}>Connect:</p>
<p className={styles.stepContent}>
<p className={styles.stepContent} role="presentation">
Connect to&nbsp;
<LinkButton
ariaLabel={'Learn more connecting to channels.'}
Expand All @@ -184,13 +184,13 @@ export class HowToBuildABot extends React.Component<HowToBuildABotProps, {}> {
</p>
</div>
</div>
<div className={styles.stepContainer}>
<div className={styles.stepContainer} role="presentation">
<div className={styles.stepIcon}>
<div className={styles.buildPlan06} />
</div>
<div className={styles.stepSection}>
<p className={styles.stepHeader}>Evaluate:</p>
<p className={styles.stepContent}>
<p className={styles.stepContent} role="presentation">
<LinkButton linkRole={true} onClick={this.onAnalyticsLinkClick}>
View analytics
</LinkButton>
Expand Down
Expand Up @@ -233,7 +233,7 @@ export class ConnectedServiceEditor extends Component<ConnectedServiceEditorProp
private get luisAndDispatchHeader(): ReactNode {
const { serviceType } = this.props;
return (
<p>
<p role="presentation">
{`You can find your LUIS app ID and subscription key in ${portalMap[serviceType]}. `}
{this.learnMoreLinkButton}
</p>
Expand All @@ -244,7 +244,7 @@ export class ConnectedServiceEditor extends Component<ConnectedServiceEditorProp
const { serviceType } = this.props;

return (
<p>
<p role="presentation">
{`You can find your knowledge base ID and subscription key in ${portalMap[serviceType]}. `}
{this.learnMoreLinkButton}
</p>
Expand All @@ -253,7 +253,7 @@ export class ConnectedServiceEditor extends Component<ConnectedServiceEditorProp

private get appInsightsAndBlobStorageHeader(): ReactNode {
return (
<p>
<p role="presentation">
{`You can find your knowledge base ID and subscription key in the `}
<LinkButton className={styles.link} linkRole={true} onClick={this.onAzurePortalClick}>
Azure Portal.
Expand All @@ -266,7 +266,7 @@ export class ConnectedServiceEditor extends Component<ConnectedServiceEditorProp

private get cosmosDbHeader(): ReactNode {
return (
<p>
<p role="presentation">
{`You can find the information below in the `}
<LinkButton className={styles.link} linkRole={true} onClick={this.onAzurePortalClick}>
Azure Portal.
Expand Down
2 changes: 1 addition & 1 deletion packages/sdk/ui-react/src/widget/textField/textField.tsx
Expand Up @@ -68,7 +68,7 @@ export class TextField extends Component<TextFieldProps, {}> {
inputClassName += styles.invalid;
}
return (
<div className={`${styles.inputContainer} ${inputContainerClassName}`}>
<div className={`${styles.inputContainer} ${inputContainerClassName}`} role="presentation">
{this.labelNode}
<input
aria-label={errorMessage ? this.props.label + ', ' + errorMessage : undefined}
Expand Down

0 comments on commit 553d64a

Please sign in to comment.