headerCell.tsx 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import {CSSProperties, forwardRef, ReactNode} from 'react';
  2. import styled from '@emotion/styled';
  3. import {Tooltip} from 'sentry/components/tooltip';
  4. import {IconArrow, IconInfo} from 'sentry/icons';
  5. import {space} from 'sentry/styles/space';
  6. import type {Crumb} from 'sentry/types/breadcrumbs';
  7. import type {NetworkSpan} from 'sentry/views/replays/types';
  8. interface SortCrumbs {
  9. asc: boolean;
  10. by: keyof Crumb | string;
  11. getValue: (row: Crumb) => any;
  12. }
  13. interface SortSpans {
  14. asc: boolean;
  15. by: keyof NetworkSpan | string;
  16. getValue: (row: NetworkSpan) => any;
  17. }
  18. type Props = {
  19. field: string;
  20. handleSort: (fieldName: string) => void;
  21. label: string;
  22. sortConfig: SortCrumbs | SortSpans;
  23. style: CSSProperties;
  24. tooltipTitle: undefined | ReactNode;
  25. };
  26. const StyledIconInfo = styled(IconInfo)`
  27. display: block;
  28. `;
  29. function CatchClicks({children}: {children: ReactNode}) {
  30. return <div onClick={e => e.stopPropagation()}>{children}</div>;
  31. }
  32. const HeaderCell = forwardRef<HTMLButtonElement, Props>(
  33. ({field, handleSort, label, sortConfig, style, tooltipTitle}: Props, ref) => (
  34. <HeaderButton style={style} onClick={() => handleSort(field)} ref={ref}>
  35. {label}
  36. {tooltipTitle ? (
  37. <Tooltip isHoverable title={<CatchClicks>{tooltipTitle}</CatchClicks>}>
  38. <StyledIconInfo size="xs" />
  39. </Tooltip>
  40. ) : null}
  41. <IconArrow
  42. color="gray300"
  43. size="xs"
  44. direction={sortConfig.by === field && !sortConfig.asc ? 'down' : 'up'}
  45. style={{visibility: sortConfig.by === field ? 'visible' : 'hidden'}}
  46. />
  47. </HeaderButton>
  48. )
  49. );
  50. const HeaderButton = styled('button')`
  51. border: 0;
  52. border-bottom: 1px solid ${p => p.theme.border};
  53. background: ${p => p.theme.backgroundSecondary};
  54. color: ${p => p.theme.subText};
  55. font-size: ${p => p.theme.fontSizeSmall};
  56. font-weight: 600;
  57. line-height: 16px;
  58. text-align: unset;
  59. text-transform: uppercase;
  60. white-space: nowrap;
  61. width: 100%;
  62. display: flex;
  63. align-items: center;
  64. justify-content: space-between;
  65. padding: ${space(0.5)} ${space(1)} ${space(0.5)} ${space(1.5)};
  66. svg {
  67. margin-left: ${space(0.25)};
  68. }
  69. `;
  70. export default HeaderCell;