Theo's Typesafe CultTTC
Theo's Typesafe Cult2y ago
5 replies
Muhct

Best practices for typing a reusable button?

I have a React-TypeScript-Material UI app with a Button component but I'm not sure if what I'm doing is a good practice. Basically in the ButtonProps 4 out of 5 props are optional. Is this ok or should I structure the code in a different way? Perhaps not turning the button into a reusable component at all?

// src\components\shared\Button.tsx
/** @jsxImportSource @emotion/react */
import React, { ReactElement } from 'react';
import { css } from '@emotion/react';

type ButtonProps = {
    children: string;
    leftIcon?: ReactElement<SVGSVGElement>;
    onClick?: () => void;
    disabled?: boolean;
    'data-testid'?: string;
};

const styles = (leftIcon: ReactElement<SVGSVGElement> | undefined) => css`
    position: relative;
    border-radius: 8px;
    border: 2px solid transparent;
    padding: ${leftIcon ? '0.6em 1em 0.6em 0.8em' : '0.5em 1.2em 0.6em 1.2em'};
`;

const iconContainerStyle = css`
    // more styling
`;

export const Button = ({
    children,
    leftIcon,
    onClick,
    disabled,
    'data-testid': testId
}: ButtonProps) => {
    return (
        <button
            css={styles(leftIcon)}
            onClick={onClick}
            disabled={disabled}
            data-testid={testId}
        >
            {leftIcon && <span css={iconContainerStyle}>{leftIcon}</span>}
            {children}
        </button>
    );
};
Solution
You can have something like this

type ButtonProps = React.ComponentProps<"button"> & {
    leftIcon?: ReactElement<SVGSVGElement>;
    'data-testid'?: string;
};

and then
        <button
            css={styles(leftIcon)}
            data-testid={testId}
            {...otherProps}
        >
Was this page helpful?