Switch AccessibleButton and derivatives to using forwardRef (#12054)

* Prevent Cypress typechecking react-sdk components without strict mode

This prevented us from switching to `forwardRef` in a bunch of places
due to it behaving different with & without strict mode.

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update global.d.ts

* Switch AccessibleButton and derivatives to using `forwardRef`

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Add missing ref={ref}

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Ensure RefObjects are used consistently

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Re-add WysiwygAutocomplete displayname

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Fix forwardRef types

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Add comments

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Remove unused export

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Readd comment

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate types & comments

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Apply suggestions from code review

Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>

* Add comment

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Improve comment

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
Co-authored-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
This commit is contained in:
Michael Telatynski
2023-12-21 08:50:42 +00:00
committed by GitHub
parent 0a881e2123
commit f632e2124f
37 changed files with 102 additions and 95 deletions

View File

@@ -14,7 +14,7 @@
limitations under the License.
*/
import React, { HTMLAttributes, InputHTMLAttributes } from "react";
import React, { forwardRef, FunctionComponent, HTMLAttributes, InputHTMLAttributes, Ref } from "react";
import classnames from "classnames";
import { getKeyBindingsManager } from "../../../KeyBindingsManager";
@@ -66,7 +66,6 @@ type DynamicElementProps<T extends keyof JSX.IntrinsicElements> = Partial<
* Extends props accepted by the underlying element specified using the `element` prop.
*/
type Props<T extends keyof JSX.IntrinsicElements> = DynamicHtmlElementProps<T> & {
inputRef?: React.Ref<Element>;
/**
* The base element type. "div" by default.
*/
@@ -101,22 +100,26 @@ interface RenderedElementProps extends React.InputHTMLAttributes<Element> {
* as a button. Identifies the element as a button, setting proper tab
* indexing and keyboard activation behavior.
*
* If a ref is passed, it will be forwarded to the rendered element as specified using the `element` prop.
*
* @param {Object} props react element properties
* @returns {Object} rendered react
*/
export default function AccessibleButton<T extends keyof JSX.IntrinsicElements>({
element = "div" as T,
onClick,
children,
kind,
disabled,
inputRef,
className,
onKeyDown,
onKeyUp,
triggerOnMouseDown,
...restProps
}: Props<T>): JSX.Element {
const AccessibleButton = forwardRef(function <T extends keyof JSX.IntrinsicElements>(
{
element = "div" as T,
onClick,
children,
kind,
disabled,
className,
onKeyDown,
onKeyUp,
triggerOnMouseDown,
...restProps
}: Props<T>,
ref: Ref<HTMLElement>,
): JSX.Element {
const newProps: RenderedElementProps = restProps;
if (disabled) {
newProps["aria-disabled"] = true;
@@ -170,7 +173,7 @@ export default function AccessibleButton<T extends keyof JSX.IntrinsicElements>(
}
// Pass through the ref - used for keyboard shortcut access to some buttons
newProps.ref = inputRef;
newProps.ref = ref;
newProps.className = classnames("mx_AccessibleButton", className, {
mx_AccessibleButton_hasKind: kind,
@@ -180,11 +183,13 @@ export default function AccessibleButton<T extends keyof JSX.IntrinsicElements>(
// React.createElement expects InputHTMLAttributes
return React.createElement(element, newProps, children);
}
});
AccessibleButton.defaultProps = {
// Type assertion required due to forwardRef type workaround in react.d.ts
(AccessibleButton as FunctionComponent).defaultProps = {
role: "button",
tabIndex: 0,
};
(AccessibleButton as FunctionComponent).displayName = "AccessibleButton";
AccessibleButton.displayName = "AccessibleButton";
export default AccessibleButton;