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

ActionButton.tsx 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. import { Theme } from '@mui/material';
  2. import React, { ReactNode, useCallback } from 'react';
  3. import { makeStyles } from 'tss-react/mui';
  4. import Icon from '../../../icons/components/Icon';
  5. import { IconArrowDown } from '../../../icons/svg';
  6. import { withPixelLineHeight } from '../../../styles/functions.web';
  7. type Props = {
  8. /**
  9. * Icon to display in the options section.
  10. */
  11. OptionsIcon?: Function;
  12. /**
  13. * The Label of the child element.
  14. */
  15. ariaDropDownLabel?: string;
  16. /**
  17. * The Label of the current element.
  18. */
  19. ariaLabel?: string;
  20. /**
  21. * To give a aria-pressed to the icon.
  22. */
  23. ariaPressed?: boolean;
  24. /**
  25. * Text of the button.
  26. */
  27. children: ReactNode;
  28. /**
  29. * Text css class of the button.
  30. */
  31. className?: string;
  32. /**
  33. * If the button is disabled or not.
  34. */
  35. disabled?: boolean;
  36. /**
  37. * If the button has options.
  38. */
  39. hasOptions?: boolean;
  40. /**
  41. * OnClick button handler.
  42. */
  43. onClick?: (e?: React.MouseEvent) => void;
  44. /**
  45. * Click handler for options.
  46. */
  47. onOptionsClick?: (e?: React.KeyboardEvent | React.MouseEvent) => void;
  48. /**
  49. * To give a role to the icon.
  50. */
  51. role?: string;
  52. /**
  53. * To navigate with the keyboard.
  54. */
  55. tabIndex?: number;
  56. /**
  57. * TestId of the button. Can be used to locate element when testing UI.
  58. */
  59. testId?: string;
  60. /**
  61. * The type of th button: primary, secondary, text.
  62. */
  63. type: string;
  64. };
  65. const useStyles = makeStyles()((theme: Theme) => {
  66. return {
  67. actionButton: {
  68. ...withPixelLineHeight(theme.typography.bodyLongBold),
  69. borderRadius: theme.shape.borderRadius,
  70. boxSizing: 'border-box',
  71. color: theme.palette.text01,
  72. cursor: 'pointer',
  73. display: 'inline-block',
  74. marginBottom: '16px',
  75. padding: '7px 16px',
  76. position: 'relative' as const,
  77. textAlign: 'center',
  78. width: '100%',
  79. border: 0,
  80. '&.primary': {
  81. background: theme.palette.action01,
  82. color: theme.palette.text01,
  83. '&:hover': {
  84. backgroundColor: theme.palette.action01Hover
  85. }
  86. },
  87. '&.secondary': {
  88. background: theme.palette.action02,
  89. color: theme.palette.text04,
  90. '&:hover': {
  91. backgroundColor: theme.palette.action02Hover
  92. }
  93. },
  94. '&.text': {
  95. width: 'auto',
  96. fontSize: '13px',
  97. margin: '0',
  98. padding: '0'
  99. },
  100. '&.disabled': {
  101. background: theme.palette.disabled01,
  102. border: '1px solid #5E6D7A',
  103. color: '#AFB6BC',
  104. cursor: 'initial',
  105. '.icon': {
  106. '& > svg': {
  107. fill: '#AFB6BC'
  108. }
  109. }
  110. },
  111. [theme.breakpoints.down(400)]: {
  112. fontSize: 16,
  113. marginBottom: 8,
  114. padding: '11px 16px'
  115. }
  116. },
  117. options: {
  118. borderRadius: Number(theme.shape.borderRadius) / 2,
  119. alignItems: 'center',
  120. display: 'flex',
  121. height: '100%',
  122. justifyContent: 'center',
  123. position: 'absolute' as const,
  124. right: 0,
  125. top: 0,
  126. width: 36,
  127. '&:hover': {
  128. backgroundColor: '#0262B6'
  129. },
  130. '& svg': {
  131. pointerEvents: 'none'
  132. }
  133. }
  134. };
  135. });
  136. /**
  137. * Button used for pre meeting actions.
  138. *
  139. * @returns {ReactElement}
  140. */
  141. function ActionButton({
  142. children,
  143. className = '',
  144. disabled,
  145. hasOptions,
  146. OptionsIcon = IconArrowDown,
  147. testId,
  148. type = 'primary',
  149. onClick,
  150. onOptionsClick,
  151. tabIndex,
  152. role,
  153. ariaPressed,
  154. ariaLabel,
  155. ariaDropDownLabel
  156. }: Props) {
  157. const { classes, cx } = useStyles();
  158. const onKeyPressHandler = useCallback(e => {
  159. if (onClick && !disabled && (e.key === ' ' || e.key === 'Enter')) {
  160. e.preventDefault();
  161. onClick(e);
  162. }
  163. }, [ onClick, disabled ]);
  164. const onOptionsKeyPressHandler = useCallback(e => {
  165. if (onOptionsClick && !disabled && (e.key === ' ' || e.key === 'Enter')) {
  166. e.preventDefault();
  167. e.stopPropagation();
  168. onOptionsClick(e);
  169. }
  170. }, [ onOptionsClick, disabled ]);
  171. const containerClasses = cx(
  172. classes.actionButton,
  173. className && className,
  174. type,
  175. disabled && 'disabled'
  176. );
  177. return (
  178. <div
  179. aria-disabled = { disabled }
  180. aria-label = { ariaLabel }
  181. className = { containerClasses }
  182. data-testid = { testId ? testId : undefined }
  183. onClick = { disabled ? undefined : onClick }
  184. onKeyPress = { onKeyPressHandler }
  185. role = 'button'
  186. tabIndex = { 0 } >
  187. {children}
  188. { hasOptions
  189. && <div
  190. aria-disabled = { disabled }
  191. aria-haspopup = 'true'
  192. aria-label = { ariaDropDownLabel }
  193. aria-pressed = { ariaPressed }
  194. className = { classes.options }
  195. data-testid = 'prejoin.joinOptions'
  196. onClick = { disabled ? undefined : onOptionsClick }
  197. onKeyPress = { onOptionsKeyPressHandler }
  198. role = { role }
  199. tabIndex = { tabIndex }>
  200. <Icon
  201. className = 'icon'
  202. size = { 14 }
  203. src = { OptionsIcon } />
  204. </div>
  205. }
  206. </div>
  207. );
  208. }
  209. export default ActionButton;