# All files / src/components message.tsx

84.61% Statements 11/13
88.23% Branches 15/17
100% Functions 1/1
84.61% Lines 11/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133

    10x

    10x

    13x
    13x

    13x
    12x

    12x

    12x
    5x

    7x

    13x

     import {
      type FC,
      type ReactNode,
      type HTMLAttributes,
      type MouseEvent,
    } from 'react';
    import cn from 'classnames';

    import InformationIcon from '../svg/information.svg';
    import WarningTriangleIcon from '../svg/warning-triangle.svg';
    import ErrorIcon from '../svg/error.svg';
    import SuccessIcon from '../svg/success.svg';
    import CloseIcon from '../svg/times.svg';

    import '../styles/components/message.scss';

    const iconSize = '1.125em';

    type Props = {
      /**
       * The message level: 'warning', 'failure', 'success', 'info' (default)
       */
      level?: 'warning' | 'failure' | 'success' | 'info';
      /**
       * The title of the message
       */
      heading?: ReactNode;
      /**
       * The content to appear underneath of the main message
       */
      subtitle?: ReactNode;
      /**
       * Whether the message can be closed or not
       */
      onDismiss?: (event: MouseEvent) => void;
      /**
       * To hide the default message icon
       */
      noIcon?: boolean;
      /**
       * To hide the default box shadow
       */
      noShadow?: boolean;
    };

    const Message: FC<Props & HTMLAttributes<HTMLDivElement>> = ({
      children,
      level = 'info',
      heading,
      subtitle,
      onDismiss,
      noIcon,
      noShadow,
      className,
      ...props
    }) => {
      let maybeIcon = null;
      const iconAlign = heading
        ? 'message--icon-align-center'
        : 'message--icon-align-top';

      if (!noIcon) {
        maybeIcon = (
          <InformationIcon
            width={iconSize}
            height={iconSize}
            className={iconAlign}
          />
        );
        Iif (level === 'warning') {
          maybeIcon = (
            <WarningTriangleIcon
              width={iconSize}
              height={iconSize}
              className={iconAlign}
            />
          );
        } else if (level === 'failure') {
          maybeIcon = (
            <ErrorIcon width={iconSize} height={iconSize} className={iconAlign} />
          );
        } else Iif (level === 'success') {
          maybeIcon = (
            <SuccessIcon width={iconSize} height={iconSize} className={iconAlign} />
          );
        }
      }

      return (
        <div
          className={cn(className, 'message', `message--${level}`, {
            'message--no-shadow': noShadow,
          })}
          role="status"
          {...props}
        >
          <div className="message__side-border" />

          {maybeIcon}

          {heading ? (
            <>
              <div
                className={cn('message__title', {
                  'message__title--no-icon': noIcon,
                })}
              >
                {heading}
              </div>
              <div className="message__text">{children}</div>
            </>
          ) : (
            <div className="message__title">{children}</div>
          )}

          {onDismiss && (
            <button
              type="button"
              aria-label="dismiss"
              className="message__dismiss"
              onClick={onDismiss}
            >
              <CloseIcon width="10" height="10" />
            </button>
          )}

          {subtitle && <div className="message__subtitle">{subtitle}</div>}
        </div>
      );
    };

    export default Message;