import { css } from '@emotion/css'; import React, { useEffect, useState, useCallback, useMemo } from 'react'; import { GrafanaTheme2 } from '@grafana/data'; import { Icon, IconButton, IconName, useStyles2, useTheme2 } from '@grafana/ui'; import { appEvents } from 'app/core/core'; import { PageBannerDisplayEvent, PageBannerEventPayload, PageBannerSeverity } from './types'; export function PageBanner(): React.ReactElement | null { const [banner, setBanner] = useState(); const severityStyling = useStylingBySeverity(banner?.severity); const styles = useStyles2((theme) => getStyles(theme, severityStyling)); useEffect(() => { const sub = appEvents.subscribe(PageBannerDisplayEvent, (event) => { setBanner(event.payload); }); return sub.unsubscribe; }, [setBanner]); const onClose = useCallback(() => { setBanner(undefined); if (banner?.onClose) { banner.onClose(); } }, [banner]); if (!banner) { return null; } const BannerBody = banner.body; return (
{banner?.onClose && (
)}
); } type SeverityStyling = { text: string; background: string; icon: IconName; }; function useStylingBySeverity(severity: PageBannerSeverity | undefined): SeverityStyling { const theme = useTheme2(); return useMemo(() => { switch (severity) { case PageBannerSeverity.error: return { icon: 'exclamation-triangle', background: theme.colors.error.main, text: theme.colors.error.contrastText, }; case PageBannerSeverity.warning: return { icon: 'exclamation-triangle', background: theme.colors.warning.main, text: theme.colors.warning.contrastText, }; case PageBannerSeverity.info: default: return { icon: 'info-circle', background: theme.colors.info.main, text: theme.colors.info.contrastText, }; } }, [theme, severity]); } function getStyles(theme: GrafanaTheme2, severityStyling: SeverityStyling) { return { banner: css` flex-grow: 0; flex-shrink: 0; display: flex; align-items: center; background-color: ${severityStyling.background}; border-radius: 2px; height: 52px; `, icon: css` padding: ${theme.spacing(0, 2)}; color: ${severityStyling.text}; display: flex; `, content: css` flex-grow: 1; display: flex; align-items: center; color: ${severityStyling.text}; `, close: css` color: ${severityStyling.text}; `, }; } // Uncomment to test this banner // setTimeout(() => { // appEvents.publish( // new PageBannerDisplayEvent({ // onClose: () => {}, // body: function test() { // return ( //
// This is a warning that you will be suspended{' '} // //
// ); // }, // }) // ); // }, 3000);