All files / NotificationDialog NotificationDialog.tsx

100% Statements 52/52
100% Branches 42/42
100% Functions 6/6
100% Lines 43/43

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 1242x 2x 2x 2x 2x   2x 2x   2x 34x 34x 34x 34x 34x 34x 34x 34x 34x 34x 34x 34x   34x 34x 34x   34x 13x     34x 34x   34x   32x   32x             32x                                               2x   2x                   22x 22x   22x     2x         2x                   2x 22x   18x           2x           2x            
import * as React from "react";
import styled, { css } from "styled-components";
import Text from "../Text/Text";
import { useTheme } from "../ThemeProvider/ThemeProvider";
import { useDebounce } from "../../helpers/CustomHooks";
import { NotificationDialogProps, NotificationDialogStyleProps } from "./NotificationDialog.types";
import { getColorPalette } from "../../helpers/helpers";
import colorTokens from "../../tokens/colors.json";
 
const NotificationDialog: React.FunctionComponent<NotificationDialogProps> = ({
  open = false,
  title,
  width = "auto",
  children,
  leadingIcon,
  trailingIcon,
  variant = "contained",
  color = colorTokens.default.primary.main,
  "data-testid": dataTestId,
  className,
  style,
  ...props
}) => {
  const [isOpen, setIsOpen] = React.useState(open);
  const debouncedOpen = useDebounce(open, 200);
  const [notifDialogRef, setNotifDialogRef] = React.useState<HTMLDivElement | null>(null);
 
  React.useEffect(() => {
    setIsOpen(open);
  }, [open]);
 
  const theme = useTheme().theme;
  const colorPalette = getColorPalette(theme, color);
 
  if(!open && !debouncedOpen) return null;
 
  const _title = title && typeof title === "string" ? (<Text disableColor variant="span">{title}</Text>) : title;
  const _children =
    typeof children === "string" ? (
      <Text disableColor variant="paragraph">{children}</Text>
    ) : (
      children
    );
 
 
  return (
    <StyledNotificationDialog
      ref={setNotifDialogRef}
      $open={isOpen}
      $variant={variant}
      $height={`${notifDialogRef?.offsetHeight}px`}
      $width={width}
      $colorPalette={colorPalette}
      $color={color}
      data-testid={dataTestId}
      className={className}
      style={style}
      {...props}
    >
      {leadingIcon && <StyledIcon>{leadingIcon}</StyledIcon>}
      <StyledNotificationContent>
        {_title}
        {_children}
      </StyledNotificationContent>
 
      {trailingIcon && <StyledIcon>{trailingIcon}</StyledIcon>}
    </StyledNotificationDialog>
  );
};
export default NotificationDialog;
 
const StyledNotificationDialog = styled.div<NotificationDialogStyleProps>`
  display: flex;
  position: fixed;
  justify-content: space-between;
  align-items: center;
  flex-direction: row;
  gap: 0.5rem;
  left: 2rem;
  border-radius: 0.5rem;
  padding: 1rem;
  width: ${(props) => props.$width};
  bottom: ${(props) => (props.$open ? "2rem" : `-${props.$height}`)};
  transition: bottom 0.2s ease-in-out;
  ${props => variantHandler(props.$variant, props.$colorPalette, props.$color)};
 
`;
const StyledNotificationContent = styled.div`
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
`;
const StyledIcon = styled.span`
  width: 1.5rem;
  height: 1.5rem;
  flex: 1 0 auto;
  & svg {
    width: 100%;
    height: 100%;
  }
`;
 
const variantHandler = (variant: NotificationDialogProps["variant"], colorPalette: any, color: string) => {
  switch (variant) {
    case "contained":
      return css`
        background-color: ${colorPalette[color].accentScale[9]};
        border: 2px solid ${colorPalette[color].accentScale[9]};
        color: ${colorPalette[color].accentContrast};
      `;
    case "outlined":
      return css`
        background-color: transparent;
        border: 2px solid ${colorPalette[color].accentScale[9]};
        color: ${colorPalette[color].accentScale[10]};
      `;
    case "soft":
      return css`
        background-color: ${colorPalette[color].accentScale[1]};
        border: 2px solid ${colorPalette[color].accentScale[1]};
        color: ${colorPalette[color].accentScale[10]};
      `;
  }
}