accessibilityTableCell.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import {ComponentProps, CSSProperties, forwardRef} from 'react';
  2. import classNames from 'classnames';
  3. import {
  4. Cell,
  5. CodeHighlightCell,
  6. Text,
  7. } from 'sentry/components/replays/virtualizedGrid/bodyCell';
  8. import {Tooltip} from 'sentry/components/tooltip';
  9. import {IconFire, IconInfo, IconWarning} from 'sentry/icons';
  10. import type useCrumbHandlers from 'sentry/utils/replays/hooks/useCrumbHandlers';
  11. import {HydratedA11yFrame} from 'sentry/utils/replays/hydrateA11yFrame';
  12. import {Color} from 'sentry/utils/theme';
  13. import useUrlParams from 'sentry/utils/useUrlParams';
  14. import useSortAccessibility from 'sentry/views/replays/detail/accessibility/useSortAccessibility';
  15. const EMPTY_CELL = '--';
  16. const IMPACT_ICON_MAPPING: Record<keyof HydratedA11yFrame['impact'], Color> = {
  17. minor: <IconInfo size="xs" />,
  18. moderate: <IconInfo size="xs" />,
  19. serious: <IconWarning size="xs" color="yellow400" />,
  20. critical: <IconFire size="xs" color="red400" />,
  21. };
  22. interface Props extends ReturnType<typeof useCrumbHandlers> {
  23. a11yIssue: HydratedA11yFrame;
  24. columnIndex: number;
  25. currentHoverTime: number | undefined;
  26. currentTime: number;
  27. onClickCell: (props: {dataIndex: number; rowIndex: number}) => void;
  28. rowIndex: number;
  29. sortConfig: ReturnType<typeof useSortAccessibility>['sortConfig'];
  30. style: CSSProperties;
  31. }
  32. const AccessibilityTableCell = forwardRef<HTMLDivElement, Props>(
  33. (
  34. {
  35. a11yIssue,
  36. columnIndex,
  37. currentHoverTime,
  38. currentTime,
  39. onClickCell,
  40. onMouseEnter,
  41. onMouseLeave,
  42. rowIndex,
  43. sortConfig,
  44. style,
  45. }: Props,
  46. ref
  47. ) => {
  48. // Rows include the sortable header, the dataIndex does not
  49. const dataIndex = rowIndex - 1;
  50. const {getParamValue} = useUrlParams('a_detail_row', '');
  51. const isSelected = getParamValue() === String(dataIndex);
  52. const hasOccurred = currentTime >= a11yIssue.offsetMs;
  53. const isBeforeHover =
  54. currentHoverTime === undefined || currentHoverTime >= a11yIssue.offsetMs;
  55. const isByTimestamp = sortConfig.by === 'timestampMs';
  56. const isAsc = isByTimestamp ? sortConfig.asc : undefined;
  57. const columnProps = {
  58. className: classNames({
  59. beforeCurrentTime: isByTimestamp
  60. ? isAsc
  61. ? hasOccurred
  62. : !hasOccurred
  63. : undefined,
  64. afterCurrentTime: isByTimestamp
  65. ? isAsc
  66. ? !hasOccurred
  67. : hasOccurred
  68. : undefined,
  69. beforeHoverTime:
  70. isByTimestamp && currentHoverTime !== undefined
  71. ? isAsc
  72. ? isBeforeHover
  73. : !isBeforeHover
  74. : undefined,
  75. afterHoverTime:
  76. isByTimestamp && currentHoverTime !== undefined
  77. ? isAsc
  78. ? !isBeforeHover
  79. : isBeforeHover
  80. : undefined,
  81. }),
  82. hasOccurred: isByTimestamp ? hasOccurred : undefined,
  83. isSelected,
  84. onClick: () => onClickCell({dataIndex, rowIndex}),
  85. onMouseEnter: () => onMouseEnter(a11yIssue),
  86. onMouseLeave: () => onMouseLeave(a11yIssue),
  87. ref,
  88. style,
  89. } as ComponentProps<typeof Cell>;
  90. const renderFns = [
  91. () => (
  92. <Cell {...columnProps}>
  93. <Text>
  94. {a11yIssue.impact ? (
  95. <Tooltip title={a11yIssue.impact ?? EMPTY_CELL}>
  96. {IMPACT_ICON_MAPPING[a11yIssue.impact]}
  97. </Tooltip>
  98. ) : (
  99. EMPTY_CELL
  100. )}
  101. </Text>
  102. </Cell>
  103. ),
  104. () => (
  105. <Cell {...columnProps}>
  106. <Text>{a11yIssue.id ?? EMPTY_CELL}</Text>
  107. </Cell>
  108. ),
  109. () => (
  110. <Cell {...columnProps}>
  111. <CodeHighlightCell language="html" hideCopyButton data-render-inline>
  112. {a11yIssue.element.element ?? EMPTY_CELL}
  113. </CodeHighlightCell>
  114. </Cell>
  115. ),
  116. ];
  117. return renderFns[columnIndex]();
  118. }
  119. );
  120. export default AccessibilityTableCell;