From 3150c9d1a5dff97ea9715ef46f29bd8d64f34227 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Tue, 1 Aug 2023 15:17:35 +0200 Subject: [PATCH] Stop using React.JSX.Element and explicitly type all components --- .eslintrc.cjs | 2 +- .../ActionControl/ActionControl.tsx | 10 +++--- src/components/Alert/Alert.tsx | 4 +-- src/components/Avatar/Avatar.tsx | 4 +-- src/components/Avatar/AvatarStack.tsx | 7 ++-- src/components/Badge/Badge.tsx | 4 +-- src/components/Button/Button.tsx | 2 +- src/components/Checkbox/Checkbox.tsx | 4 +-- src/components/Form/Control.tsx | 6 ++-- src/components/Form/Controls/MFA/MFA.test.tsx | 32 +++++++++---------- .../Form/Controls/Password/Password.tsx | 8 ++--- src/components/Form/Field.tsx | 6 ++-- src/components/Form/Label.tsx | 6 ++-- src/components/Form/Message.tsx | 8 ++--- src/components/Form/Root.tsx | 6 ++-- src/components/Form/Submit.tsx | 6 ++-- src/components/Form/ValidityState.tsx | 9 +++--- src/components/Link/Link.tsx | 4 +-- src/components/Radio/Radio.tsx | 4 +-- src/components/Toggle/Toggle.tsx | 4 +-- src/components/Typography/Body.tsx | 8 ++--- src/components/Typography/Heading.tsx | 20 ++++++------ src/components/Typography/Typography.tsx | 2 +- src/utils/SuspenseImg.tsx | 7 ++-- 24 files changed, 81 insertions(+), 92 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index b435ec01..abbcc9f0 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -22,7 +22,7 @@ module.exports = { plugins: ["prettier", "react", "@typescript-eslint", "matrix-org"], settings: { react: { - version: "detect", + version: "17", }, }, }; diff --git a/src/components/ActionControl/ActionControl.tsx b/src/components/ActionControl/ActionControl.tsx index 71051a1d..08f2c789 100644 --- a/src/components/ActionControl/ActionControl.tsx +++ b/src/components/ActionControl/ActionControl.tsx @@ -28,14 +28,14 @@ type ActionControlProps = { disabled?: boolean; } & React.ComponentProps; -export const ActionControl = ({ +export const ActionControl: React.FC> = ({ children, Icon, className, actionLabel, onActionClick, ...props -}: PropsWithChildren) => { +}) => { const id = useId(); const classes = classnames(styles.actioncontrol, className); return ( @@ -62,9 +62,9 @@ export const ActionControl = ({ ); }; -export const StandaloneActionControl = ( - props: PropsWithChildren -): React.JSX.Element => { +export const StandaloneActionControl: React.FC< + PropsWithChildren +> = (props) => { return ( diff --git a/src/components/Alert/Alert.tsx b/src/components/Alert/Alert.tsx index d81b0897..df133b9c 100644 --- a/src/components/Alert/Alert.tsx +++ b/src/components/Alert/Alert.tsx @@ -31,14 +31,14 @@ type AlertProps = { onClose?: (e: React.MouseEvent) => void; }; -export const Alert = ({ +export const Alert: React.FC> = ({ type, title, children, className, onClose, ...props -}: PropsWithChildren): React.JSX.Element => { +}: PropsWithChildren) => { const classes = classNames(styles.alert, className); const renderIcon = useCallback( diff --git a/src/components/Avatar/Avatar.tsx b/src/components/Avatar/Avatar.tsx index 933f50ed..0ea09c5b 100644 --- a/src/components/Avatar/Avatar.tsx +++ b/src/components/Avatar/Avatar.tsx @@ -30,14 +30,14 @@ type AvatarProps = { size?: CSSStyleDeclaration["height"]; }; -export const Avatar = ({ +export const Avatar: React.FC = ({ src, id, name = "", type = "round", className = "", size, -}: AvatarProps): React.JSX.Element => { +}) => { const hash = useIdColorHash(id); const style = { "--cpd-avatar-size": size, diff --git a/src/components/Avatar/AvatarStack.tsx b/src/components/Avatar/AvatarStack.tsx index 8a7c4569..68e01a9b 100644 --- a/src/components/Avatar/AvatarStack.tsx +++ b/src/components/Avatar/AvatarStack.tsx @@ -34,10 +34,9 @@ let AvatarStackUsageCount = 0; * The `type` of avatars should always be set to `round` * And all the avatars should have the same size. */ -export const AvatarStack = ({ - children, - className, -}: React.PropsWithChildren): React.JSX.Element => { +export const AvatarStack: React.FC< + React.PropsWithChildren +> = ({ children, className }) => { /** * The `clip-path` property in CSS supports a `path()` function, however * that has to use pixel values. diff --git a/src/components/Badge/Badge.tsx b/src/components/Badge/Badge.tsx index 81364a38..b60d64cb 100644 --- a/src/components/Badge/Badge.tsx +++ b/src/components/Badge/Badge.tsx @@ -24,11 +24,11 @@ type BadgeProps = { kind?: "default" | "success" | "critical"; }; -export const Badge = ({ +export const Badge: React.FC> = ({ children, kind = "default", className, -}: PropsWithChildren) => { +}) => { const classes = classnames(styles.badge, className); return ( ({ children, className, ...props -}: PropsWithChildren>): React.JSX.Element => { +}: PropsWithChildren>): React.ReactElement => { const Component = as || "button"; const classes = classNames(styles.button, className); diff --git a/src/components/Checkbox/Checkbox.tsx b/src/components/Checkbox/Checkbox.tsx index ff6e9f57..bde1a28a 100644 --- a/src/components/Checkbox/Checkbox.tsx +++ b/src/components/Checkbox/Checkbox.tsx @@ -25,12 +25,12 @@ type CheckboxProps = { onMouseDown?: (e: React.MouseEvent) => void; } & React.ComponentPropsWithoutRef<"input">; -export const Checkbox = ({ +export const Checkbox: React.FC> = ({ kind = "primary", className, onMouseDown, ...props -}: PropsWithChildren) => { +}) => { const classes = classnames(styles.checkbox, className); return (
diff --git a/src/components/Form/Control.tsx b/src/components/Form/Control.tsx index 07facc1c..ca8696ff 100644 --- a/src/components/Form/Control.tsx +++ b/src/components/Form/Control.tsx @@ -28,14 +28,14 @@ type ControlProps = { * Thin wrapper around Radix UI Control component * https://www.radix-ui.com/docs/primitives/components/form#control */ -export function Control({ +export const Control: React.FC> = ({ children, ...props -}: PropsWithChildren): React.JSX.Element { +}) => { const classes = classNames(styles.control, props.className); return ( {children} ); -} +}; diff --git a/src/components/Form/Controls/MFA/MFA.test.tsx b/src/components/Form/Controls/MFA/MFA.test.tsx index 47af70ac..86ec2063 100644 --- a/src/components/Form/Controls/MFA/MFA.test.tsx +++ b/src/components/Form/Controls/MFA/MFA.test.tsx @@ -25,28 +25,26 @@ import { Label } from "../../Label"; import { Control } from "../../Control"; describe("PasswordControl", () => { - function getMfa( - props: React.ComponentProps = {} - ): JSX.Element { - return ( - - - - - - - - - ); - } + const MFA: React.FC> = ( + props = {} + ) => ( + + + + + + + + + ); it("renders", () => { - const { asFragment } = render(getMfa()); + const { asFragment } = render(); expect(asFragment()).toMatchSnapshot(); }); it("only allows digits", async () => { - const { getByLabelText } = render(getMfa()); + const { getByLabelText } = render(); const input = getByLabelText("MFA"); await act(async () => { @@ -57,7 +55,7 @@ describe("PasswordControl", () => { }); it("respects max length", async () => { - const { getByLabelText } = render(getMfa({ length: 3 })); + const { getByLabelText } = render(); const input = getByLabelText("MFA"); await act(async () => { diff --git a/src/components/Form/Controls/Password/Password.tsx b/src/components/Form/Controls/Password/Password.tsx index 30a9f989..dd5d6e1e 100644 --- a/src/components/Form/Controls/Password/Password.tsx +++ b/src/components/Form/Controls/Password/Password.tsx @@ -39,9 +39,9 @@ const hideState = { * Thin wrapper around Radix UI Control component * https://www.radix-ui.com/docs/primitives/components/form#control */ -export function PasswordControl( - props: PropsWithChildren> -): React.JSX.Element { +export const PasswordControl: React.FC< + PropsWithChildren> +> = (props) => { const [{ icon, label, type }, togglePasswordVisibility] = useReducer( (state) => (!state.isHidden ? showState : hideState), showState @@ -56,4 +56,4 @@ export function PasswordControl( type={type} /> ); -} +}; diff --git a/src/components/Form/Field.tsx b/src/components/Form/Field.tsx index 13dde7c4..a50f7156 100644 --- a/src/components/Form/Field.tsx +++ b/src/components/Form/Field.tsx @@ -28,14 +28,14 @@ type FieldProps = { * Thin wrapper around Radix UI Field component * https://www.radix-ui.com/docs/primitives/components/form#field */ -export function Field({ +export const Field: React.FC> = ({ children, ...props -}: PropsWithChildren): React.JSX.Element { +}) => { const classes = classNames(styles.field, props.className); return ( {children} ); -} +}; diff --git a/src/components/Form/Label.tsx b/src/components/Form/Label.tsx index 7b61c658..33978838 100644 --- a/src/components/Form/Label.tsx +++ b/src/components/Form/Label.tsx @@ -28,14 +28,14 @@ type LabelProps = { * Thin wrapper around Radix UI Label component * https://www.radix-ui.com/docs/primitives/components/form#label */ -export function Label({ +export const Label: React.FC> = ({ children, ...props -}: PropsWithChildren): React.JSX.Element { +}) => { const classes = classNames(styles.label, props.className); return ( {children} ); -} +}; diff --git a/src/components/Form/Message.tsx b/src/components/Form/Message.tsx index 6b68fb6c..fb597266 100644 --- a/src/components/Form/Message.tsx +++ b/src/components/Form/Message.tsx @@ -28,16 +28,16 @@ type MessageProps = { * Thin wrapper around Radix UI Message component * https://www.radix-ui.com/docs/primitives/components/form#message */ -export function Message({ +export const Message: React.FC> = ({ children, ...props -}: PropsWithChildren): React.JSX.Element { +}) => { const classes = classNames(styles.message, props.className); return ( - {/* Pending to be replaced by the alert component, see + {/* Pending to be replaced by the alert component, see https://github.com/vector-im/compound-web/pull/6 */} {children} ); -} +}; diff --git a/src/components/Form/Root.tsx b/src/components/Form/Root.tsx index 3e547094..545a3547 100644 --- a/src/components/Form/Root.tsx +++ b/src/components/Form/Root.tsx @@ -28,14 +28,14 @@ type RootProps = { * Thin wrapper around Radix UI Root component * https://www.radix-ui.com/docs/primitives/components/form#root */ -export function Root({ +export const Root: React.FC> = ({ children, ...props -}: PropsWithChildren): React.JSX.Element { +}) => { const classes = classNames(styles.root, props.className); return ( {children} ); -} +}; diff --git a/src/components/Form/Submit.tsx b/src/components/Form/Submit.tsx index df34bc4d..6fb2c4a8 100644 --- a/src/components/Form/Submit.tsx +++ b/src/components/Form/Submit.tsx @@ -30,11 +30,11 @@ type SubmitProps = { * Thin wrapper around Radix UI Submit component * https://www.radix-ui.com/docs/primitives/components/form#submit */ -export function Submit({ +export const Submit: React.FC> = ({ children, size, ...props -}: PropsWithChildren): React.JSX.Element { +}) => { const classes = classNames(styles.submit, props.className); return ( @@ -43,4 +43,4 @@ export function Submit({ ); -} +}; diff --git a/src/components/Form/ValidityState.tsx b/src/components/Form/ValidityState.tsx index 0c7292d3..aed759ec 100644 --- a/src/components/Form/ValidityState.tsx +++ b/src/components/Form/ValidityState.tsx @@ -21,9 +21,8 @@ import { ValidityState as RadixValidityState } from "@radix-ui/react-form"; * Thin wrapper around Radix UI ValidityState component * https://www.radix-ui.com/docs/primitives/components/form#validitystate */ -export function ValidityState({ - children, - ...props -}: React.ComponentProps): React.JSX.Element { +export const ValidityState: React.FC< + React.ComponentProps +> = ({ children, ...props }) => { return {children}; -} +}; diff --git a/src/components/Link/Link.tsx b/src/components/Link/Link.tsx index a3c75395..b3756fda 100644 --- a/src/components/Link/Link.tsx +++ b/src/components/Link/Link.tsx @@ -23,12 +23,12 @@ type LinkProps = { kind?: "primary" | "critical"; } & Omit, "rel">; -export const Link = ({ +export const Link: React.FC> = ({ children, className, kind = "primary", ...props -}: PropsWithChildren) => { +}) => { return ( > = ({ kind = "primary", className, onMouseDown, ...props -}: PropsWithChildren) => { +}) => { const classes = classnames(styles.radio, className); return (
diff --git a/src/components/Toggle/Toggle.tsx b/src/components/Toggle/Toggle.tsx index 88e37689..e0d49df1 100644 --- a/src/components/Toggle/Toggle.tsx +++ b/src/components/Toggle/Toggle.tsx @@ -27,11 +27,11 @@ type ToggleProps = { * Standalone toggle component to be used with a Radix form control * See https://www.radix-ui.com/docs/primitives/components/form#composing-with-your-own-components */ -export const Toggle = ({ +export const Toggle: React.FC> = ({ className, onMouseDown, ...props -}: PropsWithChildren) => { +}) => { const classes = classnames(styles.toggle, className); return (
diff --git a/src/components/Typography/Body.tsx b/src/components/Typography/Body.tsx index 08fa8419..717d08e4 100644 --- a/src/components/Typography/Body.tsx +++ b/src/components/Typography/Body.tsx @@ -17,11 +17,9 @@ limitations under the License. import React from "react"; import { Typography } from "./Typography"; -export const Body = ({ - as = "p", - children, - ...props -}: Omit, "type">) => { +export const Body: React.FC< + Omit, "type"> +> = ({ as = "p", children, ...props }) => { return ( {children} diff --git a/src/components/Typography/Heading.tsx b/src/components/Typography/Heading.tsx index da4f4f7f..9ce8294d 100644 --- a/src/components/Typography/Heading.tsx +++ b/src/components/Typography/Heading.tsx @@ -18,11 +18,9 @@ import React from "react"; import { Typography } from "./Typography"; import { Body } from "./Body"; -export const Heading = ({ - as = "h1", - children, - ...props -}: Omit, "type">) => { +export const Heading: React.FC< + Omit, "type"> +> = ({ as = "h1", children, ...props }) => { return ( {children} @@ -35,7 +33,7 @@ type HeadingProps = Omit< "as" | "weight" | "size" >; -export const H1 = ({ children, ...props }: HeadingProps) => { +export const H1: React.FC = ({ children, ...props }) => { return ( {children} @@ -43,7 +41,7 @@ export const H1 = ({ children, ...props }: HeadingProps) => { ); }; -export const H2 = ({ children, ...props }: HeadingProps) => { +export const H2: React.FC = ({ children, ...props }) => { return ( {children} @@ -51,7 +49,7 @@ export const H2 = ({ children, ...props }: HeadingProps) => { ); }; -export const H3 = ({ children, ...props }: HeadingProps) => { +export const H3: React.FC = ({ children, ...props }) => { return ( {children} @@ -59,7 +57,7 @@ export const H3 = ({ children, ...props }: HeadingProps) => { ); }; -export const H4 = ({ children, ...props }: HeadingProps) => { +export const H4: React.FC = ({ children, ...props }) => { return ( {children} @@ -67,7 +65,7 @@ export const H4 = ({ children, ...props }: HeadingProps) => { ); }; -export const H5 = ({ children, ...props }: HeadingProps) => { +export const H5: React.FC = ({ children, ...props }) => { return ( {children} @@ -75,7 +73,7 @@ export const H5 = ({ children, ...props }: HeadingProps) => { ); }; -export const H6 = ({ children, ...props }: HeadingProps) => { +export const H6: React.FC = ({ children, ...props }) => { return ( {children} diff --git a/src/components/Typography/Typography.tsx b/src/components/Typography/Typography.tsx index c8b39f51..269f9dd2 100644 --- a/src/components/Typography/Typography.tsx +++ b/src/components/Typography/Typography.tsx @@ -30,7 +30,7 @@ export const Typography = ({ weight = "regular", size = "md", ...restProps -}: PropsWithChildren>) => { +}: PropsWithChildren>): React.ReactElement => { const Component = as || "p"; return ( diff --git a/src/utils/SuspenseImg.tsx b/src/utils/SuspenseImg.tsx index ee5badfe..37331a7c 100644 --- a/src/utils/SuspenseImg.tsx +++ b/src/utils/SuspenseImg.tsx @@ -46,10 +46,7 @@ type SuspenseImgProps = { src: string; } & React.ImgHTMLAttributes; -export function SuspenseImg({ - src, - ...props -}: SuspenseImgProps): React.JSX.Element { +export const SuspenseImg: React.FC = ({ src, ...props }) => { /** * Read the cache, if the image has already been loaded, it will be displayed * straight away. If not, it will throw an exception that will be caught by the @@ -66,4 +63,4 @@ export function SuspenseImg({ {...props} /> ); -} +};