File
Blob: src/client/components/ui/button.tsx
| 1 | import { forwardRef, type ButtonHTMLAttributes, type ReactNode } from "react"; |
| 2 | import { Loader2 } from "lucide-react"; |
| 3 | |
| 4 | import { |
| 5 | BUTTON_BASE_CLASSES, |
| 6 | BUTTON_SIZE_CLASSES, |
| 7 | BUTTON_VARIANT_CLASSES, |
| 8 | type ButtonSize, |
| 9 | type ButtonVariant, |
| 10 | } from "@/client/components/ui/button-classes"; |
| 11 | |
| 12 | export type { ButtonSize, ButtonVariant }; |
| 13 | |
| 14 | type ButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & { |
| 15 | variant?: ButtonVariant; |
| 16 | size?: ButtonSize; |
| 17 | loading?: boolean; |
| 18 | leftIcon?: ReactNode; |
| 19 | rightIcon?: ReactNode; |
| 20 | }; |
| 21 | |
| 22 | export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button( |
| 23 | { variant = "secondary", size = "md", loading, leftIcon, rightIcon, className = "", children, disabled, ...rest }, |
| 24 | ref, |
| 25 | ) { |
| 26 | return ( |
| 27 | <button |
| 28 | ref={ref} |
| 29 | disabled={disabled || loading} |
| 30 | aria-busy={loading || undefined} |
| 31 | className={`${BUTTON_BASE_CLASSES} ${BUTTON_VARIANT_CLASSES[variant]} ${BUTTON_SIZE_CLASSES[size]} ${className}`} |
| 32 | {...rest} |
| 33 | > |
| 34 | {loading ? <Loader2 className="h-3.5 w-3.5 animate-spin" strokeWidth={2.25} aria-hidden="true" /> : leftIcon} |
| 35 | {children} |
| 36 | {!loading && rightIcon} |
| 37 | </button> |
| 38 | ); |
| 39 | }); |