A11y - fix anchors-as-buttons (#7444)
* add link_inline accessiblebutton variant * valid anchors in SecurityRoomSettingsTab Signed-off-by: Kerry Archibald <kerrya@element.io> * new room intro link button Signed-off-by: Kerry Archibald <kerrya@element.io> * replace anchor with button in rerequest encryption keys message Signed-off-by: Kerry Archibald <kerrya@element.io> * inline button in UrlPreviewSettings Signed-off-by: Kerry Archibald <kerrya@element.io> * ButtonResetDefault mixin Signed-off-by: Kerry Archibald <kerrya@element.io> * inline link buttons in TextForEvent Signed-off-by: Kerry Archibald <kerrya@element.io> * fix anchors in InviteDialog Signed-off-by: Kerry Archibald <kerrya@element.io> * fix anchors in DevToolsDialog Signed-off-by: Kerry Archibald <kerrya@element.io> * fix anchors in login/registration/reset pword flows Signed-off-by: Kerry Archibald <kerrya@element.io> * fix types after fixing anchors in devtools Signed-off-by: Kerry Archibald <kerrya@element.io> * fix anchors in MemberEventListSummary Signed-off-by: Kerry Archibald <kerrya@element.io> * fix anchors in ReactionsRow and RoomUpgrade Signed-off-by: Kerry Archibald <kerrya@element.io> * fix anchors in ReplyChain Signed-off-by: Kerry Archibald <kerrya@element.io> * fix more anchors Signed-off-by: Kerry Archibald <kerrya@element.io> * fix anchors in auth comps * stylelint fixes Signed-off-by: Kerry Archibald <kerrya@element.io> * remove ignore of jsx-a11y rule that is not added yet Signed-off-by: Kerry Archibald <kerrya@element.io> * devtools style important explainer Signed-off-by: Kerry Archibald <kerrya@element.io> * translate button alt in devtools dialog Signed-off-by: Kerry Archibald <kerrya@element.io> * AccessibleButton is reactionsrow Signed-off-by: Kerry Archibald <kerrya@element.io> * fix viewsourcevent button placement, use AccessibleButton Signed-off-by: Kerry Archibald <kerrya@element.io> * use AccessibleButton in EventTile Signed-off-by: Kerry Archibald <kerrya@element.io> * unignore jsx-a11y/anchor-is-valid Signed-off-by: Kerry Archibald <kerrya@element.io> * fix lint issue in test jsx Signed-off-by: Kerry Archibald <kerrya@element.io> * update coment Signed-off-by: Kerry Archibald <kerrya@element.io>
This commit is contained in:
parent
2b9eed5357
commit
fed53a268b
39 changed files with 251 additions and 109 deletions
|
@ -21,6 +21,19 @@ import { Key } from '../../../Keyboard';
|
|||
|
||||
export type ButtonEvent = React.MouseEvent<Element> | React.KeyboardEvent<Element> | React.FormEvent<Element>;
|
||||
|
||||
type AccessibleButtonKind = | 'primary'
|
||||
| 'primary_outline'
|
||||
| 'primary_sm'
|
||||
| 'secondary'
|
||||
| 'danger'
|
||||
| 'danger_outline'
|
||||
| 'danger_sm'
|
||||
| 'link'
|
||||
| 'link_inline'
|
||||
| 'link_sm'
|
||||
| 'confirm_sm'
|
||||
| 'cancel_sm';
|
||||
|
||||
/**
|
||||
* children: React's magic prop. Represents all children given to the element.
|
||||
* element: (optional) The base element type. "div" by default.
|
||||
|
@ -32,7 +45,7 @@ interface IProps extends React.InputHTMLAttributes<Element> {
|
|||
element?: keyof ReactHTML;
|
||||
// The kind of button, similar to how Bootstrap works.
|
||||
// See available classes for AccessibleButton for options.
|
||||
kind?: string;
|
||||
kind?: AccessibleButtonKind | string;
|
||||
// The ARIA role
|
||||
role?: string;
|
||||
// The tabIndex
|
||||
|
|
|
@ -23,6 +23,7 @@ import SdkConfig from "../../../SdkConfig";
|
|||
import dis from "../../../dispatcher/dispatcher";
|
||||
import { Action } from "../../../dispatcher/actions";
|
||||
import { UserTab } from "../dialogs/UserSettingsDialog";
|
||||
import AccessibleButton from "./AccessibleButton";
|
||||
|
||||
export enum WarningKind {
|
||||
Files,
|
||||
|
@ -41,15 +42,19 @@ export default function DesktopBuildsNotice({ isRoomEncrypted, kind }: IProps) {
|
|||
if (EventIndexPeg.error) {
|
||||
return <>
|
||||
{ _t("Message search initialisation failed, check <a>your settings</a> for more information", {}, {
|
||||
a: sub => (<a onClick={(evt) => {
|
||||
evt.preventDefault();
|
||||
dis.dispatch({
|
||||
action: Action.ViewUserSettings,
|
||||
initialTabId: UserTab.Security,
|
||||
});
|
||||
}}>
|
||||
{ sub }
|
||||
</a>),
|
||||
a: sub => (
|
||||
<AccessibleButton
|
||||
kind="link_inline"
|
||||
onClick={(evt) => {
|
||||
evt.preventDefault();
|
||||
dis.dispatch({
|
||||
action: Action.ViewUserSettings,
|
||||
initialTabId: UserTab.Security,
|
||||
});
|
||||
}}
|
||||
>
|
||||
{ sub }
|
||||
</AccessibleButton>),
|
||||
}) }
|
||||
</>;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import { RightPanelPhases } from '../../../stores/right-panel/RightPanelStorePha
|
|||
import { jsxJoin } from '../../../utils/ReactUtils';
|
||||
import { Layout } from '../../../settings/enums/Layout';
|
||||
import RightPanelStore from '../../../stores/right-panel/RightPanelStore';
|
||||
import AccessibleButton from './AccessibleButton';
|
||||
|
||||
const onPinnedMessagesClick = (): void => {
|
||||
RightPanelStore.instance.setCard({ phase: RightPanelPhases.PinnedMessages }, false);
|
||||
|
@ -322,10 +323,18 @@ export default class MemberEventListSummary extends React.Component<IProps> {
|
|||
res = (userCount > 1)
|
||||
? _t("%(severalUsers)schanged the <a>pinned messages</a> for the room %(count)s times.",
|
||||
{ severalUsers: "", count: repeats },
|
||||
{ "a": (sub) => <a onClick={onPinnedMessagesClick}> { sub } </a> })
|
||||
{
|
||||
"a": (sub) => <AccessibleButton kind='link_inline' onClick={onPinnedMessagesClick}>
|
||||
{ sub }
|
||||
</AccessibleButton>,
|
||||
})
|
||||
: _t("%(oneUser)schanged the <a>pinned messages</a> for the room %(count)s times.",
|
||||
{ oneUser: "", count: repeats },
|
||||
{ "a": (sub) => <a onClick={onPinnedMessagesClick}> { sub } </a> });
|
||||
{
|
||||
"a": (sub) => <AccessibleButton kind='link_inline' onClick={onPinnedMessagesClick}>
|
||||
{ sub }
|
||||
</AccessibleButton>,
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ import { replaceableComponent } from "../../../utils/replaceableComponent";
|
|||
import Spinner from './Spinner';
|
||||
import ReplyTile from "../rooms/ReplyTile";
|
||||
import Pill from './Pill';
|
||||
import { ButtonEvent } from './AccessibleButton';
|
||||
|
||||
/**
|
||||
* This number is based on the previous behavior - if we have message of height
|
||||
|
@ -344,7 +345,7 @@ export default class ReplyChain extends React.Component<IProps, IState> {
|
|||
this.initialize();
|
||||
};
|
||||
|
||||
private onQuoteClick = async (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>): Promise<void> => {
|
||||
private onQuoteClick = async (event: ButtonEvent): Promise<void> => {
|
||||
const events = [this.state.loadedEv, ...this.state.events];
|
||||
|
||||
let loadedEv = null;
|
||||
|
@ -380,7 +381,11 @@ export default class ReplyChain extends React.Component<IProps, IState> {
|
|||
header = <blockquote className={`mx_ReplyChain ${this.getReplyChainColorClass(ev)}`}>
|
||||
{
|
||||
_t('<a>In reply to</a> <pill>', {}, {
|
||||
'a': (sub) => <a onClick={this.onQuoteClick} className="mx_ReplyChain_show">{ sub }</a>,
|
||||
'a': (sub) => (
|
||||
<button onClick={this.onQuoteClick} className="mx_ReplyChain_show">
|
||||
{ sub }
|
||||
</button>
|
||||
),
|
||||
'pill': (
|
||||
<Pill
|
||||
type={Pill.TYPE_USER_MENTION}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue