How to tsdoc a component which passes props to another component

149 Views Asked by At

I have a base button component which only accepts a limited number of props, and then multiple variations of that which pass through those props.

For example Button is a wrapper for BaseButton that sets type=button. SubmitButton is a wrapper that sets a type=submit.

The problem is that I don't know how to best document that Button accepts the same parameters as BaseButton except type. If I manually document them as @param entries I get a linting error that this component doesn't accept arguments by those names.

I need to "extend" the tsdoc for the BaseButton. Maybe I just use @see? I was hoping to allow those arguments to show up in VSCode hints.

This is further complicated by the fact that I'm re-using existing react types rather than declaring them myself on an interface. But I won't worry about that issue for this post.

// Borrow button element props from react
type BaseButtonProps = Pick<ButtonHTMLAttributes<HTMLButtonElement>, 'disabled' | 'onClick' | 'type'>;

// Define a basic interface for all button types
export interface ButtonProps extends Accented, BaseButtonProps {}

/**
 * Creates a button component without any defaults.
 *
 * @param accent The UI accent
 * @returns A basic button component
 */
const BaseButton = ({ accent, children, ...props }: PropsWithChildren<ButtonProps>): JSX.Element =>
    <button className={clsx('btn', styles.button, accent && styles[accent])} {...props}>{children}</button>

// Create a pre-typed button props definition
type TypedButtonProps = PropsWithChildren<Omit<ButtonProps, 'type'>>;

export const SubmitButton = ({ children, ...props }: Omit<TypedButtonProps, 'onClick'>): JSX.Element =>
    <BaseButton type='submit' {...props}>{children}</BaseButton>

/**
 * Creates a button component of type=button which accepts a click handler.
 *
 * @param onClick Handle button click events (optional)
 * ISSUE IS HERE... How can I document other props like "accent" and "disabled" without duplicating them for every variant
 * @returns Button component
 */
export const Button = ({ onClick, children, ...props }: TypedButtonProps): JSX.Element => {
    const onButtonClick = useCallback((event: MouseEvent<HTMLButtonElement>): void => {
        event.preventDefault()
        event.stopPropagation()

        onClick?.(event)
    }, [onClick])

    return <BaseButton onClick={onButtonClick} type='button' {...props}>{children}</BaseButton>
}
0

There are 0 best solutions below