refactor: 统一使用 Button 组件替换原有 button 元素

- 在 CopyButton、SwitchButtonGroup 和 TextInputArea 组件中,将原有的 button 元素替换为统一的 Button 组件,提升代码一致性和可维护性。
- 更新相关样式和属性以适应新组件,确保功能正常。
This commit is contained in:
雨霖铃
2026-06-19 10:08:27 +08:00
parent d401744739
commit 3ab7194501
3 changed files with 17 additions and 18 deletions
+6 -10
View File
@@ -1,8 +1,7 @@
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { Check, Copy } from 'lucide-react'; import { Check, Copy } from 'lucide-react';
import { copyTextToClipboard } from '@/utils/clipboard'; import { copyTextToClipboard } from '@/utils/clipboard';
import { cn } from '@/lib/utils'; import { Button, type ButtonProps } from '@/components/ui/button';
import { buttonVariants, type ButtonProps } from '@/components/ui/button';
import { toast } from 'sonner'; import { toast } from 'sonner';
interface CopyButtonProps extends Omit<ButtonProps, 'children' | 'onClick'> { interface CopyButtonProps extends Omit<ButtonProps, 'children' | 'onClick'> {
@@ -47,17 +46,14 @@ export const CopyButton: React.FC<CopyButtonProps> = ({
}; };
return ( return (
<button <Button
type="button" type="button"
onClick={handleCopy} onClick={handleCopy}
title={tooltip ?? '复制'} title={tooltip ?? '复制'}
aria-label={tooltip ?? '复制'} aria-label={tooltip ?? '复制'}
className={cn( variant={variant}
buttonVariants({ variant, size }), size={size}
copied && className={className}
'bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 hover:bg-emerald-500/10',
className,
)}
{...props} {...props}
> >
{copied ? ( {copied ? (
@@ -65,7 +61,7 @@ export const CopyButton: React.FC<CopyButtonProps> = ({
) : ( ) : (
<Copy className="h-[1.2em] w-[1.2em]" /> <Copy className="h-[1.2em] w-[1.2em]" />
)} )}
</button> </Button>
); );
}; };
+5 -5
View File
@@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
export interface SwitchOption<T extends string | number = string> { export interface SwitchOption<T extends string | number = string> {
@@ -45,21 +46,20 @@ export default function SwitchButtonGroup<T extends string | number = string>({
{...props} {...props}
> >
{options.map((option) => ( {options.map((option) => (
<button <Button
key={option.value} key={option.value}
type="button" type="button"
variant="ghost"
onClick={() => onChange(option.value)} onClick={() => onChange(option.value)}
className={cn( className={cn(
'flex-1 inline-flex items-center justify-center font-medium whitespace-nowrap transition-all', 'flex-1 transition-all',
'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2',
'disabled:pointer-events-none disabled:opacity-50',
SIZE_CLASSES[size], SIZE_CLASSES[size],
value === option.value ? SELECTED_CLASSES : UNSELECTED_CLASSES, value === option.value ? SELECTED_CLASSES : UNSELECTED_CLASSES,
buttonClassName, buttonClassName,
)} )}
> >
{option.label} {option.label}
</button> </Button>
))} ))}
</div> </div>
); );
+6 -3
View File
@@ -3,6 +3,7 @@ import { X } from 'lucide-react';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { toast } from 'sonner'; // 推荐使用 shadcn 的默认 Toast import { toast } from 'sonner'; // 推荐使用 shadcn 的默认 Toast
import { CopyButton } from '@/components/CopyButton'; import { CopyButton } from '@/components/CopyButton';
import { Button } from './ui/button';
export type ValidateRule = { export type ValidateRule = {
validator: (value: string) => boolean; validator: (value: string) => boolean;
@@ -273,14 +274,16 @@ const TextInputArea = forwardRef<HTMLTextAreaElement, TextInputAreaProps>((props
<CopyButton text={value} tooltip={'复制内容'} size="sm" className="h-7 w-7 p-1" /> <CopyButton text={value} tooltip={'复制内容'} size="sm" className="h-7 w-7 p-1" />
)} )}
{showClear && value && !disabled && !readOnly && ( {showClear && value && !disabled && !readOnly && (
<button <Button
type="button" type="button"
onClick={handleClear} onClick={handleClear}
aria-label={'清空'} aria-label={'清空'}
className="p-1 h-7 w-7 flex items-center justify-center rounded-md text-muted-foreground hover:text-destructive hover:bg-destructive/10 transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring" variant="ghost"
size="icon"
className="h-7 w-7 text-muted-foreground hover:text-destructive hover:bg-destructive/10"
> >
<X className="h-4 w-4" /> <X className="h-4 w-4" />
</button> </Button>
)} )}
</div> </div>
</div> </div>