您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

button.tsx 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import { Slot } from '@radix-ui/react-slot';
  2. import { cva, type VariantProps } from 'class-variance-authority';
  3. import * as React from 'react';
  4. import { cn } from '@/lib/utils';
  5. import { Loader2, Plus } from 'lucide-react';
  6. const buttonVariants = cva(
  7. 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
  8. {
  9. variants: {
  10. variant: {
  11. default: 'bg-primary text-primary-foreground hover:bg-primary/90',
  12. destructive:
  13. 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
  14. outline:
  15. 'border border-text-sub-title-invert bg-transparent hover:bg-accent hover:text-accent-foreground',
  16. secondary: 'bg-bg-card text-secondary-foreground hover:bg-secondary/80',
  17. ghost: 'hover:bg-accent hover:text-accent-foreground',
  18. link: 'text-primary underline-offset-4 hover:underline',
  19. tertiary:
  20. 'bg-colors-background-sentiment-solid-primary text-colors-text-persist-light hover:bg-colors-background-sentiment-solid-primary/80',
  21. icon: 'bg-colors-background-inverse-standard text-foreground hover:bg-colors-background-inverse-standard/80',
  22. dashed: 'border border-dashed border-input hover:bg-accent',
  23. transparent: 'bg-transparent hover:bg-accent border',
  24. },
  25. size: {
  26. default: 'h-8 px-2.5 py-1.5 ',
  27. sm: 'h-6 rounded-sm px-2',
  28. lg: 'h-11 rounded-md px-8',
  29. icon: 'h-10 w-10',
  30. auto: 'h-full px-1',
  31. },
  32. },
  33. defaultVariants: {
  34. variant: 'default',
  35. size: 'default',
  36. },
  37. },
  38. );
  39. export interface ButtonProps
  40. extends React.ButtonHTMLAttributes<HTMLButtonElement>,
  41. VariantProps<typeof buttonVariants> {
  42. asChild?: boolean;
  43. }
  44. const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  45. ({ className, variant, size, asChild = false, ...props }, ref) => {
  46. const Comp = asChild ? Slot : 'button';
  47. return (
  48. <Comp
  49. className={cn(
  50. 'bg-bg-card',
  51. buttonVariants({ variant, size, className }),
  52. )}
  53. ref={ref}
  54. {...props}
  55. />
  56. );
  57. },
  58. );
  59. Button.displayName = 'Button';
  60. export const ButtonLoading = React.forwardRef<
  61. HTMLButtonElement,
  62. ButtonProps & { loading?: boolean }
  63. >(
  64. (
  65. {
  66. className,
  67. variant,
  68. size,
  69. asChild = false,
  70. children,
  71. loading = false,
  72. disabled,
  73. ...props
  74. },
  75. ref,
  76. ) => {
  77. const Comp = asChild ? Slot : 'button';
  78. return (
  79. <Comp
  80. className={cn(buttonVariants({ variant, size, className }))}
  81. ref={ref}
  82. {...props}
  83. disabled={loading || disabled}
  84. >
  85. {loading && <Loader2 className="animate-spin" />}
  86. {children}
  87. </Comp>
  88. );
  89. },
  90. );
  91. ButtonLoading.displayName = 'ButtonLoading';
  92. export { Button, buttonVariants };
  93. export const BlockButton = React.forwardRef<HTMLButtonElement, ButtonProps>(
  94. ({ children, className, ...props }, ref) => {
  95. return (
  96. <Button
  97. variant={'outline'}
  98. ref={ref}
  99. className={cn('w-full border-dashed border-input-border', className)}
  100. {...props}
  101. >
  102. <Plus /> {children}
  103. </Button>
  104. );
  105. },
  106. );