Why is my next js mobile web app & safari zooming in when the keyboard is active but not zooming back until i tap the screen again?

58 views Asked by At

https://streamable.com/1jmdv0

the above shows a video of the issue (expires in 2 days).

but i have a react next js web app, in chrome it works fine but if i use safari or install the web app on android i get an issue where if the keyboard is active via my textArea and then i tap somewhere else, the whole screen zooms in & i lose my nav bar (rendered via _app, should always be anchored to the bottom of the screen).

Here is my code for the textBox

import React, { useState, useRef, useEffect } from 'react';
import styles from "../styles/postCreate.module.css";
import {Input, Textarea} from "@nextui-org/react";
import { postsModule } from "../API/PostsAPI";

const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

export default function PostCreate(){
    const [isOpen, setOpen] = useState(false);
    const [thought, setThought] = useState('');

    const [isPosting, setPostLoading] = useState(false);
    const [posted, setPosted] = useState(false);

    const [isPortrait, setIsPortrait] = useState(false);


    const ClearTextArea = () => {
        setThought('');
    };

    const handleBlur = (event) => {
       
        // Check if the textarea is empty and close if needed
        if (!thought.trim() && !isPosting) {
            event.preventDefault();
            setOpen(false);
        }
    };

    

    const HandlePost = async () => {
        setPosted(false);
        setPostLoading(true);
        var success = await postsModule.createPost(thought);
        
        setPosted(true);

        await wait(3000);

        ClearTextArea();
        setOpen(false);

        await wait(1000);

        setPostLoading(false);             
        setPosted(false);

    }

    var textAreaRef = useRef(null);
    useEffect(() => {

        // Focus on the textarea when it's rendered
        if (isOpen && !isPosting && !posted && textAreaRef != null && textAreaRef.current != null) {
            textAreaRef.current.focus();
        }else{
            textAreaRef = null;
            setIsPortrait(window.outerWidth < window.outerHeight);
        }

        setIsPortrait(window.outerWidth < window.outerHeight);
        const handleResize = () => {
            setIsPortrait(window.outerWidth < window.outerHeight);
        };
        window.addEventListener('resize', handleResize);
        
        return () =>{
            document.body.style.touchAction = '';
            window.removeEventListener('resize', handleResize);
        }

      

      }, [isOpen, isPosting, posted, isPortrait]);

    return ( 
        <>
            <div className={`${isOpen ? styles.centerContOpen : styles.centerCont}`}>
                <div className={`${isOpen ? styles.open : styles.closed}`}>
                   { isPosting ? 
                    <div className={`${styles.centerLoad}`}>
                        <div className={`${posted ? styles.success : styles.posting}`}>   


                        </div>
                    </div>
                    :
                    <div>
                        <Textarea
                            ref={textAreaRef} 
                            className={`${styles.textBox}`}
                            label="Create a thought"
                            placeholder="Enter your thought"
                            value={thought}
                            onChange={(e) => setThought(e.target.value)}
                            style={{ 
                              
                                width: '60vw',
                                backgroundColor: 'rgba(50, 50, 50, 0)', // Set the background color
                                color: 'white', // Set the text color
                                fontSize : '20px',
                                border: 'none',
                                borderRadius: '5px',
                                resize: 'none',
                                fontWeight:'normal',
                                outline: 'none',
                                marginTop: '10px'
                            }}
                            maxLength={250}
                            maxRows={100}
                            onBlur={handleBlur}
                            
                        />

                        <button className={`${styles.postButton}`} onClick={HandlePost}>
                            <p className={`${styles.text}`}>POST!</p>
                        </button>
                    </div>
                   
                    }

                    
                </div>
            </div>
            <div className={`${ (isPortrait ? styles.buttonContainerMobile : styles.buttonContainer) }`}>
                <button className={`${isOpen ? styles.closeButton : styles.createButton}`}  onClick={() => {
                        setOpen((prevOpen) => !prevOpen)
                        ClearTextArea();
                        }
                    }>
                      
                </button>
            </div>
        </>
    )
}

and here is my css:

.centerCont{
    display: flex;
    justify-content: center;
    width: 100vw;
    align-items: center;
    height: 100vh;
    position: fixed;
    z-index: 3;
    pointer-events: none;
    top: 0;
    left: 0;
    backdrop-filter: blur(0px);
    transition: backdrop-filter 1s ease;
}

