Tooltip: Use AccessibleButton
in RovingAccessibleTooltipButton
(#12458)
* Use `AccessibleButton` in `RovingAccessibleTooltipButton` * Update snapshots * Update @vector-im/compound-web * Update playwright * Remove placement
This commit is contained in:
parent
3634e665b1
commit
2df946b5b1
9 changed files with 34 additions and 49 deletions
|
@ -76,7 +76,7 @@
|
||||||
"@sentry/browser": "^7.0.0",
|
"@sentry/browser": "^7.0.0",
|
||||||
"@testing-library/react-hooks": "^8.0.1",
|
"@testing-library/react-hooks": "^8.0.1",
|
||||||
"@vector-im/compound-design-tokens": "^1.2.0",
|
"@vector-im/compound-design-tokens": "^1.2.0",
|
||||||
"@vector-im/compound-web": "^4.0.2",
|
"@vector-im/compound-web": "^4.1.0",
|
||||||
"@zxcvbn-ts/core": "^3.0.4",
|
"@zxcvbn-ts/core": "^3.0.4",
|
||||||
"@zxcvbn-ts/language-common": "^3.0.4",
|
"@zxcvbn-ts/language-common": "^3.0.4",
|
||||||
"@zxcvbn-ts/language-en": "^3.0.2",
|
"@zxcvbn-ts/language-en": "^3.0.2",
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.2 KiB |
|
@ -16,18 +16,15 @@ limitations under the License.
|
||||||
|
|
||||||
import React, { ComponentProps } from "react";
|
import React, { ComponentProps } from "react";
|
||||||
|
|
||||||
import AccessibleTooltipButton from "../../components/views/elements/AccessibleTooltipButton";
|
|
||||||
import { useRovingTabIndex } from "../RovingTabIndex";
|
import { useRovingTabIndex } from "../RovingTabIndex";
|
||||||
import { Ref } from "./types";
|
import { Ref } from "./types";
|
||||||
|
import AccessibleButton from "../../components/views/elements/AccessibleButton";
|
||||||
|
|
||||||
type Props<T extends keyof JSX.IntrinsicElements> = Omit<
|
type Props<T extends keyof JSX.IntrinsicElements> = Omit<ComponentProps<typeof AccessibleButton<T>>, "tabIndex"> & {
|
||||||
ComponentProps<typeof AccessibleTooltipButton<T>>,
|
|
||||||
"tabIndex"
|
|
||||||
> & {
|
|
||||||
inputRef?: Ref;
|
inputRef?: Ref;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wrapper to allow use of useRovingTabIndex for simple AccessibleTooltipButtons outside of React Functional Components.
|
// Wrapper to allow use of useRovingTabIndex for simple AccessibleButtons outside of React Functional Components.
|
||||||
export const RovingAccessibleTooltipButton = <T extends keyof JSX.IntrinsicElements>({
|
export const RovingAccessibleTooltipButton = <T extends keyof JSX.IntrinsicElements>({
|
||||||
inputRef,
|
inputRef,
|
||||||
onFocus,
|
onFocus,
|
||||||
|
@ -35,7 +32,7 @@ export const RovingAccessibleTooltipButton = <T extends keyof JSX.IntrinsicEleme
|
||||||
}: Props<T>): JSX.Element => {
|
}: Props<T>): JSX.Element => {
|
||||||
const [onFocusInternal, isActive, ref] = useRovingTabIndex(inputRef);
|
const [onFocusInternal, isActive, ref] = useRovingTabIndex(inputRef);
|
||||||
return (
|
return (
|
||||||
<AccessibleTooltipButton
|
<AccessibleButton
|
||||||
{...props}
|
{...props}
|
||||||
onFocus={(event: React.FocusEvent) => {
|
onFocus={(event: React.FocusEvent) => {
|
||||||
onFocusInternal();
|
onFocusInternal();
|
||||||
|
|
|
@ -229,22 +229,16 @@ const ReplyInThreadButton: React.FC<IReplyInThreadButton> = ({ mxEvent }) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const title = !hasARelation ? _t("action|reply_in_thread") : _t("threads|error_start_thread_existing_relation");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RovingAccessibleTooltipButton
|
<RovingAccessibleTooltipButton
|
||||||
className="mx_MessageActionBar_iconButton mx_MessageActionBar_threadButton"
|
className="mx_MessageActionBar_iconButton mx_MessageActionBar_threadButton"
|
||||||
disabled={hasARelation}
|
disabled={hasARelation}
|
||||||
tooltip={
|
title={title}
|
||||||
<>
|
|
||||||
<div className="mx_Tooltip_title">
|
|
||||||
{!hasARelation
|
|
||||||
? _t("action|reply_in_thread")
|
|
||||||
: _t("threads|error_start_thread_existing_relation")}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
title={!hasARelation ? _t("action|reply_in_thread") : _t("threads|error_start_thread_existing_relation")}
|
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
onContextMenu={onClick}
|
onContextMenu={onClick}
|
||||||
|
placement="left"
|
||||||
>
|
>
|
||||||
<ThreadIcon />
|
<ThreadIcon />
|
||||||
</RovingAccessibleTooltipButton>
|
</RovingAccessibleTooltipButton>
|
||||||
|
@ -509,18 +503,7 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||||
mx_MessageActionBar_iconButton: true,
|
mx_MessageActionBar_iconButton: true,
|
||||||
mx_MessageActionBar_expandCollapseMessageButton: true,
|
mx_MessageActionBar_expandCollapseMessageButton: true,
|
||||||
});
|
});
|
||||||
const tooltip = (
|
|
||||||
<>
|
|
||||||
<div className="mx_Tooltip_title">
|
|
||||||
{this.props.isQuoteExpanded
|
|
||||||
? _t("timeline|mab|collapse_reply_chain")
|
|
||||||
: _t("timeline|mab|expand_reply_chain")}
|
|
||||||
</div>
|
|
||||||
<div className="mx_Tooltip_sub">
|
|
||||||
{_t(ALTERNATE_KEY_NAME[Key.SHIFT]) + " + " + _t("action|click")}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
toolbarOpts.push(
|
toolbarOpts.push(
|
||||||
<RovingAccessibleTooltipButton
|
<RovingAccessibleTooltipButton
|
||||||
className={expandClassName}
|
className={expandClassName}
|
||||||
|
@ -529,9 +512,10 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||||
? _t("timeline|mab|collapse_reply_chain")
|
? _t("timeline|mab|collapse_reply_chain")
|
||||||
: _t("timeline|mab|expand_reply_chain")
|
: _t("timeline|mab|expand_reply_chain")
|
||||||
}
|
}
|
||||||
tooltip={tooltip}
|
caption={_t(ALTERNATE_KEY_NAME[Key.SHIFT]) + " + " + _t("action|click")}
|
||||||
onClick={this.props.toggleThreadExpanded}
|
onClick={this.props.toggleThreadExpanded}
|
||||||
key="expand"
|
key="expand"
|
||||||
|
placement="left"
|
||||||
>
|
>
|
||||||
{this.props.isQuoteExpanded ? <CollapseMessageIcon /> : <ExpandMessageIcon />}
|
{this.props.isQuoteExpanded ? <CollapseMessageIcon /> : <ExpandMessageIcon />}
|
||||||
</RovingAccessibleTooltipButton>,
|
</RovingAccessibleTooltipButton>,
|
||||||
|
|
|
@ -34,7 +34,6 @@ import { WidgetType } from "../../../widgets/WidgetType";
|
||||||
import { WidgetMessagingStore } from "../../../stores/widgets/WidgetMessagingStore";
|
import { WidgetMessagingStore } from "../../../stores/widgets/WidgetMessagingStore";
|
||||||
import WidgetUtils from "../../../utils/WidgetUtils";
|
import WidgetUtils from "../../../utils/WidgetUtils";
|
||||||
import { ElementWidgetActions } from "../../../stores/widgets/ElementWidgetActions";
|
import { ElementWidgetActions } from "../../../stores/widgets/ElementWidgetActions";
|
||||||
import { Alignment } from "../elements/Tooltip";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
widgetId: string;
|
widgetId: string;
|
||||||
|
@ -128,9 +127,9 @@ export const WidgetPip: FC<Props> = ({ widgetId, room, viewingRoom, onStartMovin
|
||||||
<Toolbar className="mx_WidgetPip_footer">
|
<Toolbar className="mx_WidgetPip_footer">
|
||||||
<RovingAccessibleTooltipButton
|
<RovingAccessibleTooltipButton
|
||||||
onClick={onLeaveClick}
|
onClick={onLeaveClick}
|
||||||
tooltip={_t("action|leave")}
|
title={_t("action|leave")}
|
||||||
aria-label={_t("action|leave")}
|
aria-label={_t("action|leave")}
|
||||||
alignment={Alignment.Top}
|
placement="top"
|
||||||
>
|
>
|
||||||
<HangupIcon className="mx_Icon mx_Icon_24" />
|
<HangupIcon className="mx_Icon mx_Icon_24" />
|
||||||
</RovingAccessibleTooltipButton>
|
</RovingAccessibleTooltipButton>
|
||||||
|
|
|
@ -127,16 +127,6 @@ interface IFormatButtonProps {
|
||||||
class FormatButton extends React.PureComponent<IFormatButtonProps> {
|
class FormatButton extends React.PureComponent<IFormatButtonProps> {
|
||||||
public render(): React.ReactNode {
|
public render(): React.ReactNode {
|
||||||
const className = `mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIcon${this.props.icon}`;
|
const className = `mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIcon${this.props.icon}`;
|
||||||
let shortcut;
|
|
||||||
if (this.props.shortcut) {
|
|
||||||
shortcut = <div className="mx_MessageComposerFormatBar_tooltipShortcut">{this.props.shortcut}</div>;
|
|
||||||
}
|
|
||||||
const tooltip = (
|
|
||||||
<div>
|
|
||||||
<div className="mx_Tooltip_title">{this.props.label}</div>
|
|
||||||
<div className="mx_Tooltip_sub">{shortcut}</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -145,8 +135,9 @@ class FormatButton extends React.PureComponent<IFormatButtonProps> {
|
||||||
element="button"
|
element="button"
|
||||||
type="button"
|
type="button"
|
||||||
onClick={this.props.onClick}
|
onClick={this.props.onClick}
|
||||||
|
aria-label={this.props.label}
|
||||||
title={this.props.label}
|
title={this.props.label}
|
||||||
tooltip={tooltip}
|
caption={this.props.shortcut}
|
||||||
className={className}
|
className={className}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -397,6 +397,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
|
||||||
<button
|
<button
|
||||||
aria-label="Bold"
|
aria-label="Bold"
|
||||||
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconBold"
|
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconBold"
|
||||||
|
data-state="closed"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -404,6 +405,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
|
||||||
<button
|
<button
|
||||||
aria-label="Italics"
|
aria-label="Italics"
|
||||||
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconItalic"
|
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconItalic"
|
||||||
|
data-state="closed"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -411,6 +413,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
|
||||||
<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"
|
||||||
|
data-state="closed"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -418,6 +421,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
|
||||||
<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"
|
||||||
|
data-state="closed"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -425,6 +429,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
|
||||||
<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"
|
||||||
|
data-state="closed"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -432,6 +437,7 @@ exports[`RoomView for a local room in state NEW should match the snapshot 1`] =
|
||||||
<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"
|
||||||
|
data-state="closed"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -644,6 +650,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
|
||||||
<button
|
<button
|
||||||
aria-label="Bold"
|
aria-label="Bold"
|
||||||
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconBold"
|
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconBold"
|
||||||
|
data-state="closed"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -651,6 +658,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
|
||||||
<button
|
<button
|
||||||
aria-label="Italics"
|
aria-label="Italics"
|
||||||
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconItalic"
|
class="mx_AccessibleButton mx_MessageComposerFormatBar_button mx_MessageComposerFormatBar_buttonIconItalic"
|
||||||
|
data-state="closed"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -658,6 +666,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
|
||||||
<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"
|
||||||
|
data-state="closed"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -665,6 +674,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
|
||||||
<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"
|
||||||
|
data-state="closed"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -672,6 +682,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
|
||||||
<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"
|
||||||
|
data-state="closed"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
type="button"
|
type="button"
|
||||||
|
@ -679,6 +690,7 @@ exports[`RoomView for a local room in state NEW that is encrypted should match t
|
||||||
<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"
|
||||||
|
data-state="closed"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
type="button"
|
type="button"
|
||||||
|
|
|
@ -11,6 +11,7 @@ exports[`EventTileThreadToolbar renders 1`] = `
|
||||||
<div
|
<div
|
||||||
aria-label="View in room"
|
aria-label="View in room"
|
||||||
class="mx_AccessibleButton mx_MessageActionBar_iconButton"
|
class="mx_AccessibleButton mx_MessageActionBar_iconButton"
|
||||||
|
data-state="closed"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
|
@ -19,6 +20,7 @@ exports[`EventTileThreadToolbar renders 1`] = `
|
||||||
<div
|
<div
|
||||||
aria-label="Copy link to thread"
|
aria-label="Copy link to thread"
|
||||||
class="mx_AccessibleButton mx_MessageActionBar_iconButton"
|
class="mx_AccessibleButton mx_MessageActionBar_iconButton"
|
||||||
|
data-state="closed"
|
||||||
role="button"
|
role="button"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
>
|
>
|
||||||
|
|
|
@ -3060,10 +3060,10 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
svg2vectordrawable "^2.9.1"
|
svg2vectordrawable "^2.9.1"
|
||||||
|
|
||||||
"@vector-im/compound-web@^4.0.2":
|
"@vector-im/compound-web@^4.1.0":
|
||||||
version "4.0.2"
|
version "4.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@vector-im/compound-web/-/compound-web-4.0.2.tgz#cd89ca076b9b0528718e45110a4c8126e7556c63"
|
resolved "https://registry.yarnpkg.com/@vector-im/compound-web/-/compound-web-4.1.0.tgz#45fa22e4e91b5fd4c2f535e040072990d5a33712"
|
||||||
integrity sha512-MBqmSbtcWC6KJjuTWPZ6FYc83YrUJ9dOageUdbayjhVGZ/de/a+nl/vPIAX+5ic2QWUN7nn9hujfzQF69mbIeg==
|
integrity sha512-FQSJK7PaJ3dR1c1Q3TYVSShJBl9TwlrhKadnTWsPIX6xE+rvCAeujE50QbcEWdDlWeaJ9Hi0bVPlEssJ+eRwtQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@floating-ui/react" "^0.26.9"
|
"@floating-ui/react" "^0.26.9"
|
||||||
"@floating-ui/react-dom" "^2.0.8"
|
"@floating-ui/react-dom" "^2.0.8"
|
||||||
|
|
Loading…
Reference in a new issue