import {useState} from 'react'; import {css} from '@emotion/react'; import styled from '@emotion/styled'; import Button from 'sentry/components/button'; import ButtonBar from 'sentry/components/buttonBar'; import {IconClose} from 'sentry/icons'; import {t} from 'sentry/locale'; import space from 'sentry/styles/space'; const makeKey = (prefix: string) => `${prefix}-banner-dismissed`; function dismissBanner(bannerKey: string) { localStorage.setItem(makeKey(bannerKey), 'true'); } function useDismissable(bannerKey: string) { const key = makeKey(bannerKey); const [value, setValue] = useState(localStorage.getItem(key)); const dismiss = () => { setValue('true'); dismissBanner(bannerKey); }; return [value === 'true', dismiss] as const; } type BannerWrapperProps = { backgroundComponent?: React.ReactNode; backgroundImg?: string; }; type Props = BannerWrapperProps & { className?: string; dismissKey?: string; isDismissable?: boolean; subtitle?: string; title?: string; }; type BannerType = React.FC & { /** * Helper function to hide banners outside of their usage */ dismiss: typeof dismissBanner; }; const Banner: BannerType = ({ title, subtitle, isDismissable = true, dismissKey = 'generic-banner', className, backgroundImg, backgroundComponent, children, }) => { const [dismissed, dismiss] = useDismissable(dismissKey); if (dismissed) { return null; } return ( {backgroundComponent} {isDismissable ? : null} {title} {subtitle} {children} ); }; Banner.dismiss = dismissBanner; const BannerWrapper = styled('div')` ${p => p.backgroundImg ? css` background: url(${p.backgroundImg}); background-repeat: no-repeat; background-size: cover; background-position: center center; ` : css` background-color: ${p.theme.gray500}; `} display: flex; overflow: hidden; align-items: center; justify-content: center; position: relative; margin-bottom: ${space(2)}; box-shadow: ${p => p.theme.dropShadowLight}; border-radius: ${p => p.theme.borderRadius}; height: 180px; color: ${p => p.theme.white}; @media (min-width: ${p => p.theme.breakpoints.small}) { height: 220px; } `; const BannerContent = styled('div')` position: absolute; display: grid; justify-items: center; grid-template-rows: repeat(3, max-content); text-align: center; padding: ${space(4)}; `; const BannerTitle = styled('h1')` margin: 0; @media (min-width: ${p => p.theme.breakpoints.small}) { font-size: 40px; } `; const BannerSubtitle = styled('div')` margin: 0; @media (min-width: ${p => p.theme.breakpoints.small}) { font-size: ${p => p.theme.fontSizeExtraLarge}; } `; const StyledButtonBar = styled(ButtonBar)` margin-top: ${space(2)}; width: fit-content; `; const CloseButton = styled(Button)` position: absolute; display: block; top: ${space(2)}; right: ${space(2)}; color: ${p => p.theme.white}; cursor: pointer; z-index: 1; `; CloseButton.defaultProps = { icon: , ['aria-label']: t('Close'), priority: 'link', borderless: true, size: 'xs', }; export default Banner;