Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

ActionButton.tsx 5.9KB

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