PayButton.tsx 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. 'use client';
  2. import './payButton.scss';
  3. import { cn } from '@/lib/utils/client';
  4. export type PayButtonState = 'idle'|'loading'|'success';
  5. type Props = {
  6. state: PayButtonState;
  7. label: string;
  8. icon?: React.ReactNode;
  9. onClick?: () => void;
  10. disabled?: boolean;
  11. className?: string;
  12. type?: 'button'|'submit';
  13. };
  14. export default function PayButton({
  15. state,
  16. label,
  17. icon,
  18. onClick,
  19. disabled,
  20. className,
  21. type = 'button'
  22. }: Props)
  23. {
  24. const isBusy = state === 'loading' || state === 'success';
  25. return (
  26. <button
  27. type={type}
  28. disabled={disabled || isBusy}
  29. onClick={onClick}
  30. className={cn(
  31. 'pay-button',
  32. state === 'loading' && 'pay-button--loading',
  33. state === 'success' && 'pay-button--success',
  34. className
  35. )}
  36. >
  37. <span className='pay-button__label'>
  38. {icon}
  39. {label}
  40. </span>
  41. <span className='pay-button__spinner' aria-hidden>
  42. <svg viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
  43. <circle cx='12' cy='12' r='9' stroke='rgba(255,255,255,0.25)' strokeWidth='3' />
  44. <path
  45. d='M21 12a9 9 0 0 0-9-9'
  46. stroke='#fff'
  47. strokeWidth='3'
  48. strokeLinecap='round'
  49. />
  50. </svg>
  51. </span>
  52. <span className='pay-button__check' aria-hidden>
  53. <svg viewBox='0 0 28 28' fill='none' xmlns='http://www.w3.org/2000/svg'>
  54. <path
  55. d='M6 14.5 11.5 20 22 9'
  56. stroke='#fff'
  57. strokeWidth='3'
  58. strokeLinecap='round'
  59. strokeLinejoin='round'
  60. />
  61. </svg>
  62. </span>
  63. </button>
  64. );
  65. }