pageBanner.tsx 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import type {CSSProperties, ReactNode} from 'react';
  2. import styled from '@emotion/styled';
  3. import {Button} from 'sentry/components/button';
  4. import Panel from 'sentry/components/panels/panel';
  5. import {IconClose} from 'sentry/icons';
  6. import {t} from 'sentry/locale';
  7. import {space} from 'sentry/styles/space';
  8. interface Props {
  9. description: ReactNode;
  10. heading: ReactNode;
  11. icon: ReactNode;
  12. image: any;
  13. title: ReactNode;
  14. button?: ReactNode;
  15. onDismiss?: () => void;
  16. style?: CSSProperties;
  17. }
  18. export default function PageBanner({
  19. button,
  20. description,
  21. heading,
  22. icon,
  23. image,
  24. onDismiss,
  25. title,
  26. style,
  27. }: Props) {
  28. return (
  29. <Wrapper style={style}>
  30. {onDismiss && (
  31. <CloseButton
  32. onClick={onDismiss}
  33. icon={<IconClose size="xs" />}
  34. aria-label={t('Hide')}
  35. size="xs"
  36. />
  37. )}
  38. <Background image={image} />
  39. <Stack>
  40. <TypeText>
  41. {icon}
  42. {title}
  43. </TypeText>
  44. <TextContainer>
  45. <h4>{heading}</h4>
  46. <SubText>{description}</SubText>
  47. </TextContainer>
  48. </Stack>
  49. {button}
  50. </Wrapper>
  51. );
  52. }
  53. const Wrapper = styled(Panel)`
  54. display: flex;
  55. padding: ${space(2)};
  56. min-height: 100px;
  57. justify-content: space-between;
  58. align-items: center;
  59. margin: 0;
  60. `;
  61. const CloseButton = styled(Button)`
  62. justify-content: center;
  63. position: absolute;
  64. top: -${space(1)};
  65. right: -${space(1)};
  66. border-radius: 50%;
  67. height: ${p => p.theme.iconSizes.lg};
  68. width: ${p => p.theme.iconSizes.lg};
  69. z-index: 1;
  70. `;
  71. const Background = styled('div')<{image: any}>`
  72. display: flex;
  73. justify-self: flex-end;
  74. position: absolute;
  75. top: 0px;
  76. right: 0px;
  77. height: 100%;
  78. width: 50%;
  79. /* Prevent the image from going behind the text, keep text readable */
  80. max-width: 500px;
  81. background-image: url(${p => p.image});
  82. background-repeat: no-repeat;
  83. background-size: cover;
  84. `;
  85. const Stack = styled('div')`
  86. display: flex;
  87. flex-direction: column;
  88. justify-content: space-between;
  89. max-width: 50%;
  90. gap: ${space(1)};
  91. `;
  92. const TextContainer = styled('div')`
  93. display: flex;
  94. flex-direction: column;
  95. justify-content: space-between;
  96. z-index: 1;
  97. h4 {
  98. margin-bottom: ${space(0.5)};
  99. }
  100. `;
  101. const SubText = styled('div')`
  102. color: ${p => p.theme.subText};
  103. font-size: ${p => p.theme.fontSizeMedium};
  104. line-height: ${p => p.theme.fontSizeMedium};
  105. `;
  106. const TypeText = styled(SubText)`
  107. align-items: center;
  108. display: flex;
  109. font-weight: 500;
  110. gap: ${space(0.5)};
  111. text-transform: uppercase;
  112. `;