pageUpsellOverlay.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import {Button} from 'sentry/components/button';
  4. import ButtonBar from 'sentry/components/buttonBar';
  5. import PageOverlay from 'sentry/components/pageOverlay';
  6. import {t, tct} from 'sentry/locale';
  7. import type {Organization} from 'sentry/types/organization';
  8. import {openUpsellModal} from 'getsentry/actionCreators/modal';
  9. import UpsellProvider from 'getsentry/components/upsellProvider';
  10. import withSubscription from 'getsentry/components/withSubscription';
  11. import type {Subscription} from 'getsentry/types';
  12. import {displayPlanName} from 'getsentry/utils/billing';
  13. import PlanFeature from './planFeature';
  14. type Props = Omit<React.ComponentProps<typeof PageOverlay>, 'text'> & {
  15. description: React.ReactNode;
  16. features: string[];
  17. name: string;
  18. organization: Organization;
  19. requiredPlan: React.ReactNode;
  20. source: string;
  21. subscription: Subscription;
  22. customSecondaryCTA?: React.ReactNode;
  23. defaultUpsellSelection?: string;
  24. };
  25. /**
  26. * Wrapper component that will render the wrapped content with a animated upsell
  27. * overlay.
  28. *
  29. * This uses the PageOverlay component and makes it more "upselly".
  30. */
  31. function PageUpsellOverlay({
  32. organization,
  33. subscription,
  34. features,
  35. name,
  36. description,
  37. source,
  38. requiredPlan,
  39. customSecondaryCTA,
  40. defaultUpsellSelection,
  41. ...props
  42. }: Props) {
  43. const requiredPlanContents =
  44. requiredPlan ??
  45. tct("You'll need the [plan] or up to access [name]", {
  46. name,
  47. plan: (
  48. <PlanFeature {...{organization, features}}>
  49. {({plan}) => (
  50. <strong data-test-id="upsell-planid">
  51. {t('%s Plan', displayPlanName(plan))}
  52. </strong>
  53. )}
  54. </PlanFeature>
  55. ),
  56. });
  57. return (
  58. <PageOverlay
  59. text={({Header, Body}) => (
  60. <Fragment>
  61. <Header>{name}</Header>
  62. <Body>{description}</Body>
  63. <Body css={theme => `font-size: ${theme.fontSizeMedium}`}>
  64. {requiredPlanContents}
  65. </Body>
  66. <Body>
  67. <StyledButtonBar gap={1}>
  68. {subscription?.canSelfServe && (
  69. <UpsellProvider
  70. source={source}
  71. organization={organization}
  72. triggerMemberRequests
  73. >
  74. {({defaultButtonText, onClick}) => (
  75. <Button priority="primary" size="sm" onClick={onClick}>
  76. {defaultButtonText}
  77. </Button>
  78. )}
  79. </UpsellProvider>
  80. )}
  81. {customSecondaryCTA ?? (
  82. <Button
  83. onClick={() =>
  84. openUpsellModal({
  85. organization,
  86. source,
  87. defaultSelection: defaultUpsellSelection,
  88. })
  89. }
  90. size="sm"
  91. >
  92. {t('Learn More')}
  93. </Button>
  94. )}
  95. </StyledButtonBar>
  96. </Body>
  97. </Fragment>
  98. )}
  99. {...props}
  100. />
  101. );
  102. }
  103. const StyledButtonBar = styled(ButtonBar)`
  104. width: fit-content;
  105. `;
  106. export default withSubscription(PageUpsellOverlay, {noLoader: true});