Home > Net >  ReactJS - Modal is enabled inside component
ReactJS - Modal is enabled inside component

Time:04-09

I have a modal that I use on login(/) and home(/posts) pages. In my home page it works, but in the home page it doesn't work. It is displayed inside component that I call it. The issue GIF: Issue reproduction

Any idea how to solve this, please?

The project structure folder is:

├── src
│   ├── styles
│   │   │   ├── globalstyles.tsx
│   │   │   ├── render-theme.tsx
│   │   │   ├── theme.ts
│   ├── components
│   │   ├── Modal
│   │   │   ├── index.tsx
│   │   │   ├── styles.ts
│   ├── pages
│   │   ├── Home
│   │   │   ├── index.tsx
│   │   │   ├── styles.ts
│   │   ├── Posts
│   │   │   ├── index.tsx
│   │   │   ├── styles.ts

Besides login and delete post, the modal component will to be used to edit post:

Modal code:

import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { env } from '../../environments';
import { modalTypeEnum } from '../../utils/enum';
import { Button } from '../Button';
import { TextInput } from '../TextInput';
import {
  LoginModalContainer,
  LoginModalBackground,
  LoginModalContent,
  LoginModalContentHeader,
  LoginModalContentTitleText,
  LoginModalContentBody,
  LoginModalForm,
  LoginModalContentBodyDeleteConfirm,
  LoginModalContentBodyDeleteConfirmText,
} from './styles';

interface ModalProps {
  type: modalTypeEnum;
}

export function Modal({ type }: ModalProps) {
  const [username, setUsername] = useState<string>('');
  const navigate = useNavigate();

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    navigate(`${env.ROUTER_UTILS.base.posts}/${username}`);
  };

  const handleClose = async () => {
    document.querySelector('.modal-visible')?.classList.add('modal-hide');
  };

  return (
    <LoginModalContainer>
      <LoginModalBackground
        onClick={() => type !== modalTypeEnum.LOGIN && handleClose()}
        className={type !== modalTypeEnum.LOGIN ? 'modal-visible' : ''}
      >
        <LoginModalContent
          onClick={(e) => e.stopPropagation()}
          width={window.innerWidth}
        >
          {type === modalTypeEnum.LOGIN && (
            <LoginModalContentHeader>
              <LoginModalContentTitleText>
                Welcome to CodeLeap network!
              </LoginModalContentTitleText>
            </LoginModalContentHeader>
          )}
          <LoginModalContentBody>
            {type !== modalTypeEnum.DELETE_POST && (
              <LoginModalForm onSubmit={handleSubmit}>
                <TextInput
                  label={
                    type === modalTypeEnum.LOGIN
                      ? 'Please enter your username'
                      : 'Title'
                  }
                  value={username}
                  onChange={(e) => setUsername(e.target.value)}
                />
                <Button
                  inputValue={username ? true : false}
                  label="ENTER"
                  isWhite={false}
                />
              </LoginModalForm>
            )}
            {type === modalTypeEnum.DELETE_POST && (
              <LoginModalContentBodyDeleteConfirm>
                <LoginModalContentBodyDeleteConfirmText>
                  Are you sure you want to delete this item?
                </LoginModalContentBodyDeleteConfirmText>
              </LoginModalContentBodyDeleteConfirm>
            )}
          </LoginModalContentBody>
        </LoginModalContent>
      </LoginModalBackground>
    </LoginModalContainer>
  );
}

Modal Styles code:

import styled, { css } from 'styled-components';

interface LoginModalContentProps {
  width: number;
}

export const LoginModalContainer = styled.div`
  z-index: 9999;
  display: flex;
  .modal-visible.modal-hide {
    display: none;
  }
`;

export const LoginModalBackground = styled.div`
  width: 100vw;
  height: 100vh;
  background: ${({ theme }) => theme.colors.modalBackground};
  position: fixed;
  top: 0px;
  left: 0px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
`;

export const LoginModalContent = styled.div<LoginModalContentProps>`
  flex-direction: column;
  max-width: ${(p) => (p.width < 768 ? '' : '500px')};
  ${({ theme }) => css`
    background: ${theme.colors.white};
    width: 85%;
    min-width: 288px;
    padding: 30px;
    box-shadow: rgba(0, 0, 0, 0.6) 0px 7px 29px 0px;
    display: flex;
  `}
`;
export const LoginModalContentHeader = styled.div`
  display: flex;
  align-items: left;
  margin-bottom: ${({ theme }) => theme.spacings.small};
`;

