stepHeader.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import {css} from '@emotion/react';
  2. import styled from '@emotion/styled';
  3. import kebabCase from 'lodash/kebabCase';
  4. import {IconCheckmark, IconChevron} from 'sentry/icons';
  5. import {t} from 'sentry/locale';
  6. import {space} from 'sentry/styles/space';
  7. import type {Organization} from 'sentry/types/organization';
  8. import type {PlanTier} from 'getsentry/types';
  9. import LegacyPlanToggle from 'getsentry/views/amCheckout/legacyPlanToggle';
  10. import {getToggleTier} from 'getsentry/views/amCheckout/utils';
  11. type Props = {
  12. isActive: boolean;
  13. isCompleted: boolean;
  14. onEdit: (stepNumber: number) => void;
  15. stepNumber: number;
  16. title: string;
  17. /**
  18. * Can skip directly to this step
  19. */
  20. canSkip?: boolean;
  21. checkoutTier?: PlanTier;
  22. onToggleLegacy?: (tier: string) => void;
  23. organization?: Organization;
  24. trailingItems?: React.ReactNode;
  25. };
  26. function StepHeader({
  27. isActive,
  28. isCompleted,
  29. stepNumber,
  30. onEdit,
  31. title,
  32. trailingItems,
  33. canSkip,
  34. onToggleLegacy,
  35. checkoutTier,
  36. organization,
  37. }: Props) {
  38. const canEdit = !isActive && (isCompleted || canSkip);
  39. const toggleTier = getToggleTier(checkoutTier);
  40. return (
  41. <Header
  42. isActive={isActive}
  43. canEdit={canEdit}
  44. onClick={() => canEdit && onEdit(stepNumber)}
  45. data-test-id={`header-${kebabCase(title)}`}
  46. >
  47. <StepTitleWrapper>
  48. <StepTitle>
  49. {isCompleted ? (
  50. <IconCheckmark isCircled color="green300" />
  51. ) : (
  52. <div>{`${stepNumber}.`}</div>
  53. )}
  54. {title}
  55. </StepTitle>
  56. {trailingItems && <div>{trailingItems}</div>}
  57. </StepTitleWrapper>
  58. <div>
  59. {isActive && toggleTier ? (
  60. typeof onToggleLegacy === 'function' && (
  61. <LegacyPlanToggle
  62. organization={organization}
  63. checkoutTier={checkoutTier}
  64. onClick={() => onToggleLegacy(toggleTier)}
  65. data-test-id="legacy-tier-toggle"
  66. />
  67. )
  68. ) : (
  69. <EditStep>
  70. {isCompleted && <a onClick={() => onEdit(stepNumber)}>{t('Edit')}</a>}
  71. {canEdit && <Chevron direction="down" aria-label={t('Expand section')} />}
  72. </EditStep>
  73. )}
  74. </div>
  75. </Header>
  76. );
  77. }
  78. export default StepHeader;
  79. const Header = styled('div')<{canEdit?: boolean; isActive?: boolean}>`
  80. display: grid;
  81. grid-template-columns: auto max-content;
  82. gap: ${space(1)};
  83. align-items: center;
  84. padding: ${space(3)} ${space(2)};
  85. ${p =>
  86. p.isActive &&
  87. css`
  88. border-bottom: 1px solid ${p.theme.border};
  89. `};
  90. ${p =>
  91. p.canEdit &&
  92. css`
  93. cursor: pointer;
  94. `};
  95. `;
  96. const StepTitle = styled('div')`
  97. display: grid;
  98. grid-auto-flow: column;
  99. justify-content: start;
  100. gap: ${space(1)};
  101. align-items: center;
  102. font-size: ${p => p.theme.fontSizeLarge};
  103. color: ${p => p.theme.subText};
  104. `;
  105. const EditStep = styled('div')`
  106. display: grid;
  107. grid-auto-flow: column;
  108. gap: ${space(1)};
  109. align-items: center;
  110. `;
  111. const Chevron = styled(IconChevron)`
  112. color: ${p => p.theme.border};
  113. justify-self: end;
  114. `;
  115. const StepTitleWrapper = styled('div')`
  116. display: flex;
  117. justify-content: space-between;
  118. `;