[Accessibility] [Keyboard Navigation] Enable left panels to focus on the first interactive element (#2334)
* Fixed focus on the first element when opening the Resources and Bot explorer panels * Renamed prop with a more descriptive name Co-authored-by: Federico Bernal <64086728+FedericoBernal@users.noreply.github.com>
This commit is contained in:
Родитель
544e913c19
Коммит
ffbdf716a1
|
@ -32,6 +32,7 @@
|
|||
//
|
||||
|
||||
import { IBotConfiguration } from 'botframework-config/lib/schema';
|
||||
import { removeNotification } from 'packages/app/client/src/state/sagas/notificationSagas';
|
||||
import * as React from 'react';
|
||||
|
||||
import { BotNotOpenExplorerContainer } from '../botNotOpenExplorer';
|
||||
|
@ -48,20 +49,35 @@ interface BotExplorerBarProps {
|
|||
}
|
||||
|
||||
export default class BotExplorerBar extends React.Component<BotExplorerBarProps, Record<string, unknown>> {
|
||||
private static get activeBotJsx(): JSX.Element {
|
||||
private get activeBotJsx(): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
<EndpointExplorerContainer title="Endpoint" ariaLabel="Endpoints" />
|
||||
<EndpointExplorerContainer
|
||||
title="Endpoint"
|
||||
ariaLabel="Endpoints"
|
||||
elementRefHandler={this.setEndpointsPanelRef}
|
||||
/>
|
||||
<ServicesExplorerContainer title="Services" ariaLabel="Services" />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
private openBotSettingsButtonRef: HTMLButtonElement;
|
||||
private endpointsPanelRef: HTMLElement;
|
||||
|
||||
public componentDidMount(): void {
|
||||
if (this.endpointsPanelRef) {
|
||||
this.endpointsPanelRef.focus();
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
const className = this.props.hidden ? styles.explorerOffScreen : '';
|
||||
const explorerBody = this.props.activeBot ? BotExplorerBar.activeBotJsx : <BotNotOpenExplorerContainer />;
|
||||
const explorerBody = this.props.activeBot ? (
|
||||
this.activeBotJsx
|
||||
) : (
|
||||
<BotNotOpenExplorerContainer elementRefHandler={this.setEndpointsPanelRef} />
|
||||
);
|
||||
return (
|
||||
<div className={`${styles.botExplorerBar} ${className}`}>
|
||||
<div className={explorerStyles.explorerBarHeader}>
|
||||
|
@ -91,4 +107,8 @@ export default class BotExplorerBar extends React.Component<BotExplorerBarProps,
|
|||
private setOpenBotSettingsRef = (ref: HTMLButtonElement): void => {
|
||||
this.openBotSettingsButtonRef = ref;
|
||||
};
|
||||
|
||||
private setEndpointsPanelRef = (ref: HTMLElement) => {
|
||||
this.endpointsPanelRef = ref;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ export interface BotNotOpenExplorerProps {
|
|||
hasChat?: boolean;
|
||||
openBotFile?: () => Promise<any>;
|
||||
showCreateNewBotDialog?: () => void;
|
||||
elementRefHandler?: (ref: HTMLElement) => void;
|
||||
}
|
||||
|
||||
export class BotNotOpenExplorer extends React.Component<BotNotOpenExplorerProps, Record<string, unknown>> {
|
||||
|
@ -50,7 +51,12 @@ export class BotNotOpenExplorer extends React.Component<BotNotOpenExplorerProps,
|
|||
return (
|
||||
<ul className={styles.botNotOpenExplorer}>
|
||||
<li>
|
||||
<ExpandCollapse expanded={true} ariaLabel={label} title={label}>
|
||||
<ExpandCollapse
|
||||
expanded={true}
|
||||
ariaLabel={label}
|
||||
title={label}
|
||||
elementRefHandler={this.props.elementRefHandler}
|
||||
>
|
||||
<ExpandCollapseContent>
|
||||
<div className={styles.explorerEmptyState}>
|
||||
{`To connect the Emulator services, `}
|
||||
|
|
|
@ -47,6 +47,14 @@ export interface ResourcesBarProps {
|
|||
}
|
||||
|
||||
export class ResourcesBar extends Component<ResourcesBarProps, ResourcesBarProps> {
|
||||
private chatFilesRef: HTMLElement;
|
||||
|
||||
public componentDidMount(): void {
|
||||
if (this.chatFilesRef) {
|
||||
this.chatFilesRef.focus();
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div className={styles.resourcesBar}>
|
||||
|
@ -56,6 +64,7 @@ export class ResourcesBar extends Component<ResourcesBarProps, ResourcesBarProps
|
|||
<ul className={explorerStyles.explorerSet}>
|
||||
<li>
|
||||
<ResourceExplorerContainer
|
||||
elementRefHandler={this.setChatFilesRef}
|
||||
files={this.props.chatFiles}
|
||||
resourcesPath={this.props.chatsPath}
|
||||
title="chat files"
|
||||
|
@ -72,4 +81,7 @@ export class ResourcesBar extends Component<ResourcesBarProps, ResourcesBarProps
|
|||
</div>
|
||||
);
|
||||
}
|
||||
private setChatFilesRef = (elementRefHandler: HTMLElement) => {
|
||||
this.chatFilesRef = elementRefHandler;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ export interface ServicePaneProps extends ServicePaneState {
|
|||
title?: string;
|
||||
ariaLabel?: string;
|
||||
sortCriteria?: string;
|
||||
elementRefHandler?: (ref: HTMLElement) => void;
|
||||
}
|
||||
|
||||
export interface ServicePaneState {
|
||||
|
@ -181,6 +182,7 @@ export abstract class ServicePane<
|
|||
className={styles.servicePane}
|
||||
key={this.props.title}
|
||||
title={this.props.title}
|
||||
elementRefHandler={this.props.elementRefHandler}
|
||||
ariaLabel={this.props.ariaLabel}
|
||||
expanded={this.state.expanded}
|
||||
>
|
||||
|
|
|
@ -43,6 +43,7 @@ export interface ExpandCollapseProps {
|
|||
title?: string;
|
||||
className?: string;
|
||||
ariaLabel?: string;
|
||||
elementRefHandler?: (ref: HTMLElement) => void;
|
||||
}
|
||||
|
||||
export interface ExpandCollapseState {
|
||||
|
@ -66,6 +67,7 @@ export class ExpandCollapse extends React.Component<ExpandCollapseProps, ExpandC
|
|||
return (
|
||||
<div className={`${styles.expandCollapse} ${className} ${expanded ? 'expanded' : ''}`}>
|
||||
<div
|
||||
ref={this.setElementRefHandler}
|
||||
aria-expanded={expanded}
|
||||
aria-label={ariaLabel}
|
||||
role="toolbar"
|
||||
|
@ -121,6 +123,13 @@ export class ExpandCollapse extends React.Component<ExpandCollapseProps, ExpandC
|
|||
}
|
||||
};
|
||||
|
||||
private setElementRefHandler = (ref: HTMLElement): void => {
|
||||
const { elementRefHandler } = this.props;
|
||||
if (elementRefHandler) {
|
||||
elementRefHandler(ref);
|
||||
}
|
||||
};
|
||||
|
||||
private get announcePanelState(): React.ReactNode {
|
||||
const { expanded } = this.state;
|
||||
const { title } = this.props;
|
||||
|
|
Загрузка…
Ссылка в новой задаче