export const LoginModalContentTitleText = styled.h1``;

export const LoginModalContentBody = styled.div`
  display: flex;
  width: 100%;
`;
export const LoginModalForm = styled.form``;

export const LoginModalFormButtonDiv = styled.div`
  width: 100%;
  display: flex;
  justify-content: flex-end;
  margin-top: ${({ theme }) => theme.spacings.small};
`;
export const LoginModalFormConfirmButton = styled.button``;
export const LoginModalContentBodyDeleteConfirm = styled.div``;
export const LoginModalContentBodyDeleteConfirmText = styled.p``;

globalstyle code:

import { createGlobalStyle } from 'styled-components';
import { Theme } from '../types/styled-components';

export const GlobalStyles = createGlobalStyle<Theme>`
 *{
  margin: 0;
  padding: 0;
  outline: none;
  box-sizing: border-box;
}

  html {
    font-size: 62.5%;
    scroll-behavior: smooth;
  }

  body {
    font-size: 1.6rem;
    font-family: ${({ theme }) => theme.font.family.default};
  }

  h1, h2, h3, h4, h5, h6 {
    font-family: ${({ theme }) => theme.font.family.default};
    color: ${({ theme }) => theme.colors.primaryColor};
  }
  h1 {
    font-size: ${({ theme }) => theme.font.sizes.large};
    font-weight: 700;
  }

  p {
    margin: ${({ theme }) => theme.spacings.medium} 0 ${({ theme }) =>
  theme.spacings.small} 0;
    font-size: 1.125em;
    color: ${({ theme }) => theme.colors.primaryColor};
  }
  /* a {
    color: ${({ theme }) => theme.colors.primaryColor};
    display: flex;
    flex-direction: column;
    align-items: center;
    transition: all, 0.3s;
    text-decoration: none;
    margin: 10px;
  }
  a:hover {
    color: ${({ theme }) => theme.colors.secondaryColor};
  } */

  button {
    width: 111px;
    color: ${({ theme }) => theme.colors.white};
    cursor: pointer;
    background: ${({ theme }) => theme.colors.primaryColor};
    border: 2px solid ${({ theme }) => theme.colors.primaryColor};
    padding: 5px 20px;
    font-size: ${({ theme }) => theme.font.sizes.small};
    transition: all, 0.3s;
  }
  button:hover {
    border-color: ${({ theme }) => theme.colors.secondaryColor};
  }

  button:disabled {
      background: ${({ theme }) => theme.colors.mediumGray};
      border: 2px solid transparent;
      cursor: not-allowed;
    }

  input[type='text'] {
      font-size: ${({ theme }) => theme.font.sizes.large};
      width: 100%;
      padding: 5px 10px;
      border-radius: 4px;
      &::placeholder {
        font-size: ${({ theme }) => theme.font.sizes.xsmall};
      }
  }
  textarea {
      border: 2px solid ${({ theme }) => theme.colors.primaryColor};
      resize: none;
      font-size: ${({ theme }) => theme.font.sizes.large};
      width: 100%;
      padding: 5px 10px;
      border-radius: 4px;
      &::placeholder {
        font-size: ${({ theme }) => theme.font.sizes.xsmall};
      }
  }
  /* .pressable {
    cursor: pointer;
    color: ${({ theme }) => theme.colors.primaryColor};
    text-decoration: none;
    border-color: transparent;
    transition: all, 0.3s;
  }
  .pressable:hover {
    color: ${({ theme }) => theme.colors.secondaryColor};
  } */
  form {
    width: 100%;
  }
  .icon-pressable {
    cursor: pointer;
    color: ${({ theme }) => theme.colors.white};
    text-decoration: none;
    border-color: transparent;
    transition: all, 0.3s;
  }
  .icon-pressable:hover {
    transform: scale(1.4);
  }
`;

CodePudding user response:

position: fixed doesn't work when there is transform css on one of the parent divs of the modal. Please try to not use transform on parent div.

So remove the transform: scale() css from parent div it should fix the issue.

  • Related