buster/web/src/components/ui/buttons/AppButton.tsx

81 lines
2.2 KiB
TypeScript
Raw Normal View History

2025-02-23 04:50:10 +08:00
import * as React from 'react';
import { Slot } from '@radix-ui/react-slot';
import { cva, type VariantProps } from 'class-variance-authority';
2025-02-23 05:01:55 +08:00
import { cn } from '@/lib/classMerge';
2025-02-23 05:58:58 +08:00
import { CircleSpinnerLoader } from '../loaders/CircleSpinnerLoader';
2025-02-23 05:01:55 +08:00
const buttonVariants = cva(
2025-02-23 05:58:58 +08:00
'inline-flex items-center justify-center gap-1.5 shadow-btn rounded transition-all duration-200 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none cursor-pointer disabled:cursor-not-allowed data-[loading=true]:cursor-progress px-2.5 py-1.5',
2025-02-23 05:01:55 +08:00
{
variants: {
2025-02-23 05:58:58 +08:00
buttonType: {
default:
'bg-white border hover:bg-item-hover disabled:bg-disabled disabled:text-foreground active:bg-item-active data-[selected=true]:bg-disabled',
2025-02-23 05:01:55 +08:00
black: 'bg-black text-white hover:bg-gray-900',
2025-02-23 05:58:58 +08:00
primary: 'bg-primary text-white hover:bg-primary-light '
2025-02-23 05:01:55 +08:00
},
size: {
default: 'h-6',
tall: 'h-8'
}
},
defaultVariants: {
2025-02-23 05:58:58 +08:00
buttonType: 'default',
2025-02-23 05:01:55 +08:00
size: 'default'
}
}
);
export interface ButtonProps
2025-02-23 05:58:58 +08:00
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'prefix'>,
2025-02-23 05:01:55 +08:00
VariantProps<typeof buttonVariants> {
asChild?: boolean;
2025-02-23 05:58:58 +08:00
prefix?: React.ReactNode;
suffix?: React.ReactNode;
loading?: boolean;
selected?: boolean;
2025-02-23 05:01:55 +08:00
}
const AppButton = React.forwardRef<HTMLButtonElement, ButtonProps>(
2025-02-23 05:58:58 +08:00
(
{
className,
buttonType,
size,
asChild = false,
prefix,
suffix,
children,
loading = false,
selected = false,
...props
},
ref
) => {
2025-02-23 05:01:55 +08:00
const Comp = asChild ? Slot : 'button';
return (
2025-02-23 05:58:58 +08:00
<Comp
className={cn(buttonVariants({ buttonType, size, className }))}
ref={ref}
disabled={props.disabled}
data-loading={loading}
data-selected={selected}
{...props}>
{loading ? (
<div className="animate-in fade-in text-black duration-400 dark:text-white">
<CircleSpinnerLoader size={9} />
</div>
) : (
prefix && <span>{prefix}</span>
)}
{children}
{suffix && <span>{suffix}</span>}
</Comp>
2025-02-23 05:01:55 +08:00
);
}
);
AppButton.displayName = 'AppButton';
export { AppButton, buttonVariants };