sortableHeader.tsx 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import styled from '@emotion/styled';
  2. import Link from 'sentry/components/links/link';
  3. import QuestionTooltip from 'sentry/components/questionTooltip';
  4. import {IconArrow} from 'sentry/icons';
  5. import space from 'sentry/styles/space';
  6. import type {Sort} from 'sentry/utils/discover/fields';
  7. import {useLocation} from 'sentry/utils/useLocation';
  8. import type {ReplayListLocationQuery} from 'sentry/views/replays/types';
  9. type NotSortable = {
  10. label: string;
  11. tooltip?: string;
  12. };
  13. type Sortable = {
  14. fieldName: string;
  15. label: string;
  16. sort: undefined | Sort;
  17. tooltip?: string;
  18. };
  19. type Props = NotSortable | Sortable;
  20. function SortableHeader(props: Props) {
  21. const location = useLocation<ReplayListLocationQuery>();
  22. if (!('sort' in props) || !props.sort) {
  23. const {label, tooltip} = props;
  24. return (
  25. <Header>
  26. {label}
  27. {tooltip ? (
  28. <StyledQuestionTooltip size="xs" position="top" title={tooltip} />
  29. ) : null}
  30. </Header>
  31. );
  32. }
  33. const {fieldName, label, sort, tooltip} = props;
  34. const arrowDirection = sort?.kind === 'asc' ? 'up' : 'down';
  35. const sortArrow = <IconArrow color="gray300" size="xs" direction={arrowDirection} />;
  36. return (
  37. <Header>
  38. <SortLink
  39. role="columnheader"
  40. aria-sort={
  41. sort?.field.endsWith(fieldName)
  42. ? sort?.kind === 'asc'
  43. ? 'ascending'
  44. : 'descending'
  45. : 'none'
  46. }
  47. to={{
  48. pathname: location.pathname,
  49. query: {
  50. ...location.query,
  51. sort: sort?.field.endsWith(fieldName)
  52. ? sort?.kind === 'desc'
  53. ? fieldName
  54. : '-' + fieldName
  55. : '-' + fieldName,
  56. },
  57. }}
  58. >
  59. {label} {sort?.field === fieldName && sortArrow}
  60. </SortLink>
  61. {tooltip ? (
  62. <StyledQuestionTooltip size="xs" position="top" title={tooltip} />
  63. ) : null}
  64. </Header>
  65. );
  66. }
  67. const Header = styled('div')`
  68. display: grid;
  69. grid-template-columns: repeat(2, max-content);
  70. align-items: center;
  71. `;
  72. const SortLink = styled(Link)`
  73. color: inherit;
  74. :hover {
  75. color: inherit;
  76. }
  77. svg {
  78. vertical-align: top;
  79. }
  80. `;
  81. const StyledQuestionTooltip = styled(QuestionTooltip)`
  82. margin-left: ${space(0.5)};
  83. `;
  84. export default SortableHeader;