Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

Button.tsx 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. import { makeStyles } from '@material-ui/core';
  2. import clsx from 'clsx';
  3. import React from 'react';
  4. import { useTranslation } from 'react-i18next';
  5. import Icon from '../../../icons/components/Icon';
  6. import { withPixelLineHeight } from '../../../styles/functions.web';
  7. import { BUTTON_TYPES } from '../../constants';
  8. import { Theme } from '../../types';
  9. import { ButtonProps } from '../types';
  10. interface IButtonProps extends ButtonProps {
  11. /**
  12. * Class name used for additional styles.
  13. */
  14. className?: string,
  15. /**
  16. * Whether or not the button should be full width.
  17. */
  18. fullWidth?: boolean,
  19. /**
  20. * The id of the button.
  21. */
  22. id?: string;
  23. /**
  24. * Whether or not the button is a submit form button.
  25. */
  26. isSubmit?: boolean;
  27. /**
  28. * Text to be displayed on the component.
  29. * Used when there's no labelKey.
  30. */
  31. label?: string;
  32. /**
  33. * Which size the button should be.
  34. */
  35. size?: 'small' | 'medium' | 'large';
  36. /**
  37. * Data test id.
  38. */
  39. testId?: string;
  40. }
  41. const useStyles = makeStyles((theme: Theme) => {
  42. return {
  43. button: {
  44. backgroundColor: theme.palette.action01,
  45. color: theme.palette.text01,
  46. borderRadius: theme.shape.borderRadius,
  47. padding: '10px 16px',
  48. display: 'flex',
  49. alignItems: 'center',
  50. justifyContent: 'center',
  51. border: 0,
  52. ...withPixelLineHeight(theme.typography.bodyShortBold),
  53. transition: 'background .2s',
  54. cursor: 'pointer',
  55. '&:hover': {
  56. backgroundColor: theme.palette.action01Hover
  57. },
  58. '&:active': {
  59. backgroundColor: theme.palette.action01Active
  60. },
  61. '&:focus': {
  62. outline: 0,
  63. boxShadow: `0px 0px 0px 2px ${theme.palette.focus01}`
  64. },
  65. '& svg': {
  66. fill: theme.palette.icon01
  67. }
  68. },
  69. primary: {},
  70. secondary: {
  71. backgroundColor: theme.palette.action02,
  72. color: theme.palette.text04,
  73. '&:hover': {
  74. backgroundColor: theme.palette.action02Hover
  75. },
  76. '&:active': {
  77. backgroundColor: theme.palette.action02Active
  78. },
  79. '& svg': {
  80. fill: theme.palette.icon04
  81. }
  82. },
  83. tertiary: {
  84. backgroundColor: theme.palette.action03,
  85. '&:hover': {
  86. backgroundColor: theme.palette.action03Hover
  87. },
  88. '&:active': {
  89. backgroundColor: theme.palette.action03Active
  90. }
  91. },
  92. destructive: {
  93. backgroundColor: theme.palette.actionDanger,
  94. '&:hover': {
  95. backgroundColor: theme.palette.actionDangerHover
  96. },
  97. '&:active': {
  98. backgroundColor: theme.palette.actionDangerActive
  99. }
  100. },
  101. disabled: {
  102. backgroundColor: theme.palette.disabled01,
  103. color: theme.palette.text03,
  104. '&:hover': {
  105. backgroundColor: theme.palette.disabled01,
  106. color: theme.palette.text03
  107. },
  108. '&:active': {
  109. backgroundColor: theme.palette.disabled01,
  110. color: theme.palette.text03
  111. },
  112. '& svg': {
  113. fill: theme.palette.icon03
  114. }
  115. },
  116. iconButton: {
  117. padding: '10px'
  118. },
  119. textWithIcon: {
  120. marginLeft: `${theme.spacing(2)}px`
  121. },
  122. small: {
  123. padding: '8px 16px',
  124. ...withPixelLineHeight(theme.typography.labelBold),
  125. '&.iconButton': {
  126. padding: '6px'
  127. }
  128. },
  129. medium: {},
  130. large: {
  131. padding: '13px 16px',
  132. ...withPixelLineHeight(theme.typography.bodyShortBoldLarge),
  133. '&.iconButton': {
  134. padding: '14px'
  135. }
  136. },
  137. fullWidth: {
  138. width: '100%'
  139. }
  140. };
  141. });
  142. const Button = ({
  143. accessibilityLabel,
  144. className,
  145. disabled,
  146. fullWidth,
  147. icon,
  148. id,
  149. isSubmit,
  150. label,
  151. labelKey,
  152. onClick = () => null,
  153. size = 'medium',
  154. testId,
  155. type = BUTTON_TYPES.PRIMARY
  156. }: IButtonProps) => {
  157. const styles = useStyles();
  158. const { t } = useTranslation();
  159. return (
  160. <button
  161. aria-label = { accessibilityLabel }
  162. className = { clsx(styles.button, styles[type],
  163. disabled && styles.disabled,
  164. icon && !(labelKey || label) && `${styles.iconButton} iconButton`,
  165. styles[size], fullWidth && styles.fullWidth, className) }
  166. data-testid = { testId }
  167. disabled = { disabled }
  168. { ...(id ? { id } : {}) }
  169. onClick = { onClick }
  170. title = { accessibilityLabel }
  171. type = { isSubmit ? 'submit' : 'button' }>
  172. {icon && <Icon
  173. size = { 20 }
  174. src = { icon } />}
  175. {(labelKey || label) && <span className = { icon ? styles.textWithIcon : '' }>
  176. {labelKey ? t(labelKey) : label}
  177. </span>}
  178. </button>
  179. );
  180. };
  181. export default Button;