@spaced-out/ui-design-system
Version:
Sense UI components library
150 lines (135 loc) • 3.8 kB
Flow
// @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>
)}
</>
);
},
);