您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

ContextMenuItem.tsx 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import React, { ReactNode } from 'react';
  2. import { useSelector } from 'react-redux';
  3. import { makeStyles } from 'tss-react/mui';
  4. import { showOverflowDrawer } from '../../../../toolbox/functions.web';
  5. import Icon from '../../../icons/components/Icon';
  6. import { withPixelLineHeight } from '../../../styles/functions.web';
  7. import { TEXT_OVERFLOW_TYPES } from '../../constants.any';
  8. import TextWithOverflow from './TextWithOverflow';
  9. export interface IProps {
  10. /**
  11. * Label used for accessibility.
  12. */
  13. accessibilityLabel: string;
  14. /**
  15. * Component children.
  16. */
  17. children?: ReactNode;
  18. /**
  19. * CSS class name used for custom styles.
  20. */
  21. className?: string;
  22. /**
  23. * Id of dom element controlled by this item. Matches aria-controls.
  24. * Useful if you need this item as a tab element.
  25. *
  26. */
  27. controls?: string;
  28. /**
  29. * Custom icon. If used, the icon prop is ignored.
  30. * Used to allow custom children instead of just the default icons.
  31. */
  32. customIcon?: ReactNode;
  33. /**
  34. * Whether or not the action is disabled.
  35. */
  36. disabled?: boolean;
  37. /**
  38. * Default icon for action.
  39. */
  40. icon?: Function;
  41. /**
  42. * Id of the action container.
  43. */
  44. id?: string;
  45. /**
  46. * Click handler.
  47. */
  48. onClick?: (e?: React.MouseEvent) => void;
  49. /**
  50. * Keydown handler.
  51. */
  52. onKeyDown?: (e: React.KeyboardEvent<HTMLDivElement>) => void;
  53. /**
  54. * Keypress handler.
  55. */
  56. onKeyPress?: (e?: React.KeyboardEvent) => void;
  57. /**
  58. * Overflow type for item text.
  59. */
  60. overflowType?: TEXT_OVERFLOW_TYPES;
  61. /**
  62. * You can use this item as a tab. Defaults to button if not set.
  63. */
  64. role?: 'tab' | 'button';
  65. /**
  66. * Whether the item is marked as selected.
  67. */
  68. selected?: boolean;
  69. /**
  70. * TestId of the element, if any.
  71. */
  72. testId?: string;
  73. /**
  74. * Action text.
  75. */
  76. text?: string;
  77. /**
  78. * Class name for the text.
  79. */
  80. textClassName?: string;
  81. }
  82. const useStyles = makeStyles()(theme => {
  83. return {
  84. contextMenuItem: {
  85. alignItems: 'center',
  86. cursor: 'pointer',
  87. display: 'flex',
  88. minHeight: '40px',
  89. padding: '10px 16px',
  90. boxSizing: 'border-box',
  91. '& > *:not(:last-child)': {
  92. marginRight: theme.spacing(3)
  93. },
  94. '&:hover': {
  95. backgroundColor: theme.palette.ui02
  96. },
  97. '&:active': {
  98. backgroundColor: theme.palette.ui03
  99. },
  100. '&.focus-visible': {
  101. boxShadow: `inset 0 0 0 2px ${theme.palette.action01Hover}`
  102. }
  103. },
  104. selected: {
  105. borderLeft: `3px solid ${theme.palette.action01Hover}`,
  106. paddingLeft: '13px',
  107. backgroundColor: theme.palette.ui02
  108. },
  109. contextMenuItemDisabled: {
  110. pointerEvents: 'none'
  111. },
  112. contextMenuItemDrawer: {
  113. padding: '13px 16px'
  114. },
  115. contextMenuItemIcon: {
  116. '& svg': {
  117. fill: theme.palette.icon01
  118. }
  119. },
  120. text: {
  121. ...withPixelLineHeight(theme.typography.bodyShortRegular),
  122. color: theme.palette.text01
  123. },
  124. drawerText: {
  125. ...withPixelLineHeight(theme.typography.bodyShortRegularLarge)
  126. }
  127. };
  128. });
  129. const ContextMenuItem = ({
  130. accessibilityLabel,
  131. children,
  132. className,
  133. controls,
  134. customIcon,
  135. disabled,
  136. id,
  137. icon,
  138. onClick,
  139. onKeyDown,
  140. onKeyPress,
  141. overflowType,
  142. role = 'button',
  143. selected,
  144. testId,
  145. text,
  146. textClassName }: IProps) => {
  147. const { classes: styles, cx } = useStyles();
  148. const _overflowDrawer: boolean = useSelector(showOverflowDrawer);
  149. return (
  150. <div
  151. aria-controls = { controls }
  152. aria-disabled = { disabled }
  153. aria-label = { accessibilityLabel }
  154. aria-selected = { role === 'tab' ? selected : undefined }
  155. className = { cx(styles.contextMenuItem,
  156. _overflowDrawer && styles.contextMenuItemDrawer,
  157. disabled && styles.contextMenuItemDisabled,
  158. selected && styles.selected,
  159. className
  160. ) }
  161. data-testid = { testId }
  162. id = { id }
  163. key = { text }
  164. onClick = { disabled ? undefined : onClick }
  165. onKeyDown = { disabled ? undefined : onKeyDown }
  166. onKeyPress = { disabled ? undefined : onKeyPress }
  167. role = { role }
  168. tabIndex = { role === 'tab'
  169. ? selected ? 0 : -1
  170. : disabled ? undefined : 0
  171. }>
  172. {customIcon ? customIcon
  173. : icon && <Icon
  174. className = { styles.contextMenuItemIcon }
  175. size = { 20 }
  176. src = { icon } />}
  177. {text && (
  178. <TextWithOverflow
  179. className = { cx(styles.text,
  180. _overflowDrawer && styles.drawerText,
  181. textClassName) }
  182. overflowType = { overflowType } >
  183. {text}
  184. </TextWithOverflow>
  185. )}
  186. {children}
  187. </div>
  188. );
  189. };
  190. export default ContextMenuItem;