index.tsx 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. import type { CSSProperties } from 'react'
  2. import React from 'react'
  3. import { type VariantProps, cva } from 'class-variance-authority'
  4. import Spinner from '../spinner'
  5. import classNames from '@/utils/classnames'
  6. const buttonVariants = cva(
  7. 'btn disabled:btn-disabled',
  8. {
  9. variants: {
  10. variant: {
  11. 'primary': 'btn-primary',
  12. 'warning': 'btn-warning',
  13. 'secondary': 'btn-secondary',
  14. 'secondary-accent': 'btn-secondary-accent',
  15. 'ghost': 'btn-ghost',
  16. 'ghost-accent': 'btn-ghost-accent',
  17. 'tertiary': 'btn-tertiary',
  18. },
  19. size: {
  20. small: 'btn-small',
  21. medium: 'btn-medium',
  22. large: 'btn-large',
  23. },
  24. },
  25. defaultVariants: {
  26. variant: 'secondary',
  27. size: 'medium',
  28. },
  29. },
  30. )
  31. export type ButtonProps = {
  32. destructive?: boolean
  33. loading?: boolean
  34. styleCss?: CSSProperties
  35. spinnerClassName?: string
  36. } & React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<typeof buttonVariants>
  37. const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  38. ({ className, variant, size, destructive, loading, styleCss, children, spinnerClassName, ...props }, ref) => {
  39. return (
  40. <button
  41. type='button'
  42. className={classNames(
  43. buttonVariants({ variant, size, className }),
  44. destructive && 'btn-destructive',
  45. )}
  46. ref={ref}
  47. style={styleCss}
  48. {...props}
  49. >
  50. {children}
  51. {loading && <Spinner loading={loading} className={classNames('!text-white !h-3 !w-3 !border-2 !ml-1', spinnerClassName)} />}
  52. </button>
  53. )
  54. },
  55. )
  56. Button.displayName = 'Button'
  57. export default Button
  58. export { Button, buttonVariants }