.centerContOpen{
  display: flex;
  justify-content: center;
  width: 100vw;
  align-items: center;
  height: 100vh;
  position: fixed;
  z-index: 6;
  top: 0;
  left: 0;
  backdrop-filter: blur(15px);
  overflow: hidden;
  transition: backdrop-filter 1s ease;
}


.open{

    background-color: rgba(0, 0, 0, 0.342);
    height: fit-content;
    padding-bottom: 1vh;
    padding-left: 20px;
    padding-right: 20px;
    width: fit-content;
    border-radius: 30px;
    backdrop-filter: blur(15px);
    justify-content: center;
    border: 2px;
    border-color: rgba(179, 179, 179, 0.543);
    border-style:solid;
    transform: translateY(-60%);
}

.closed{
    position: fixed;
    background-color: rgba(0, 0, 0, 0.342);
    height: fit-content;
    padding-bottom: 1vh;
    padding-left: 20px;
    padding-right: 20px;
    width: fit-content;
    top: -30vh;
    border-radius: 30px;
    z-index: 2;
    backdrop-filter: blur(15px);
    justify-content: center;
    border: 2px;
    border-color: rgba(179, 179, 179, 0.543);
    border-style:solid;
    transform: translateY(-60%);
}

.textBox{
    color: aliceblue;
    font-size: 20px;
    font-weight: bolder;
    margin-top: 5vh;
   
    border-radius: 20px;
}

.buttonContainer{
    position: fixed;
    width: 10vw;
    height: 10vw;
    
    z-index: 10;
    bottom: 0vh;
    right: 0vw;
    border-radius: 50px;
   
  }

  .buttonContainerMobile{
    position: fixed;
    width: 10vw;
    height: 10vw;
    z-index: 10;
    bottom: 30vh;
    right: 0vw;
    border-radius: 50px;
   
  }
  
  .createButton{
    width: 5vw;
    height: 5vw;
    max-width: 80px;
    max-height:  80px;
    mask-image:url('/images/write.png');
    mask-size:contain;
    mask-repeat: no-repeat;
    mask-position: center center;
    background-color: white;
    animation: none;
    animation: show 0.7s ease-in 1;
  }

  .closeButton{
    width: 5vw;
    height: 5vw;
    max-width: 80px;
    max-height:  80px;
    mask-image:url('/images/close.png');
    mask-size:contain;
    mask-repeat: no-repeat;
    mask-position: center center;
    background-color: white;
    animation: none;
     animation: hide 0.7s ease-in 1;
  }

  .postButton{
    background-color: rgba(56, 56, 56, 0.183);
    width: 60vw;
    height: 4vh;
    border-radius: 20px;
    border: 1.5px;
    border-style: solid;
    border-color: rgba(240, 248, 255, 0.256);
    right: 0;
  }

  .text{
    color: rgba(255, 255, 255, 0.779);
    font-size: 2vh;
    font-weight: bolder;
  }

.centerLoad{
    display: flex;
    justify-content: center;
    width: 60vw;
}

  .posting{
    margin-top: 10vh;
    height: 10vh;
    width: 10vh;
    mask-image:url('/images/loading.png');
    mask-size: contain;
    background-size: cover;
    background: rgba(240, 248, 255, 0.192);
    animation: load 1.8s linear infinite;
    margin-bottom: 4vh;
  }

  .success{
    margin-top: 10vh;
    height: 10vh;
    width: 10vh;
    mask-image:url('/images/success.png');
    mask-size:contain;
    background: rgba(103, 103, 103, 0.279);
    margin-bottom: 4vh;
    animation: show 0.7s ease-in 1;
  }

  @keyframes load {
    0% {
      transform:rotate(0deg);

    }
    100% {
      transform:rotate(360deg);
    }
  }

  @keyframes show {
    0% {
      transform:scale(0);

    }
    80% {
        transform:scale(1.1);
      }
    100% {
      transform:scale(1);
    }
  }

  @keyframes hide {
    0% {
      transform:scale(0);

    }
    80% {
        transform:scale(1.1);
      }
    100% {
      transform:scale(1);
    }
  }

i tried adding:

  <Head>
                    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0,user-scalable=0" />
  </Head>

to my _app but did not work, i also ensured that my texts' font-size is 16px or greater but i still get the odd behaviour

0

There are 0 answers