ReactJS 中的动态按钮

问题描述 投票:0回答:0

我正在尝试创建一个动态组件,它可以是标签、按钮或链接。现在我想添加另一个组件,它是

Component
的孩子。但是打字稿错误使我无法完成它。有人可以帮我吗?

import { css } from '@emotion/react';
import React, { ReactNode } from 'react';
import { Link } from 'react-router-dom';

const sizes = {
    sm: 'font-size: 1.2rem; padding: 0.8rem 2rem;',
    md: 'font-size: 1.4rem; padding: 0.8rem 2rem;',
    lg: 'font-size: 2rem; padding: 0.8rem 2rem;',
};

type RemoveDuplicatedProps<ComponentProps, PassedProps> = Omit<ComponentProps, keyof PassedProps>;

type GetPropsWithOverride<Root extends ButtonRoots, Props> = {
    as?: Root;
} & Props &
    RemoveDuplicatedProps<React.ComponentProps<Root>, Props>;

type ButtonRoots = 'a' | 'button' | typeof Link;

interface BaseButton<Props> {
    <Root extends ButtonRoots>(props: GetPropsWithOverride<Root, Props>): JSX.Element;
    (props: Props): JSX.Element;
}

type ButtonProps = {
    className?: string;
    children?: ReactNode;
    disabled?: boolean;
    size?: keyof typeof sizes;
    text?: boolean;
    rounded?: boolean;
};

const Button: BaseButton<ButtonProps> = ({
    as: Component = 'button',
    size = 'md',
    text = false,
    disabled = false,
    rounded = false,
    ...props
}) => {
    const tmpProps = { ...props };

    if (disabled) {
        Object.keys(props).forEach((propKey) => {
            if (propKey.startsWith('on') && typeof props[propKey] === 'function') {
                delete tmpProps[propKey];
            }
        });
    }
    return <Component css={buttonCss(disabled, rounded, text, size as keyof typeof sizes)} {...tmpProps} />;
};

const buttonCss = (disabled: boolean, rounded: boolean, text: boolean, size: keyof typeof sizes) => css`
    & {
        width: max-content;
        display: inline-flex;
        align-items: center;
        outline: none;
        text-decoration: transparent;
        transition: all linear 0.1s;
        ${sizes[size]}
        color: ${text ? 'var(--black-color)' : 'var(--white-color)'};
        background: ${text ? 'transparent' : 'var(--primary-color)'};
        ${disabled ? 'opacity: 0.5; cursor: auto;' : 'cursor: pointer;'};
        ${rounded && !text && 'border-radius: 4px'};
    }
    &:hover {
        ${!disabled && 'opacity: 0.8;'}
    }
    &:active {
        ${!disabled && 'opacity: 1'}
    }
`;

export default Button;

reactjs typescript components
© www.soinside.com 2019 - 2024. All rights reserved.