UNPKG

nishant-design-system

Version:
203 lines (187 loc) 5.18 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 {ClickableIcon, Icon} from '../Icon'; import {Link} from '../Link'; import {SubTitleExtraSmall} from '../Text'; import {Truncate} from '../Truncate'; import css from './InContextAlert.module.css'; export const ALERT_SEMANTIC = Object.freeze({ neutral: 'neutral', success: 'success', information: 'information', warning: 'warning', danger: 'danger', }); type ClassNames = $ReadOnly<{ wrapper?: string, alertText?: string, actionContainer?: string, }>; export type AlertSemanticType = $Values<typeof ALERT_SEMANTIC>; type InContextAlertBaseProps = { classNames?: ClassNames, ... | { dismissable: true, onCloseClick?: ?(SyntheticEvent<HTMLElement>) => mixed, selfDismiss?: boolean, } | {dismissable?: false}, children?: string, actionText?: string, onAction?: ?(SyntheticEvent<HTMLElement>) => mixed, }; export type InContextAlertProps = { ...InContextAlertBaseProps, semantic?: AlertSemanticType, leftIconName?: string, leftIconType?: IconType, }; const AlertIcon = ({ semantic, leftIconName, leftIconType, }: { semantic: AlertSemanticType, leftIconName: string, leftIconType?: IconType, }) => { switch (semantic) { case ALERT_SEMANTIC.neutral: return ( <Icon color={TEXT_COLORS.neutral} name={leftIconName ? leftIconName : 'face-smile'} size="small" type={leftIconType} /> ); case ALERT_SEMANTIC.success: return ( <Icon name={leftIconName ? leftIconName : 'circle-check'} size="small" color={TEXT_COLORS.success} type={leftIconType} /> ); case ALERT_SEMANTIC.information: return ( <Icon name={leftIconName ? leftIconName : 'circle-info'} size="small" color={TEXT_COLORS.information} type={leftIconType} /> ); case ALERT_SEMANTIC.warning: return ( <Icon name={leftIconName ? leftIconName : 'circle-exclamation'} size="small" color={TEXT_COLORS.warning} type={leftIconType} /> ); case ALERT_SEMANTIC.danger: return ( <Icon name={leftIconName ? leftIconName : 'shield-exclamation'} size="small" color={TEXT_COLORS.danger} type={leftIconType} /> ); default: return ( <Icon color={TEXT_COLORS.neutral} name={leftIconName ? leftIconName : 'face-smile'} size="small" type={leftIconType} /> ); } }; export const InContextAlert: React$AbstractComponent< InContextAlertProps, HTMLDivElement, > = React.forwardRef<InContextAlertProps, HTMLDivElement>( (props: InContextAlertProps, ref): React.Node => { const { classNames, semantic = ALERT_SEMANTIC.neutral, dismissable, children, selfDismiss = false, leftIconName = '', onCloseClick, actionText = '', onAction, leftIconType, } = props; const [dismissed, setDismissed] = React.useState(false); const closeClickHandler = (e) => { onCloseClick && onCloseClick(e); selfDismiss && setDismissed(true); }; return ( <> {!dismissed && ( <div className={classify( css.alertContainer, { [css.neutral]: semantic === ALERT_SEMANTIC.neutral, [css.success]: semantic === ALERT_SEMANTIC.success, [css.information]: semantic === ALERT_SEMANTIC.information, [css.warning]: semantic === ALERT_SEMANTIC.warning, [css.danger]: semantic === ALERT_SEMANTIC.danger, }, classNames?.wrapper, )} ref={ref} > <AlertIcon semantic={semantic} leftIconName={leftIconName} leftIconType={leftIconType} /> {React.Children.count(children) > 0 && ( <SubTitleExtraSmall className={classify(classNames?.alertText)}> <Truncate line={2}>{children}</Truncate> </SubTitleExtraSmall> )} {!!(actionText || dismissable) && ( <div className={classify( css.actionContainer, classNames?.actionContainer, )} > {!!actionText && ( <Link onClick={onAction} color="primary"> {actionText} </Link> )} {!!dismissable && ( <ClickableIcon color={TEXT_COLORS.primary} name="close" size="small" type="regular" onClick={closeClickHandler} className={css.closeIcon} /> )} </div> )} </div> )} </> ); }, );