accessibilityTableCell.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. // startTimestampMs: number;
  31. style: CSSProperties;
  32. }
  33. const AccessibilityTableCell = forwardRef<HTMLDivElement, Props>(
  34. (
  35. {
  36. a11yIssue,
  37. columnIndex,
  38. currentHoverTime,
  39. currentTime,
  40. onClickCell,
  41. onMouseEnter,
  42. onMouseLeave,
  43. rowIndex,
  44. sortConfig,
  45. style,
  46. }: Props,
  47. ref
  48. ) => {
  49. // Rows include the sortable header, the dataIndex does not
  50. const dataIndex = rowIndex - 1;
  51. const {getParamValue} = useUrlParams('a_detail_row', '');
  52. const isSelected = getParamValue() === String(dataIndex);
  53. const hasOccurred = currentTime >= a11yIssue.offsetMs;
  54. const isBeforeHover =
  55. currentHoverTime === undefined || currentHoverTime >= a11yIssue.offsetMs;
  56. const isByTimestamp = sortConfig.by === 'timestampMs';
  57. const isAsc = isByTimestamp ? sortConfig.asc : undefined;
  58. const columnProps = {
  59. className: classNames({
  60. beforeCurrentTime: isByTimestamp
  61. ? isAsc
  62. ? hasOccurred
  63. : !hasOccurred
  64. : undefined,
  65. afterCurrentTime: isByTimestamp
  66. ? isAsc
  67. ? !hasOccurred
  68. : hasOccurred
  69. : undefined,
  70. beforeHoverTime:
  71. isByTimestamp && currentHoverTime !== undefined
  72. ? isAsc
  73. ? isBeforeHover
  74. : !isBeforeHover
  75. : undefined,
  76. afterHoverTime:
  77. isByTimestamp && currentHoverTime !== undefined
  78. ? isAsc
  79. ? !isBeforeHover
  80. : isBeforeHover
  81. : undefined,
  82. }),
  83. hasOccurred: isByTimestamp ? hasOccurred : undefined,
  84. isSelected,
  85. onClick: () => onClickCell({dataIndex, rowIndex}),
  86. onMouseEnter: () => onMouseEnter(a11yIssue),
  87. onMouseLeave: () => onMouseLeave(a11yIssue),
  88. ref,
  89. style,
  90. } as ComponentProps<typeof Cell>;
  91. const renderFns = [
  92. () => (
  93. <Cell {...columnProps}>
  94. <Text>
  95. {a11yIssue.impact ? (
  96. <Tooltip title={a11yIssue.impact ?? EMPTY_CELL}>
  97. {IMPACT_ICON_MAPPING[a11yIssue.impact]}
  98. </Tooltip>
  99. ) : (
  100. EMPTY_CELL
  101. )}
  102. </Text>
  103. </Cell>
  104. ),
  105. () => (
  106. <Cell {...columnProps}>
  107. <Text>{a11yIssue.id ?? EMPTY_CELL}</Text>
  108. </Cell>
  109. ),
  110. () => (
  111. <Cell {...columnProps}>
  112. <CodeHighlightCell language="html" hideCopyButton>
  113. {a11yIssue.element.element ?? EMPTY_CELL}
  114. </CodeHighlightCell>
  115. </Cell>
  116. ),
  117. ];
  118. return renderFns[columnIndex]();
  119. }
  120. );
  121. export default AccessibilityTableCell;