All files / src/components/common/Modal/ModalFactory/atoms ModalTitle.tsx

100% Statements 12/12
90.9% Branches 10/11
100% Functions 5/5
100% Lines 11/11

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                                                      21x                       85x 85x   85x                                                                                         21x                             21x 170x           85x             21x 361x 85x                  
import { CloseIcon } from "@assets/icons";
import { StyledIconButton } from "@common/IconButton";
import { Text, TruncateText } from "@common/Text";
import { FontWeight, ITextProps } from "@common/Text/Text";
import FadeUpWrapper from "@components/animation/FadeUpWrapper";
import { Divider, Stack, StackProps, styled } from "@mui/material";
import { palette } from "@palette";
import { ReactElement } from "react";
 
type TextStyles = {
  title?: ITextProps;
  description?: ITextProps;
};
 
type TitleProps = {
  Icon?: JSX.Element;
  title?: string;
  onClose?: () => void;
  description?: string | ReactElement;
  containerProps?: StackProps;
  textStyles?: TextStyles;
  padding?: string;
  closeButtonSize?: number;
  animationDelay?: number;
  showDivider?: boolean;
};
 
export const ModalTitle = ({
  Icon,
  title,
  onClose,
  description,
  containerProps,
  textStyles,
  padding,
  closeButtonSize = 24,
  animationDelay = 20,
  showDivider = false,
}: TitleProps) => {
  const titleStyle = getStyle("title", textStyles?.title);
  const descriptionStyle = getStyle("description", textStyles?.description);
 
  return (
    <FadeUpWrapper delay={animationDelay}>
      <ModalTitleContainer
        {...containerProps}
        sx={{ ...containerProps?.sx, padding }}
      >
        <Stack direction="row" spacing={1}>
          {Icon && Icon}
          <TruncateText
            variant="h3"
            {...titleStyle}
            minHeight={titleStyle.lineHeight}
            sx={{ userSelect: "none" }}
            flexGrow={1}
            lineClamp={2}
          >
            {title}
          </TruncateText>
          {onClose && (
            <CloseButton
              data-testid="close-button"
              onClick={onClose}
              closeButtonSize={closeButtonSize}
            >
              <CloseIcon
                width={closeButtonSize - 2}
                height={closeButtonSize - 2}
                stroke={palette?.black?.[100]}
              />
            </CloseButton>
          )}
        </Stack>
        {description && <Text {...descriptionStyle}>{description}</Text>}
      </ModalTitleContainer>
      {showDivider && (
        <Divider
          sx={{
            marginBottom: "16px",
          }}
        />
      )}
    </FadeUpWrapper>
  );
};
 
const defaultTextProps = {
  title: {
    fontSize: "20px",
    lineHeight: "27px",
    fontWeight: "book" as FontWeight,
    color: palette?.black?.[100],
  },
  description: {
    fontSize: "14px",
    lineHeight: "16.8px",
    fontWeight: "book" as FontWeight,
    color: palette?.gray?.[300],
  },
};
 
const getStyle = (key: "title" | "description", customStyles?: ITextProps) => {
  return {
    ...defaultTextProps[key],
    ...customStyles,
  };
};
 
const ModalTitleContainer = styled(Stack)(() => ({
  flexDirection: "column",
  alignItems: "stretch",
  gap: "8px",
  background: "inherit",
}));
 
const CloseButton = styled(StyledIconButton, {
  shouldForwardProp: (prop) => prop !== "closeButtonSize",
})<{ closeButtonSize: number }>(({ closeButtonSize }) => ({
  maxWidth: `${closeButtonSize}px`,
  maxHeight: `${closeButtonSize}px`,
  borderRadius: "4px",
  padding: "0 !important",
  display: "flex",
  alignItems: "center",
  justifyContent: "center",
}));