focusTabs.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import {Fragment, ReactNode} from 'react';
  2. import queryString from 'query-string';
  3. import FeatureBadge from 'sentry/components/featureBadge';
  4. import ExternalLink from 'sentry/components/links/externalLink';
  5. import ListLink from 'sentry/components/links/listLink';
  6. import ScrollableTabs from 'sentry/components/replays/scrollableTabs';
  7. import {Tooltip} from 'sentry/components/tooltip';
  8. import {t} from 'sentry/locale';
  9. import type {Organization} from 'sentry/types';
  10. import {trackAnalytics} from 'sentry/utils/analytics';
  11. import useActiveReplayTab, {TabKey} from 'sentry/utils/replays/hooks/useActiveReplayTab';
  12. import {useLocation} from 'sentry/utils/useLocation';
  13. import useOrganization from 'sentry/utils/useOrganization';
  14. function getReplayTabs(organization: Organization): Record<TabKey, ReactNode> {
  15. // The new Accessibility tab:
  16. const hasA11yTab = organization.features.includes('session-replay-a11y-tab');
  17. // The new trace table inside Breadcrumb items:
  18. const hasTraceTable = organization.features.includes('session-replay-trace-table');
  19. return {
  20. [TabKey.BREADCRUMBS]: t('Breadcrumbs'),
  21. [TabKey.CONSOLE]: t('Console'),
  22. [TabKey.NETWORK]: t('Network'),
  23. [TabKey.ERRORS]: t('Errors'),
  24. [TabKey.TRACE]: hasTraceTable ? null : t('Trace'),
  25. [TabKey.PERF]: null,
  26. [TabKey.A11Y]: hasA11yTab ? (
  27. <Fragment>
  28. <Tooltip
  29. isHoverable
  30. title={
  31. <ExternalLink href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/What_is_accessibility">
  32. {t('What is accessibility?')}
  33. </ExternalLink>
  34. }
  35. >
  36. {t('a11y')}
  37. </Tooltip>
  38. <FeatureBadge type="alpha" />
  39. </Fragment>
  40. ) : null,
  41. [TabKey.MEMORY]: t('Memory'),
  42. [TabKey.TAGS]: t('Tags'),
  43. };
  44. }
  45. type Props = {
  46. className?: string;
  47. };
  48. function FocusTabs({className}: Props) {
  49. const organization = useOrganization();
  50. const {pathname, query} = useLocation();
  51. const {getActiveTab, setActiveTab} = useActiveReplayTab();
  52. const activeTab = getActiveTab();
  53. return (
  54. <ScrollableTabs className={className} underlined>
  55. {Object.entries(getReplayTabs(organization)).map(([tab, label]) =>
  56. label ? (
  57. <ListLink
  58. data-test-id={`replay-details-${tab}-btn`}
  59. key={tab}
  60. isActive={() => tab === activeTab}
  61. to={`${pathname}?${queryString.stringify({...query, t_main: tab})}`}
  62. onClick={e => {
  63. e.preventDefault();
  64. setActiveTab(tab);
  65. trackAnalytics('replay.details-tab-changed', {
  66. tab,
  67. organization,
  68. });
  69. }}
  70. >
  71. {label}
  72. </ListLink>
  73. ) : null
  74. )}
  75. </ScrollableTabs>
  76. );
  77. }
  78. export default FocusTabs;