From 01304439eefb1af1bd169d74bbd745d335368cb8 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 6 Dec 2024 17:49:32 +0000 Subject: [PATCH] Make tsc faster again (#28678) * Stash initial work to bring TSC from over 6 mins to under 1 minute Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Stabilise types Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix incorrect props to AccessibleButton Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Swap AccessibleButton element types to match the props they provide Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Changed my mind, remove spurious previously ignored props Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update snapshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../context_menu/ContextMenuButton.tsx | 13 ++-- .../context_menu/ContextMenuTooltipButton.tsx | 13 ++-- .../roving/RovingAccessibleButton.tsx | 22 +++---- src/components/structures/auth/SoftLogout.tsx | 7 +-- .../auth/InteractiveAuthEntryComponents.tsx | 2 +- .../dialogs/devtools/SettingExplorer.tsx | 2 +- .../dialogs/spotlight/SpotlightDialog.tsx | 2 +- .../views/dialogs/spotlight/TooltipOption.tsx | 7 +-- .../views/directory/NetworkDropdown.tsx | 2 +- .../views/elements/AccessibleButton.tsx | 63 ++++++++++--------- .../views/elements/EditableItemList.tsx | 7 +-- src/components/views/emojipicker/Emoji.tsx | 2 +- .../views/messages/MPollEndBody.tsx | 2 +- .../views/messages/MessageActionBar.tsx | 2 +- src/components/views/settings/SetIdServer.tsx | 1 - .../devices/DeviceExpandDetailsButton.tsx | 15 ++--- .../tabs/user/MjolnirUserSettingsTab.tsx | 8 +-- .../views/spaces/SpaceBasicSettings.tsx | 1 - src/components/views/spaces/SpacePanel.tsx | 2 +- .../views/spaces/SpaceTreeLevel.tsx | 14 ++--- .../LegacyCallView/LegacyCallViewButtons.tsx | 2 +- .../__snapshots__/MatrixChat-test.tsx.snap | 1 - .../settings/SetIntegrationManager-test.tsx | 2 +- .../MjolnirUserSettingsTab-test.tsx.snap | 2 - 24 files changed, 83 insertions(+), 111 deletions(-) diff --git a/src/accessibility/context_menu/ContextMenuButton.tsx b/src/accessibility/context_menu/ContextMenuButton.tsx index d8c7d912c1b..9d8b5585e3b 100644 --- a/src/accessibility/context_menu/ContextMenuButton.tsx +++ b/src/accessibility/context_menu/ContextMenuButton.tsx @@ -8,25 +8,24 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ComponentProps, forwardRef, Ref } from "react"; +import React, { forwardRef, Ref } from "react"; -import AccessibleButton from "../../components/views/elements/AccessibleButton"; +import AccessibleButton, { ButtonProps } from "../../components/views/elements/AccessibleButton"; -type Props<T extends keyof JSX.IntrinsicElements> = ComponentProps<typeof AccessibleButton<T>> & { +type Props<T extends keyof HTMLElementTagNameMap> = ButtonProps<T> & { label?: string; // whether the context menu is currently open isExpanded: boolean; }; // Semantic component for representing the AccessibleButton which launches a <ContextMenu /> -export const ContextMenuButton = forwardRef(function <T extends keyof JSX.IntrinsicElements>( - { label, isExpanded, children, onClick, onContextMenu, element, ...props }: Props<T>, - ref: Ref<HTMLElement>, +export const ContextMenuButton = forwardRef(function <T extends keyof HTMLElementTagNameMap>( + { label, isExpanded, children, onClick, onContextMenu, ...props }: Props<T>, + ref: Ref<HTMLElementTagNameMap[T]>, ) { return ( <AccessibleButton {...props} - element={element as keyof JSX.IntrinsicElements} onClick={onClick} onContextMenu={onContextMenu ?? onClick ?? undefined} aria-label={label} diff --git a/src/accessibility/context_menu/ContextMenuTooltipButton.tsx b/src/accessibility/context_menu/ContextMenuTooltipButton.tsx index 11437866bd0..80023680838 100644 --- a/src/accessibility/context_menu/ContextMenuTooltipButton.tsx +++ b/src/accessibility/context_menu/ContextMenuTooltipButton.tsx @@ -8,24 +8,23 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ComponentProps, forwardRef, Ref } from "react"; +import React, { forwardRef, Ref } from "react"; -import AccessibleButton from "../../components/views/elements/AccessibleButton"; +import AccessibleButton, { ButtonProps } from "../../components/views/elements/AccessibleButton"; -type Props<T extends keyof JSX.IntrinsicElements> = ComponentProps<typeof AccessibleButton<T>> & { +type Props<T extends keyof HTMLElementTagNameMap> = ButtonProps<T> & { // whether the context menu is currently open isExpanded: boolean; }; // Semantic component for representing the AccessibleButton which launches a <ContextMenu /> -export const ContextMenuTooltipButton = forwardRef(function <T extends keyof JSX.IntrinsicElements>( - { isExpanded, children, onClick, onContextMenu, element, ...props }: Props<T>, - ref: Ref<HTMLElement>, +export const ContextMenuTooltipButton = forwardRef(function <T extends keyof HTMLElementTagNameMap>( + { isExpanded, children, onClick, onContextMenu, ...props }: Props<T>, + ref: Ref<HTMLElementTagNameMap[T]>, ) { return ( <AccessibleButton {...props} - element={element as keyof JSX.IntrinsicElements} onClick={onClick} onContextMenu={onContextMenu ?? onClick ?? undefined} aria-haspopup={true} diff --git a/src/accessibility/roving/RovingAccessibleButton.tsx b/src/accessibility/roving/RovingAccessibleButton.tsx index f50fb010ae3..b53221e1c99 100644 --- a/src/accessibility/roving/RovingAccessibleButton.tsx +++ b/src/accessibility/roving/RovingAccessibleButton.tsx @@ -6,39 +6,33 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ComponentProps } from "react"; +import React, { RefObject } from "react"; -import AccessibleButton from "../../components/views/elements/AccessibleButton"; +import AccessibleButton, { ButtonProps } from "../../components/views/elements/AccessibleButton"; import { useRovingTabIndex } from "../RovingTabIndex"; -import { Ref } from "./types"; -type Props<T extends keyof JSX.IntrinsicElements> = Omit< - ComponentProps<typeof AccessibleButton<T>>, - "inputRef" | "tabIndex" -> & { - inputRef?: Ref; +type Props<T extends keyof HTMLElementTagNameMap> = Omit<ButtonProps<T>, "tabIndex"> & { + inputRef?: RefObject<HTMLElementTagNameMap[T]>; focusOnMouseOver?: boolean; }; // Wrapper to allow use of useRovingTabIndex for simple AccessibleButtons outside of React Functional Components. -export const RovingAccessibleButton = <T extends keyof JSX.IntrinsicElements>({ +export const RovingAccessibleButton = <T extends keyof HTMLElementTagNameMap>({ inputRef, onFocus, onMouseOver, focusOnMouseOver, - element, ...props }: Props<T>): JSX.Element => { - const [onFocusInternal, isActive, ref] = useRovingTabIndex(inputRef); + const [onFocusInternal, isActive, ref] = useRovingTabIndex<HTMLElementTagNameMap[T]>(inputRef); return ( <AccessibleButton {...props} - element={element as keyof JSX.IntrinsicElements} - onFocus={(event: React.FocusEvent) => { + onFocus={(event: React.FocusEvent<never, never>) => { onFocusInternal(); onFocus?.(event); }} - onMouseOver={(event: React.MouseEvent) => { + onMouseOver={(event: React.MouseEvent<never, never>) => { if (focusOnMouseOver) onFocusInternal(); onMouseOver?.(event); }} diff --git a/src/components/structures/auth/SoftLogout.tsx b/src/components/structures/auth/SoftLogout.tsx index db72a0a04bb..9c7a900643e 100644 --- a/src/components/structures/auth/SoftLogout.tsx +++ b/src/components/structures/auth/SoftLogout.tsx @@ -235,12 +235,7 @@ export default class SoftLogout extends React.Component<IProps, IState> { value={this.state.password} disabled={this.state.busy} /> - <AccessibleButton - onClick={this.onPasswordLogin} - kind="primary" - type="submit" - disabled={this.state.busy} - > + <AccessibleButton onClick={this.onPasswordLogin} kind="primary" disabled={this.state.busy}> {_t("action|sign_in")} </AccessibleButton> <AccessibleButton onClick={this.onForgotPassword} kind="link"> diff --git a/src/components/views/auth/InteractiveAuthEntryComponents.tsx b/src/components/views/auth/InteractiveAuthEntryComponents.tsx index b1360f55604..ae5c07e3483 100644 --- a/src/components/views/auth/InteractiveAuthEntryComponents.tsx +++ b/src/components/views/auth/InteractiveAuthEntryComponents.tsx @@ -910,7 +910,7 @@ export class SSOAuthEntry extends React.Component<ISSOAuthEntryProps, ISSOAuthEn export class FallbackAuthEntry<T = {}> extends React.Component<IAuthEntryProps & T> { protected popupWindow: Window | null; - protected fallbackButton = createRef<HTMLButtonElement>(); + protected fallbackButton = createRef<HTMLDivElement>(); public constructor(props: IAuthEntryProps & T) { super(props); diff --git a/src/components/views/dialogs/devtools/SettingExplorer.tsx b/src/components/views/dialogs/devtools/SettingExplorer.tsx index ed4b64d870d..ae37fa3e1c9 100644 --- a/src/components/views/dialogs/devtools/SettingExplorer.tsx +++ b/src/components/views/dialogs/devtools/SettingExplorer.tsx @@ -298,7 +298,7 @@ const SettingsList: React.FC<ISettingsListProps> = ({ onBack, onView, onEdit }) <code>{i}</code> </AccessibleButton> <AccessibleButton - alt={_t("devtools|edit_setting")} + title={_t("devtools|edit_setting")} onClick={() => onEdit(i)} className="mx_DevTools_SettingsExplorer_edit" > diff --git a/src/components/views/dialogs/spotlight/SpotlightDialog.tsx b/src/components/views/dialogs/spotlight/SpotlightDialog.tsx index 20d6825b9b7..a87b7341e7d 100644 --- a/src/components/views/dialogs/spotlight/SpotlightDialog.tsx +++ b/src/components/views/dialogs/spotlight/SpotlightDialog.tsx @@ -1253,7 +1253,7 @@ const SpotlightDialog: React.FC<IProps> = ({ initialText = "", initialFilter = n <span>{filterToLabel(filter)}</span> <AccessibleButton tabIndex={-1} - alt={_t("spotlight_dialog|remove_filter", { + title={_t("spotlight_dialog|remove_filter", { filter: filterToLabel(filter), })} className="mx_SpotlightDialog_filter--close" diff --git a/src/components/views/dialogs/spotlight/TooltipOption.tsx b/src/components/views/dialogs/spotlight/TooltipOption.tsx index 1d60fed5b30..ebb0b4cf06e 100644 --- a/src/components/views/dialogs/spotlight/TooltipOption.tsx +++ b/src/components/views/dialogs/spotlight/TooltipOption.tsx @@ -13,15 +13,15 @@ import { useRovingTabIndex } from "../../../../accessibility/RovingTabIndex"; import AccessibleButton, { ButtonProps } from "../../elements/AccessibleButton"; import { Ref } from "../../../../accessibility/roving/types"; -type TooltipOptionProps<T extends keyof JSX.IntrinsicElements> = ButtonProps<T> & { +type TooltipOptionProps<T extends keyof HTMLElementTagNameMap> = ButtonProps<T> & { + className?: string; endAdornment?: ReactNode; inputRef?: Ref; }; -export const TooltipOption = <T extends keyof JSX.IntrinsicElements>({ +export const TooltipOption = <T extends keyof HTMLElementTagNameMap>({ inputRef, className, - element, ...props }: TooltipOptionProps<T>): JSX.Element => { const [onFocus, isActive, ref] = useRovingTabIndex(inputRef); @@ -34,7 +34,6 @@ export const TooltipOption = <T extends keyof JSX.IntrinsicElements>({ tabIndex={-1} aria-selected={isActive} role="option" - element={element as keyof JSX.IntrinsicElements} /> ); }; diff --git a/src/components/views/directory/NetworkDropdown.tsx b/src/components/views/directory/NetworkDropdown.tsx index 43d123676b0..a1b1986f471 100644 --- a/src/components/views/directory/NetworkDropdown.tsx +++ b/src/components/views/directory/NetworkDropdown.tsx @@ -168,7 +168,7 @@ export const NetworkDropdown: React.FC<IProps> = ({ protocols, config, setConfig adornment: ( <AccessibleButton className="mx_NetworkDropdown_removeServer" - alt={_t("spotlight|public_rooms|network_dropdown_remove_server_adornment", { roomServer })} + title={_t("spotlight|public_rooms|network_dropdown_remove_server_adornment", { roomServer })} onClick={() => setUserDefinedServers(without(userDefinedServers, roomServer))} /> ), diff --git a/src/components/views/elements/AccessibleButton.tsx b/src/components/views/elements/AccessibleButton.tsx index b8b5297384c..8b58f251c36 100644 --- a/src/components/views/elements/AccessibleButton.tsx +++ b/src/components/views/elements/AccessibleButton.tsx @@ -6,7 +6,15 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ -import React, { ComponentProps, forwardRef, FunctionComponent, HTMLAttributes, InputHTMLAttributes, Ref } from "react"; +import React, { + ComponentProps, + ComponentPropsWithoutRef, + forwardRef, + FunctionComponent, + ReactElement, + KeyboardEvent, + Ref, +} from "react"; import classnames from "classnames"; import { Tooltip } from "@vector-im/compound-web"; @@ -38,20 +46,8 @@ export type AccessibleButtonKind = | "icon_primary" | "icon_primary_outline"; -/** - * This type construct allows us to specifically pass those props down to the element we’re creating that the element - * actually supports. - * - * e.g., if element is set to "a", we’ll support href and target, if it’s set to "input", we support type. - * - * To remain compatible with existing code, we’ll continue to support InputHTMLAttributes<Element> - */ -type DynamicHtmlElementProps<T extends keyof JSX.IntrinsicElements> = - JSX.IntrinsicElements[T] extends HTMLAttributes<{}> ? DynamicElementProps<T> : DynamicElementProps<"div">; -type DynamicElementProps<T extends keyof JSX.IntrinsicElements> = Partial< - Omit<JSX.IntrinsicElements[T], "ref" | "onClick" | "onMouseDown" | "onKeyUp" | "onKeyDown"> -> & - Omit<InputHTMLAttributes<Element>, "onClick">; +type ElementType = keyof HTMLElementTagNameMap; +const defaultElement = "div"; type TooltipProps = ComponentProps<typeof Tooltip>; @@ -60,7 +56,7 @@ type TooltipProps = ComponentProps<typeof Tooltip>; * * Extends props accepted by the underlying element specified using the `element` prop. */ -type Props<T extends keyof JSX.IntrinsicElements> = DynamicHtmlElementProps<T> & { +type Props<T extends ElementType = "div"> = { /** * The base element type. "div" by default. */ @@ -105,14 +101,12 @@ type Props<T extends keyof JSX.IntrinsicElements> = DynamicHtmlElementProps<T> & disableTooltip?: TooltipProps["disabled"]; }; -export type ButtonProps<T extends keyof JSX.IntrinsicElements> = Props<T>; +export type ButtonProps<T extends ElementType> = Props<T> & Omit<ComponentPropsWithoutRef<T>, keyof Props<T>>; /** * Type of the props passed to the element that is rendered by AccessibleButton. */ -interface RenderedElementProps extends React.InputHTMLAttributes<Element> { - ref?: React.Ref<Element>; -} +type RenderedElementProps<T extends ElementType> = React.InputHTMLAttributes<Element> & RefProp<T>; /** * AccessibleButton is a generic wrapper for any element that should be treated @@ -124,9 +118,9 @@ interface RenderedElementProps extends React.InputHTMLAttributes<Element> { * @param {Object} props react element properties * @returns {Object} rendered react */ -const AccessibleButton = forwardRef(function <T extends keyof JSX.IntrinsicElements>( +const AccessibleButton = forwardRef(function <T extends ElementType = typeof defaultElement>( { - element = "div" as T, + element, onClick, children, kind, @@ -141,10 +135,10 @@ const AccessibleButton = forwardRef(function <T extends keyof JSX.IntrinsicEleme onTooltipOpenChange, disableTooltip, ...restProps - }: Props<T>, - ref: Ref<HTMLElement>, + }: ButtonProps<T>, + ref: Ref<HTMLElementTagNameMap[T]>, ): JSX.Element { - const newProps: RenderedElementProps = restProps; + const newProps = restProps as RenderedElementProps<T>; newProps["aria-label"] = newProps["aria-label"] ?? title; if (disabled) { newProps["aria-disabled"] = true; @@ -162,7 +156,7 @@ const AccessibleButton = forwardRef(function <T extends keyof JSX.IntrinsicEleme // And divs which we report as role button to assistive technologies. // Browsers handle space and enter key presses differently and we are only adjusting to the // inconsistencies here - newProps.onKeyDown = (e) => { + newProps.onKeyDown = (e: KeyboardEvent<never>) => { const action = getKeyBindingsManager().getAccessibilityAction(e); switch (action) { @@ -178,7 +172,7 @@ const AccessibleButton = forwardRef(function <T extends keyof JSX.IntrinsicEleme onKeyDown?.(e); } }; - newProps.onKeyUp = (e) => { + newProps.onKeyUp = (e: KeyboardEvent<never>) => { const action = getKeyBindingsManager().getAccessibilityAction(e); switch (action) { @@ -207,7 +201,7 @@ const AccessibleButton = forwardRef(function <T extends keyof JSX.IntrinsicEleme }); // React.createElement expects InputHTMLAttributes - const button = React.createElement(element, newProps, children); + const button = React.createElement(element ?? defaultElement, newProps, children); if (title) { return ( @@ -233,4 +227,15 @@ const AccessibleButton = forwardRef(function <T extends keyof JSX.IntrinsicEleme }; (AccessibleButton as FunctionComponent).displayName = "AccessibleButton"; -export default AccessibleButton; +interface RefProp<T extends ElementType> { + ref?: Ref<HTMLElementTagNameMap[T]>; +} + +interface ButtonComponent { + // With the explicit `element` prop + <C extends ElementType>(props: { element?: C } & ButtonProps<C> & RefProp<C>): ReactElement; + // Without the explicit `element` prop + (props: ButtonProps<"div"> & RefProp<"div">): ReactElement; +} + +export default AccessibleButton as ButtonComponent; diff --git a/src/components/views/elements/EditableItemList.tsx b/src/components/views/elements/EditableItemList.tsx index dc6e6c09a16..ad2d9aceee7 100644 --- a/src/components/views/elements/EditableItemList.tsx +++ b/src/components/views/elements/EditableItemList.tsx @@ -133,12 +133,7 @@ export default class EditableItemList<P = {}> extends React.PureComponent<IProps onChange={this.onNewItemChanged} list={this.props.suggestionsListId} /> - <AccessibleButton - onClick={this.onItemAdded} - kind="primary" - type="submit" - disabled={!this.props.newItem} - > + <AccessibleButton onClick={this.onItemAdded} kind="primary" disabled={!this.props.newItem}> {_t("action|add")} </AccessibleButton> </form> diff --git a/src/components/views/emojipicker/Emoji.tsx b/src/components/views/emojipicker/Emoji.tsx index c3dfb24bd13..a852122b750 100644 --- a/src/components/views/emojipicker/Emoji.tsx +++ b/src/components/views/emojipicker/Emoji.tsx @@ -31,7 +31,7 @@ class Emoji extends React.PureComponent<IProps> { return ( <RovingAccessibleButton id={this.props.id} - onClick={(ev) => onClick(ev, emoji)} + onClick={(ev: ButtonEvent) => onClick(ev, emoji)} onMouseEnter={() => onMouseEnter(emoji)} onMouseLeave={() => onMouseLeave(emoji)} className="mx_EmojiPicker_item_wrapper" diff --git a/src/components/views/messages/MPollEndBody.tsx b/src/components/views/messages/MPollEndBody.tsx index 94671fea12e..1129b3538ed 100644 --- a/src/components/views/messages/MPollEndBody.tsx +++ b/src/components/views/messages/MPollEndBody.tsx @@ -90,7 +90,7 @@ export const MPollEndBody = React.forwardRef<any, IBodyProps>(({ mxEvent, ...pro const { pollStartEvent, isLoadingPollStartEvent } = usePollStartEvent(mxEvent); if (!pollStartEvent) { - const pollEndFallbackMessage = M_TEXT.findIn(mxEvent.getContent()) || textForEvent(mxEvent, cli); + const pollEndFallbackMessage = M_TEXT.findIn<string>(mxEvent.getContent()) || textForEvent(mxEvent, cli); return ( <> <PollIcon className="mx_MPollEndBody_icon" /> diff --git a/src/components/views/messages/MessageActionBar.tsx b/src/components/views/messages/MessageActionBar.tsx index 9d21b8fa45a..579db054e9e 100644 --- a/src/components/views/messages/MessageActionBar.tsx +++ b/src/components/views/messages/MessageActionBar.tsx @@ -435,7 +435,7 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction <RovingAccessibleButton className="mx_MessageActionBar_iconButton" title={isPinned ? _t("action|unpin") : _t("action|pin")} - onClick={(e) => this.onPinClick(e, isPinned)} + onClick={(e: ButtonEvent) => this.onPinClick(e, isPinned)} onContextMenu={(e: ButtonEvent) => this.onPinClick(e, isPinned)} key="pin" placement="left" diff --git a/src/components/views/settings/SetIdServer.tsx b/src/components/views/settings/SetIdServer.tsx index 8ed6461d0a3..6dc3ae48a2c 100644 --- a/src/components/views/settings/SetIdServer.tsx +++ b/src/components/views/settings/SetIdServer.tsx @@ -407,7 +407,6 @@ export default class SetIdServer extends React.Component<IProps, IState> { forceValidity={this.state.error ? false : undefined} /> <AccessibleButton - type="submit" kind="primary_sm" onClick={this.checkIdServer} disabled={!this.idServerChangeEnabled()} diff --git a/src/components/views/settings/devices/DeviceExpandDetailsButton.tsx b/src/components/views/settings/devices/DeviceExpandDetailsButton.tsx index e7839b71da2..a04430a0c23 100644 --- a/src/components/views/settings/devices/DeviceExpandDetailsButton.tsx +++ b/src/components/views/settings/devices/DeviceExpandDetailsButton.tsx @@ -7,23 +7,21 @@ Please see LICENSE files in the repository root for full details. */ import classNames from "classnames"; -import React, { ComponentProps } from "react"; +import React from "react"; import { ChevronDownIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; import { _t } from "../../../../languageHandler"; -import AccessibleButton from "../../elements/AccessibleButton"; +import AccessibleButton, { ButtonProps } from "../../elements/AccessibleButton"; -type Props<T extends keyof JSX.IntrinsicElements> = Omit< - ComponentProps<typeof AccessibleButton<T>>, - "aria-label" | "title" | "kind" | "className" | "onClick" | "element" +type Props<T extends keyof HTMLElementTagNameMap> = Omit< + ButtonProps<T>, + "aria-label" | "title" | "kind" | "className" | "element" > & { isExpanded: boolean; - onClick: () => void; }; -export const DeviceExpandDetailsButton = <T extends keyof JSX.IntrinsicElements>({ +export const DeviceExpandDetailsButton = <T extends keyof HTMLElementTagNameMap>({ isExpanded, - onClick, ...rest }: Props<T>): JSX.Element => { const label = isExpanded ? _t("settings|sessions|hide_details") : _t("settings|sessions|show_details"); @@ -36,7 +34,6 @@ export const DeviceExpandDetailsButton = <T extends keyof JSX.IntrinsicElements> className={classNames("mx_DeviceExpandDetailsButton", { mx_DeviceExpandDetailsButton_expanded: isExpanded, })} - onClick={onClick} > <ChevronDownIcon className="mx_DeviceExpandDetailsButton_icon" /> </AccessibleButton> diff --git a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx index 9ad7df31e98..3e86d779ff3 100644 --- a/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx @@ -268,7 +268,6 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState> onChange={this.onPersonalRuleChanged} /> <AccessibleButton - type="submit" kind="primary" onClick={this.onAddPersonalRule} disabled={this.state.busy} @@ -295,12 +294,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState> value={this.state.newList} onChange={this.onNewListChanged} /> - <AccessibleButton - type="submit" - kind="primary" - onClick={this.onSubscribeList} - disabled={this.state.busy} - > + <AccessibleButton kind="primary" onClick={this.onSubscribeList} disabled={this.state.busy}> {_t("action|subscribe")} </AccessibleButton> </form> diff --git a/src/components/views/spaces/SpaceBasicSettings.tsx b/src/components/views/spaces/SpaceBasicSettings.tsx index 8311e6728ec..63a70a97cd4 100644 --- a/src/components/views/spaces/SpaceBasicSettings.tsx +++ b/src/components/views/spaces/SpaceBasicSettings.tsx @@ -71,7 +71,6 @@ export const SpaceAvatar: React.FC<Pick<IProps, "avatarUrl" | "avatarDisabled" | <AccessibleButton className="mx_SpaceBasicSettings_avatar" onClick={() => avatarUploadRef.current?.click()} - alt="" /> <AccessibleButton onClick={() => avatarUploadRef.current?.click()} diff --git a/src/components/views/spaces/SpacePanel.tsx b/src/components/views/spaces/SpacePanel.tsx index af484445b42..73bb66af380 100644 --- a/src/components/views/spaces/SpacePanel.tsx +++ b/src/components/views/spaces/SpacePanel.tsx @@ -221,7 +221,7 @@ const CreateSpaceButton: React.FC<Pick<IInnerSpacePanelProps, "isPanelCollapsed" isPanelCollapsed, setPanelCollapsed, }) => { - const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu<HTMLElement>(); + const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu<HTMLDivElement>(); useEffect(() => { if (!isPanelCollapsed && menuDisplayed) { diff --git a/src/components/views/spaces/SpaceTreeLevel.tsx b/src/components/views/spaces/SpaceTreeLevel.tsx index cee4cf54ecd..38329c39b73 100644 --- a/src/components/views/spaces/SpaceTreeLevel.tsx +++ b/src/components/views/spaces/SpaceTreeLevel.tsx @@ -30,7 +30,7 @@ import defaultDispatcher from "../../../dispatcher/dispatcher"; import { Action } from "../../../dispatcher/actions"; import { ContextMenuTooltipButton } from "../../../accessibility/context_menu/ContextMenuTooltipButton"; import { toRightOf, useContextMenu } from "../../structures/ContextMenu"; -import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent, ButtonProps as AccessibleButtonProps } from "../elements/AccessibleButton"; import { StaticNotificationState } from "../../../stores/notifications/StaticNotificationState"; import { NotificationLevel } from "../../../stores/notifications/NotificationLevel"; import { getKeyBindingsManager } from "../../../KeyBindingsManager"; @@ -39,8 +39,8 @@ import SpaceContextMenu from "../context_menus/SpaceContextMenu"; import { useRovingTabIndex } from "../../../accessibility/RovingTabIndex"; import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts"; -type ButtonProps<T extends keyof JSX.IntrinsicElements> = Omit< - ComponentProps<typeof AccessibleButton<T>>, +type ButtonProps<T extends keyof HTMLElementTagNameMap> = Omit< + AccessibleButtonProps<T>, "title" | "onClick" | "size" | "element" > & { space?: Room; @@ -52,12 +52,12 @@ type ButtonProps<T extends keyof JSX.IntrinsicElements> = Omit< notificationState?: NotificationState; isNarrow?: boolean; size: string; - innerRef?: RefObject<HTMLElement>; + innerRef?: RefObject<HTMLDivElement>; ContextMenuComponent?: ComponentType<ComponentProps<typeof SpaceContextMenu>>; onClick?(ev?: ButtonEvent): void; }; -export const SpaceButton = <T extends keyof JSX.IntrinsicElements>({ +export const SpaceButton = <T extends keyof HTMLElementTagNameMap>({ space, spaceKey: _spaceKey, className, @@ -72,8 +72,8 @@ export const SpaceButton = <T extends keyof JSX.IntrinsicElements>({ ContextMenuComponent, ...props }: ButtonProps<T>): JSX.Element => { - const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu<HTMLElement>(innerRef); - const [onFocus, isActive, ref] = useRovingTabIndex(handle); + const [menuDisplayed, handle, openMenu, closeMenu] = useContextMenu<HTMLDivElement>(innerRef); + const [onFocus, isActive, ref] = useRovingTabIndex<HTMLDivElement>(handle); const tabIndex = isActive ? 0 : -1; const spaceKey = _spaceKey ?? space?.roomId; diff --git a/src/components/views/voip/LegacyCallView/LegacyCallViewButtons.tsx b/src/components/views/voip/LegacyCallView/LegacyCallViewButtons.tsx index bdcd3713cb5..105736d04e2 100644 --- a/src/components/views/voip/LegacyCallView/LegacyCallViewButtons.tsx +++ b/src/components/views/voip/LegacyCallView/LegacyCallViewButtons.tsx @@ -69,7 +69,7 @@ interface IDropdownButtonProps extends ButtonProps { } const LegacyCallViewDropdownButton: React.FC<IDropdownButtonProps> = ({ state, deviceKinds, ...props }) => { - const [menuDisplayed, buttonRef, openMenu, closeMenu] = useContextMenu(); + const [menuDisplayed, buttonRef, openMenu, closeMenu] = useContextMenu<HTMLDivElement>(); const [hoveringDropdown, setHoveringDropdown] = useState(false); const classes = classNames("mx_LegacyCallViewButtons_button", "mx_LegacyCallViewButtons_dropdownButton", { diff --git a/test/unit-tests/components/structures/__snapshots__/MatrixChat-test.tsx.snap b/test/unit-tests/components/structures/__snapshots__/MatrixChat-test.tsx.snap index 94c26783886..1bdbe016d41 100644 --- a/test/unit-tests/components/structures/__snapshots__/MatrixChat-test.tsx.snap +++ b/test/unit-tests/components/structures/__snapshots__/MatrixChat-test.tsx.snap @@ -314,7 +314,6 @@ exports[`<MatrixChat /> with a soft-logged-out session should show the soft-logo class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary" role="button" tabindex="0" - type="submit" > Sign in </div> diff --git a/test/unit-tests/components/views/settings/SetIntegrationManager-test.tsx b/test/unit-tests/components/views/settings/SetIntegrationManager-test.tsx index 888499d5245..5c77e88d932 100644 --- a/test/unit-tests/components/views/settings/SetIntegrationManager-test.tsx +++ b/test/unit-tests/components/views/settings/SetIntegrationManager-test.tsx @@ -35,7 +35,7 @@ describe("SetIntegrationManager", () => { deleteThreePid: jest.fn(), }); - let stores: SdkContextClass; + let stores!: SdkContextClass; const getComponent = () => ( <MatrixClientContext.Provider value={mockClient}> diff --git a/test/unit-tests/components/views/settings/tabs/user/__snapshots__/MjolnirUserSettingsTab-test.tsx.snap b/test/unit-tests/components/views/settings/tabs/user/__snapshots__/MjolnirUserSettingsTab-test.tsx.snap index 4bdaf3275c8..17986bd3bcc 100644 --- a/test/unit-tests/components/views/settings/tabs/user/__snapshots__/MjolnirUserSettingsTab-test.tsx.snap +++ b/test/unit-tests/components/views/settings/tabs/user/__snapshots__/MjolnirUserSettingsTab-test.tsx.snap @@ -85,7 +85,6 @@ exports[`<MjolnirUserSettingsTab /> renders correctly when user has no ignored u class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary" role="button" tabindex="0" - type="submit" > Ignore </div> @@ -150,7 +149,6 @@ exports[`<MjolnirUserSettingsTab /> renders correctly when user has no ignored u class="mx_AccessibleButton mx_AccessibleButton_hasKind mx_AccessibleButton_kind_primary" role="button" tabindex="0" - type="submit" > Subscribe </div>