Docs
Button

Button

动态交互按钮组件

自动安装

npx tofu-ui-cli@latest add button

手动安装 (可选)

注意
如果你使用手动安装,将无法获取更新

在项目目录中创建

components/ui/tofu/button.tsx

复制此代码

/**
 * TofuUI Button 按钮组件
 * @author shuakami
 * @version 1.0.0
 * @copyright ByteFreeze&TofuUI
 */
 
import React from 'react';
 
interface ButtonProps {
    text: string; // 按钮文字
    iconRight?: React.ReactNode; // 右侧图标
    iconLeft?: React.ReactNode; // 左侧图标
    onClick?: (event: any) => void; // 点击事件处理函数
    disabled?: boolean; // 是否禁用
    type?: 'button' | 'submit' | 'reset'; // 按钮类型
    size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl'; // 按钮大小
    variant?: 'primary' | 'secondary' | 'outline'; // 按钮样式变体
    fullWidth?: boolean; // 是否占据全部宽度
    className?: string; // 自定义类名
    url?: string; // 按钮链接
    loading?: boolean; // 是否显示加载状态
    loadingText?: string; // 加载状态下的文字
    ariaLabel?: string; // 无障碍标签
    title?: string; // 提示文字
}
 
const Button: React.FC<ButtonProps> = ({
                                           text,
                                           iconRight,
                                           iconLeft,
                                           onClick,
                                           disabled = false,
                                           type = 'button',
                                           size = 'md',
                                           variant = 'primary',
                                           fullWidth = false,
                                           className = '',
                                           url,
                                           loading = false,
                                           loadingText = 'Loading...',
                                           ariaLabel,
                                           title,
                                       }) => {
    const buttonStyle = `
  transition duration-200 ease-in-out 
  rounded-full px-4 
  flex items-center justify-center gap-1
  font-medium 
  ${
        size === 'sm'
            ? 'px-3 min-h-[2rem] text-xs'
            : size === 'md'
                ? 'px-4 min-h-[2.5rem] text-sm'
                : size === 'lg'
                    ? 'px-5 min-h-[2.7rem] text-base'
                    : size === 'xl'
                        ? 'px-7 min-h-[3.15rem] text-lg'
                        : size === '2xl'
                            ? 'px-10 min-h-[4rem] text-xl'
                            : 'px-12 min-h-[4.5rem] text-2xl'
    }
  ${
        variant === 'primary'
            ? '!bg-black !text-white dark:!bg-white dark:!text-black hover:bg-gray-800 dark:hover:bg-gray-100'
            : variant === 'secondary'
                ? 'bg-gray-200 text-black dark:bg-gray-700 dark:text-white hover:bg-gray-300 dark:hover:bg-gray-600'
                : 'bg-transparent text-black dark:text-white border border-black dark:border-white hover:bg-black hover:text-white dark:hover:bg-white dark:hover:text-black'
    }
  ${fullWidth ? 'w-full' : ''}
  ${disabled || loading ? 'opacity-50 cursor-not-allowed' : ''}
  ${className}
`;
 
    const iconStyle = `w-2.5 h-2.5 stroke-current stroke-[1.25] stroke-linecap-round stroke-linejoin-round`;
 
    const content = (
        <>
            {iconLeft && iconLeft}
            {loading ? loadingText : text}
            {iconRight && (
                <svg
                    width="0.625rem"
                    viewBox="0 0 10 10"
                    fill="none"
                    xmlns="http://www.w3.org/2000/svg"
                    className={iconStyle}
                >
                    <path d="M1 9L9 1M9 1H2.5M9 1V7.22222" />
                </svg>
            )}
            <span className="sr-only">(opens in a new window)</span>
        </>
    );
 
    if (url) {
        return (
            <a
                href={url}
                target="_blank"
                rel="noopener noreferrer"
                className={buttonStyle}
                onClick={onClick}
                aria-label={ariaLabel}
                title={title}
            >
                {content}
            </a>
        );
    }
 
    return (
        <button
            className={buttonStyle}
            onClick={onClick}
            disabled={disabled || loading}
            type={type}
            aria-label={ariaLabel}
            title={title}
        >
            {content}
        </button>
    );
};
 
export default Button;

按钮大小

支持参数

⭐参数名🤔类型🐳默认值🌎说明
textstring-按钮显示的文本
iconRightReact.ReactNodeundefined右侧图标,若设置true则显示
iconLeftReact.ReactNodeundefined左侧图标,若设置true则显示
onClickfunctionundefined点击事件处理函数
disabledbooleanfalse设置按钮是否禁用
type'button' | 'submit' | 'reset''button'指定按钮类型
size'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl''xl'按钮大小设置
variant'primary' | 'secondary' | 'outline''primary'按钮的样式变体
fullWidthbooleanfalse是否占据全部宽度
classNamestring-自定义类名,用于覆盖或添加额外的样式
urlstringundefined如果设置,按钮将作为链接使用,并打开新窗口
loadingbooleanfalse是否显示加载状态,若为true则显示loadingText
loadingTextstring'Loading...'加载状态下显示的文本
ariaLabelstringundefined无障碍标签,用于提高可访问性
titlestringundefined提示文本,通常用作鼠标悬停提示