ds-button.tsx 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import { forwardRef, ReactNode } from 'react'
  2. import { Button, ButtonProps, Spinner } from 'react-bootstrap'
  3. import { useTranslation } from 'react-i18next'
  4. import classNames from 'classnames'
  5. type DSButtonProps = Pick<
  6. ButtonProps,
  7. | 'children'
  8. | 'disabled'
  9. | 'href'
  10. | 'id'
  11. | 'target'
  12. | 'rel'
  13. | 'onClick'
  14. | 'onMouseDown'
  15. | 'onMouseOver'
  16. | 'onMouseOut'
  17. | 'onFocus'
  18. | 'onBlur'
  19. | 'size'
  20. | 'active'
  21. | 'type'
  22. > & {
  23. leadingIcon?: ReactNode
  24. trailingIcon?: ReactNode
  25. variant?: 'primary' | 'secondary' | 'tertiary' | 'danger'
  26. isLoading?: boolean
  27. loadingLabel?: string
  28. }
  29. const DSButton = forwardRef<HTMLButtonElement, DSButtonProps>(
  30. (
  31. {
  32. children,
  33. leadingIcon,
  34. isLoading = false,
  35. loadingLabel,
  36. trailingIcon,
  37. variant = 'primary',
  38. size,
  39. ...props
  40. },
  41. ref
  42. ) => {
  43. const { t } = useTranslation()
  44. const buttonClassName = classNames('d-inline-grid btn-ds', {
  45. 'button-loading': isLoading,
  46. })
  47. const loadingSpinnerClassName =
  48. size === 'lg' ? 'loading-spinner-large' : 'loading-spinner-small'
  49. return (
  50. <Button
  51. className={buttonClassName}
  52. variant={variant}
  53. size={size}
  54. {...props}
  55. ref={ref}
  56. disabled={isLoading || props.disabled}
  57. data-ol-loading={isLoading}
  58. role={undefined}
  59. >
  60. {isLoading && (
  61. <span className="spinner-container">
  62. <Spinner
  63. size="sm"
  64. animation="border"
  65. aria-hidden="true"
  66. className={loadingSpinnerClassName}
  67. />
  68. <span className="visually-hidden">
  69. {loadingLabel ?? t('loading')}
  70. </span>
  71. </span>
  72. )}
  73. <span className="button-content" aria-hidden={isLoading}>
  74. {leadingIcon}
  75. {children}
  76. {trailingIcon}
  77. </span>
  78. </Button>
  79. )
  80. }
  81. )
  82. DSButton.displayName = 'DSButton'
  83. export default DSButton