UNPKG

@spaced-out/ui-design-system

Version:
209 lines (194 loc) 5.47 kB
// @flow strict import * as React from 'react'; import type {AlertSemanticType} from '../../types/common'; import {ALERT_SEMANTIC} from '../../types/common'; 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'; type ClassNames = $ReadOnly<{ wrapper?: string, alertText?: string, actionContainer?: string, icon?: string, }>; 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, iconClassName, }: { semantic: AlertSemanticType, leftIconName: string, leftIconType?: IconType, iconClassName?: string, }) => { switch (semantic) { case ALERT_SEMANTIC.neutral: return ( <Icon color={TEXT_COLORS.neutral} name={leftIconName ? leftIconName : 'face-smile'} size="small" type={leftIconType} className={iconClassName} /> ); case ALERT_SEMANTIC.success: return ( <Icon name={leftIconName ? leftIconName : 'circle-check'} size="small" color={TEXT_COLORS.success} type={leftIconType} className={iconClassName} /> ); case ALERT_SEMANTIC.information: return ( <Icon name={leftIconName ? leftIconName : 'circle-info'} size="small" color={TEXT_COLORS.information} type={leftIconType} className={iconClassName} /> ); case ALERT_SEMANTIC.warning: return ( <Icon name={leftIconName ? leftIconName : 'circle-exclamation'} size="small" color={TEXT_COLORS.warning} type={leftIconType} className={iconClassName} /> ); case ALERT_SEMANTIC.danger: return ( <Icon name={leftIconName ? leftIconName : 'shield-exclamation'} size="small" color={TEXT_COLORS.danger} type={leftIconType} className={iconClassName} /> ); default: return ( <Icon color={TEXT_COLORS.neutral} name={leftIconName ? leftIconName : 'face-smile'} size="small" type={leftIconType} className={iconClassName} /> ); } }; 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} iconClassName={classNames?.icon} /> {React.Children.count(children) > 0 && ( <SubTitleExtraSmall className={classify(classNames?.alertText)}> <Truncate line={2} wordBreak="initial"> {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} ariaLabel="close" name="close" size="small" type="regular" onClick={closeClickHandler} className={css.closeIcon} /> )} </div> )} </div> )} </> ); }, );