UNPKG

@spaced-out/ui-design-system

Version:
150 lines (135 loc) 3.8 kB
// @flow strict import * as React from 'react'; import {TEXT_COLORS} from '../../types/typography'; import {classify} from '../../utils/classify'; import type {IconType} from '../Icon'; import {Icon} from '../Icon'; import {SubTitleSmall} from '../Text'; import css from './Notification.module.css'; export const NOTIFICATION_SEMANTIC = Object.freeze({ success: 'success', information: 'information', danger: 'danger', }); type ClassNames = $ReadOnly<{wrapper?: string, text?: string}>; export type NotificationSemanticType = $Values<typeof NOTIFICATION_SEMANTIC>; type BaseNotificationProps = { classNames?: ClassNames, semantic: NotificationSemanticType, iconLeftName?: string, iconLeftType?: IconType, dismissable?: boolean, children?: string, onCloseClick?: ?(SyntheticEvent<HTMLElement>) => mixed, }; type NotificationBaseProps = { ...BaseNotificationProps, classNames?: ClassNames, ... | { dismissable: true, onCloseClick?: ?(SyntheticEvent<HTMLElement>) => mixed, selfDismiss?: boolean, } | {dismissable?: false}, }; export type NotificationProps = { ...NotificationBaseProps, semantic: NotificationSemanticType, }; // Base Notification will not have any state. const BaseNotification: React$AbstractComponent< BaseNotificationProps, HTMLDivElement, > = React.forwardRef<BaseNotificationProps, HTMLDivElement>( (props: BaseNotificationProps, ref): React.Node => { const { classNames, semantic = NOTIFICATION_SEMANTIC.success, iconLeftName, iconLeftType = 'regular', dismissable, children, onCloseClick, } = props; return ( <div className={classify( css.baseContainer, { [css.success]: semantic === NOTIFICATION_SEMANTIC.success, [css.information]: semantic === NOTIFICATION_SEMANTIC.information, [css.danger]: semantic === NOTIFICATION_SEMANTIC.danger, [css.dismissable]: dismissable, }, classNames?.wrapper, )} ref={ref} > {iconLeftName ? ( <Icon name={iconLeftName} color={TEXT_COLORS.inversePrimary} size="small" type={iconLeftType} /> ) : null} <SubTitleSmall className={classify(classNames?.text)} color={TEXT_COLORS.inversePrimary} > {children} </SubTitleSmall> {dismissable && ( <Icon color={TEXT_COLORS.inversePrimary} name="close" size="small" type="regular" onClick={onCloseClick} className={css.closeIcon} /> )} </div> ); }, ); export const Notification: React$AbstractComponent< NotificationProps, HTMLDivElement, > = React.forwardRef<NotificationProps, HTMLDivElement>( (props: NotificationProps, ref): React.Node => { const { classNames, semantic = NOTIFICATION_SEMANTIC.success, iconLeftName, iconLeftType, dismissable, children, selfDismiss = false, onCloseClick, } = props; const [dismissed, setDismissed] = React.useState(false); const closeClickHandler = (e) => { onCloseClick && onCloseClick(e); selfDismiss && setDismissed(true); }; return ( <> {!dismissed && ( <BaseNotification classNames={classNames} iconLeftName={iconLeftName} iconLeftType={iconLeftType} semantic={semantic} dismissable={dismissable} onCloseClick={closeClickHandler} ref={ref} > {children} </BaseNotification> )} </> ); }, );