You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Icon.tsx 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /* eslint-disable import/order */
  2. import React, { useCallback } from 'react';
  3. // @ts-ignore
  4. import { Container } from '../../react/base';
  5. // @ts-ignore
  6. import { styleTypeToObject } from '../../styles';
  7. type Props = {
  8. /**
  9. * Class name for the web platform, if any.
  10. */
  11. className?: string,
  12. /**
  13. * Color of the icon (if not provided by the style object).
  14. */
  15. color?: string,
  16. /**
  17. * Id prop (mainly for autotests).
  18. */
  19. id?: string,
  20. /**
  21. * Id of the icon container.
  22. */
  23. containerId?: string,
  24. /**
  25. * Function to invoke on click.
  26. */
  27. onClick?: Function,
  28. /**
  29. * The size of the icon (if not provided by the style object).
  30. */
  31. size?: number | string,
  32. /**
  33. * The preloaded icon component to render.
  34. */
  35. src: Function,
  36. /**
  37. * Style object to be applied.
  38. */
  39. style?: Object,
  40. /**
  41. * Aria disabled flag for the Icon.
  42. */
  43. ariaDisabled?: boolean,
  44. /**
  45. * Aria label for the Icon.
  46. */
  47. ariaLabel?: string,
  48. /**
  49. * Whether the element has a popup.
  50. */
  51. ariaHasPopup?: boolean,
  52. /**
  53. * Whether the element has a pressed.
  54. */
  55. ariaPressed?: boolean,
  56. /**
  57. * Id of description label.
  58. */
  59. ariaDescribedBy?: string,
  60. /**
  61. * Whether the element popup is expanded.
  62. */
  63. ariaExpanded?: boolean,
  64. /**
  65. * The id of the element this button icon controls.
  66. */
  67. ariaControls?: string,
  68. /**
  69. * TabIndex for the Icon.
  70. */
  71. tabIndex?: number,
  72. /**
  73. * Role for the Icon.
  74. */
  75. role?: string,
  76. /**
  77. * Keypress handler.
  78. */
  79. onKeyPress?: Function,
  80. /**
  81. * Keydown handler.
  82. */
  83. onKeyDown?: Function
  84. }
  85. export const DEFAULT_COLOR = navigator.product === 'ReactNative' ? 'white' : undefined;
  86. export const DEFAULT_SIZE = navigator.product === 'ReactNative' ? 36 : 22;
  87. /**
  88. * Implements an Icon component that takes a loaded SVG file as prop and renders it as an icon.
  89. *
  90. * @param {Props} props - The props of the component.
  91. * @returns {ReactElement}
  92. */
  93. export default function Icon(props: Props) {
  94. const {
  95. className,
  96. color,
  97. id,
  98. containerId,
  99. onClick,
  100. size,
  101. src: IconComponent,
  102. style,
  103. ariaHasPopup,
  104. ariaLabel,
  105. ariaDisabled,
  106. ariaExpanded,
  107. ariaControls,
  108. tabIndex,
  109. ariaPressed,
  110. ariaDescribedBy,
  111. role,
  112. onKeyPress,
  113. onKeyDown,
  114. ...rest
  115. }: Props = props;
  116. const {
  117. color: styleColor,
  118. fontSize: styleSize,
  119. ...restStyle
  120. } = styleTypeToObject(style ?? {});
  121. const calculatedColor = color ?? styleColor ?? DEFAULT_COLOR;
  122. const calculatedSize = size ?? styleSize ?? DEFAULT_SIZE;
  123. const onKeyPressHandler = useCallback(e => {
  124. if ((e.key === 'Enter' || e.key === ' ') && onClick) {
  125. e.preventDefault();
  126. onClick(e);
  127. } else if (onKeyPress) {
  128. onKeyPress(e);
  129. }
  130. }, [ onClick, onKeyPress ]);
  131. const jitsiIconClassName = calculatedColor ? 'jitsi-icon' : 'jitsi-icon jitsi-icon-default';
  132. return (
  133. <Container
  134. { ...rest }
  135. aria-controls = { ariaControls }
  136. aria-describedby = { ariaDescribedBy }
  137. aria-disabled = { ariaDisabled }
  138. aria-expanded = { ariaExpanded }
  139. aria-haspopup = { ariaHasPopup }
  140. aria-label = { ariaLabel }
  141. aria-pressed = { ariaPressed }
  142. className = { `${jitsiIconClassName} ${className || ''}` }
  143. id = { containerId }
  144. onClick = { onClick }
  145. onKeyDown = { onKeyDown }
  146. onKeyPress = { onKeyPressHandler }
  147. role = { role }
  148. style = { restStyle }
  149. tabIndex = { tabIndex }>
  150. <IconComponent
  151. fill = { calculatedColor }
  152. height = { calculatedSize }
  153. id = { id }
  154. width = { calculatedSize } />
  155. </Container>
  156. );
  157. }
  158. Icon.defaultProps = {
  159. className: ''
  160. };