Make composer format bar an aria toolbar (#10583)

* Make composer format bar an aria toolbar

* Iterate

* Iterate

* Update snapshot
pull/28788/head^2
Michael Telatynski 2023-04-12 14:58:38 +01:00 committed by GitHub
parent d179956af8
commit e5b1b7b632
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 18 deletions

View File

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import React from "react"; import React, { forwardRef } from "react";
import { RovingTabIndexProvider } from "./RovingTabIndex"; import { RovingTabIndexProvider } from "./RovingTabIndex";
import { getKeyBindingsManager } from "../KeyBindingsManager"; import { getKeyBindingsManager } from "../KeyBindingsManager";
@ -25,7 +25,7 @@ interface IProps extends Omit<React.HTMLProps<HTMLDivElement>, "onKeyDown"> {}
// This component implements the Toolbar design pattern from the WAI-ARIA Authoring Practices guidelines. // This component implements the Toolbar design pattern from the WAI-ARIA Authoring Practices guidelines.
// https://www.w3.org/TR/wai-aria-practices-1.1/#toolbar // https://www.w3.org/TR/wai-aria-practices-1.1/#toolbar
// All buttons passed in children must use RovingTabIndex to set `onFocus`, `isActive`, `ref` // All buttons passed in children must use RovingTabIndex to set `onFocus`, `isActive`, `ref`
const Toolbar: React.FC<IProps> = ({ children, ...props }) => { const Toolbar = forwardRef<HTMLDivElement, IProps>(({ children, ...props }, ref) => {
const onKeyDown = (ev: React.KeyboardEvent): void => { const onKeyDown = (ev: React.KeyboardEvent): void => {
const target = ev.target as HTMLElement; const target = ev.target as HTMLElement;
// Don't interfere with input default keydown behaviour // Don't interfere with input default keydown behaviour
@ -56,12 +56,12 @@ const Toolbar: React.FC<IProps> = ({ children, ...props }) => {
return ( return (
<RovingTabIndexProvider handleHomeEnd handleLeftRight onKeyDown={onKeyDown}> <RovingTabIndexProvider handleHomeEnd handleLeftRight onKeyDown={onKeyDown}>
{({ onKeyDownHandler }) => ( {({ onKeyDownHandler }) => (
<div {...props} onKeyDown={onKeyDownHandler} role="toolbar"> <div {...props} onKeyDown={onKeyDownHandler} role="toolbar" ref={ref}>
{children} {children}
</div> </div>
)} )}
</RovingTabIndexProvider> </RovingTabIndexProvider>
); );
}; });
export default Toolbar; export default Toolbar;

View File

@ -18,7 +18,8 @@ import React, { createRef } from "react";
import classNames from "classnames"; import classNames from "classnames";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; import { RovingAccessibleTooltipButton } from "../../../accessibility/RovingTabIndex";
import Toolbar from "../../../accessibility/Toolbar";
export enum Formatting { export enum Formatting {
Bold = "bold", Bold = "bold",
@ -51,7 +52,7 @@ export default class MessageComposerFormatBar extends React.PureComponent<IProps
mx_MessageComposerFormatBar_shown: this.state.visible, mx_MessageComposerFormatBar_shown: this.state.visible,
}); });
return ( return (
<div className={classes} ref={this.formatBarRef}> <Toolbar className={classes} ref={this.formatBarRef} aria-label={_t("Formatting")}>
<FormatButton <FormatButton
label={_t("Bold")} label={_t("Bold")}
onClick={() => this.props.onAction(Formatting.Bold)} onClick={() => this.props.onAction(Formatting.Bold)}
@ -93,7 +94,7 @@ export default class MessageComposerFormatBar extends React.PureComponent<IProps
shortcut={this.props.shortcuts.insert_link} shortcut={this.props.shortcuts.insert_link}
visible={this.state.visible} visible={this.state.visible}
/> />
</div> </Toolbar>
); );
} }
@ -140,7 +141,7 @@ class FormatButton extends React.PureComponent<IFormatButtonProps> {
// element="button" and type="button" are necessary for the buttons to work on WebKit, // element="button" and type="button" are necessary for the buttons to work on WebKit,
// otherwise the text is deselected before onClick can ever be called // otherwise the text is deselected before onClick can ever be called
return ( return (
<AccessibleTooltipButton <RovingAccessibleTooltipButton
element="button" element="button"
type="button" type="button"
onClick={this.props.onClick} onClick={this.props.onClick}

View File

@ -1952,6 +1952,7 @@
"Poll": "Poll", "Poll": "Poll",
"Hide formatting": "Hide formatting", "Hide formatting": "Hide formatting",
"Show formatting": "Show formatting", "Show formatting": "Show formatting",
"Formatting": "Formatting",
"Italics": "Italics", "Italics": "Italics",
"Strikethrough": "Strikethrough", "Strikethrough": "Strikethrough",
"Code block": "Code block", "Code block": "Code block",

View File

@ -446,7 +446,9 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
class="mx_BasicMessageComposer" class="mx_BasicMessageComposer"
> >
<div <div
aria-label="Formatting"
class="mx_MessageComposerFormatBar" class="mx_MessageComposerFormatBar"
role="toolbar"
> >
<button <button
aria-label="Bold" aria-label="Bold"
@ -459,35 +461,35 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
aria-label="Italics" aria-label="Italics"
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconItalic" class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconItalic"
role="button" role="button"
tabindex="0" tabindex="-1"
type="button" type="button"
/> />
<button <button
aria-label="Strikethrough" aria-label="Strikethrough"
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconStrikethrough" class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconStrikethrough"
role="button" role="button"
tabindex="0" tabindex="-1"
type="button" type="button"
/> />
<button <button
aria-label="Code block" aria-label="Code block"
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconCode" class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconCode"
role="button" role="button"
tabindex="0" tabindex="-1"
type="button" type="button"
/> />
<button <button
aria-label="Quote" aria-label="Quote"
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconQuote" class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconQuote"
role="button" role="button"
tabindex="0" tabindex="-1"
type="button" type="button"
/> />
<button <button
aria-label="Insert link" aria-label="Insert link"
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconInsertLink" class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconInsertLink"
role="button" role="button"
tabindex="0" tabindex="-1"
type="button" type="button"
/> />
</div> </div>
@ -706,7 +708,9 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
class="mx_BasicMessageComposer" class="mx_BasicMessageComposer"
> >
<div <div
aria-label="Formatting"
class="mx_MessageComposerFormatBar" class="mx_MessageComposerFormatBar"
role="toolbar"
> >
<button <button
aria-label="Bold" aria-label="Bold"
@ -719,35 +723,35 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
aria-label="Italics" aria-label="Italics"
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconItalic" class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconItalic"
role="button" role="button"
tabindex="0" tabindex="-1"
type="button" type="button"
/> />
<button <button
aria-label="Strikethrough" aria-label="Strikethrough"
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconStrikethrough" class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconStrikethrough"
role="button" role="button"
tabindex="0" tabindex="-1"
type="button" type="button"
/> />
<button <button
aria-label="Code block" aria-label="Code block"
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconCode" class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconCode"
role="button" role="button"
tabindex="0" tabindex="-1"
type="button" type="button"
/> />
<button <button
aria-label="Quote" aria-label="Quote"
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconQuote" class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconQuote"
role="button" role="button"
tabindex="0" tabindex="-1"
type="button" type="button"
/> />
<button <button
aria-label="Insert link" aria-label="Insert link"
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconInsertLink" class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconInsertLink"
role="button" role="button"
tabindex="0" tabindex="-1"
type="button" type="button"
/> />
</div> </div>