newIssueExperienceButton.tsx 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import {useCallback} from 'react';
  2. import styled from '@emotion/styled';
  3. import {Button} from 'sentry/components/button';
  4. import DropdownButton from 'sentry/components/dropdownButton';
  5. import {DropdownMenu} from 'sentry/components/dropdownMenu';
  6. import {IconLab} from 'sentry/icons';
  7. import {t} from 'sentry/locale';
  8. import {trackAnalytics} from 'sentry/utils/analytics';
  9. import {useFeedbackForm} from 'sentry/utils/useFeedbackForm';
  10. import {useLocation} from 'sentry/utils/useLocation';
  11. import useMutateUserOptions from 'sentry/utils/useMutateUserOptions';
  12. import {useNavigate} from 'sentry/utils/useNavigate';
  13. import useOrganization from 'sentry/utils/useOrganization';
  14. import {useHasStreamlinedUI} from 'sentry/views/issueDetails/utils';
  15. export function NewIssueExperienceButton() {
  16. const organization = useOrganization();
  17. const location = useLocation();
  18. const navigate = useNavigate();
  19. const hasStreamlinedUIFlag = organization.features.includes('issue-details-streamline');
  20. const hasStreamlinedUI = useHasStreamlinedUI();
  21. const openForm = useFeedbackForm();
  22. const {mutate} = useMutateUserOptions();
  23. const handleToggle = useCallback(() => {
  24. mutate({['prefersIssueDetailsStreamlinedUI']: !hasStreamlinedUI});
  25. trackAnalytics('issue_details.streamline_ui_toggle', {
  26. isEnabled: !hasStreamlinedUI,
  27. organization: organization,
  28. });
  29. navigate({
  30. ...location,
  31. query: {...location.query, streamline: hasStreamlinedUI ? '0' : '1'},
  32. });
  33. }, [mutate, organization, hasStreamlinedUI, location, navigate]);
  34. if (!hasStreamlinedUIFlag) {
  35. return null;
  36. }
  37. if (!openForm || !hasStreamlinedUI) {
  38. const label = hasStreamlinedUI
  39. ? t('Switch to the old issue experience')
  40. : t('Switch to the new issue experience');
  41. return (
  42. <StyledButton
  43. enabled={hasStreamlinedUI}
  44. size={hasStreamlinedUI ? 'xs' : 'sm'}
  45. icon={<IconLab isSolid={hasStreamlinedUI} />}
  46. title={label}
  47. aria-label={label}
  48. onClick={handleToggle}
  49. />
  50. );
  51. }
  52. return (
  53. <DropdownMenu
  54. trigger={triggerProps => (
  55. <StyledDropdownButton
  56. {...triggerProps}
  57. enabled={hasStreamlinedUI}
  58. size={hasStreamlinedUI ? 'xs' : 'sm'}
  59. aria-label={t('Switch issue experience')}
  60. >
  61. {/* Passing icon as child to avoid extra icon margin */}
  62. <IconLab isSolid={hasStreamlinedUI} />
  63. </StyledDropdownButton>
  64. )}
  65. items={[
  66. {
  67. key: 'switch-to-old-ui',
  68. label: t('Switch to the old issue experience'),
  69. onAction: handleToggle,
  70. },
  71. {
  72. key: 'give-feedback',
  73. label: t('Give feedback on new UI'),
  74. hidden: !openForm,
  75. onAction: () => {
  76. openForm({
  77. messagePlaceholder: t('How can we make this new UI work for you?'),
  78. });
  79. },
  80. },
  81. ]}
  82. position="bottom-end"
  83. />
  84. );
  85. }
  86. const StyledDropdownButton = styled(DropdownButton)<{enabled: boolean}>`
  87. color: ${p => (p.enabled ? p.theme.button.primary.background : 'inherit')};
  88. :hover {
  89. color: ${p => (p.enabled ? p.theme.button.primary.background : 'inherit')};
  90. }
  91. `;
  92. const StyledButton = styled(Button)<{enabled: boolean}>`
  93. color: ${p => (p.enabled ? p.theme.button.primary.background : 'inherit')};
  94. :hover {
  95. color: ${p => (p.enabled ? p.theme.button.primary.background : 'inherit')};
  96. }
  97. `;