Jump to content
Search Community

Opening Flowbite Modals Kills Ability to Scroll

jamesCodes808 test
Moderator Tag

Recommended Posts

I am fairly new to Next.js, React hooks and everything. I am wondering if I am doing this right, I am making a customizable portfolio site using Next.js, Flowbite-react, and TailwindCSS on the front end and Django on the back end.

For testing, I have set up a Navbar, that opens up modals and gets the user's input.

 

When I click on the Modal, it gets rid of my ability to scroll down the page.

My components > Navbar.js looks like this, the {modalContent being passed in is basically separate forms in components}

import {Avatar, Dropdown, Modal, Navbar} from "flowbite-react";
import { useState } from 'react';
import EditEducation from "@/components/EditEducation";
import EditExperience from "@/components/EditExperience";
import EditSkills from "@/components/EditSkills";


export default function Nav({ setEducation, setExperience, setSkills }) {
    const [modalVisible, setModalVisible] = useState(false);
    const [modalContent, setModalContent] = useState(null);

    const openModal = (content) => {
        setModalContent(content);
        setModalVisible(true);
    };

    const closeModal = () => {
        setModalVisible(false);
        setModalContent(null);
    }

    const onEducationChange = (education) => {
        setEducation(education);
    }

    const onExperienceChange = (experience) => {
        setExperience(experience);
    }

    const onSkillsChange = (skills) => {
        setSkills(skills)
    }

    return (
        <>
            <Navbar
                fluid={true}
            >
                <div className='flex md:order-2'>
                    <Dropdown
                        arrowIcon={false}
                        inline={true}
                        label={<Avatar alt='User settings' img={null} rounded={true}/>} >
                        <Dropdown.Header>
                            <span className='block text-sm'>
                                tester
                            </span>
                            <span className='block truncate text-sm font-medium'>
                                test@test.com
                            </span>
                        </Dropdown.Header>
                        <Dropdown.Item>
                            Dashboard
                        </Dropdown.Item>
                        <Dropdown.Item>
                            Settings
                        </Dropdown.Item>
                        <Dropdown.Item>
                            Sign Out
                        </Dropdown.Item>
                    </Dropdown>
                    <Navbar.Toggle/>
                </div>
                <Navbar.Collapse>
                    <Navbar.Link href='/' active={true}>
                        Home
                    </Navbar.Link>
                    <Navbar.Link href='#' onClick={() => openModal(<EditEducation
                        onEducationChange={onEducationChange}
                        onClose={closeModal}/>)}>
                        Education
                    </Navbar.Link>
                    <Navbar.Link href='#' onClick={() => openModal(<EditExperience
                        onExperienceChange={onExperienceChange}
                        onClose={closeModal}/>)}>
                        Experience
                    </Navbar.Link>
                    <Navbar.Link href='#' onClick={() => {
                        openModal(
                            <EditSkills
                            onSkillsChange={onSkillsChange}
                            onClose={closeModal}
                            />)}}>
                        Skills
                    </Navbar.Link>
                </Navbar.Collapse>
            </Navbar>
            {modalVisible && (
                <Modal
                    id='edit_modal'
                    show={modalVisible}
                    size='md'
                    popup={true}
                    onClose={closeModal}>
                    <Modal.Header/>
                    <Modal.Body>{modalContent}</Modal.Body>

                </Modal>
            )}
        </>
    )
}


And this data is going up into my pages > index.js, then back down into the components > Portfolio.js
 

import React, { useState } from 'react'
import Hero from "@/components/Hero";
import Footer from "@/components/Footer";
import Portfolio from "@/components/Portfolio";
import Nav from "@/components/Nav";


function Home() {
    const [education, setEducation] = useState([]);
    const [experience, setExperience] = useState([]);
    const [skills, setSkills] = useState([]);

    return (
        <>

        <Nav
            setEducation={setEducation}
            setExperience={setExperience}
            setSkills={setSkills}
        />
        <Hero/>
        <Portfolio
            education={education}
            experience={experience}
            skills={skills}
        />
        <Footer/>

        </>
            )
}

export default Home

This is what my components > Portfolio.js looks like (Where the GSAP and parallax scrolling live)
 

import React, {useEffect, useRef} from 'react';
import { ParallaxProvider, Parallax } from 'react-scroll-parallax';
import { gsap } from 'gsap';
import ScrollTrigger from 'gsap/dist/ScrollTrigger';

const PortfolioSection = ({backgroundRef,
                              sectionRef,
                              triggerRef,
                              education,
                              experience,
                              skills}) => {
    const renderEducationContent = () => {
        return education.map((edu, index) => (
          <div key={index}>
            <h4>Degree: {edu.degree}</h4>
            <p>University: {edu.university}</p>
            <p>Year: {edu.year}</p>
          </div>
        ));
    };

    const renderExperienceContent = () => {
        return experience.map((exp, index) => (
          <div key={index}>
            <h4>Company: {exp.company}</h4>
            <p>Position: {exp.position}</p>
            <p>Duration: {exp.duration}</p>
          </div>
        ));
    };

    const renderSkillsContent = () => {
        return skills.map((skill, index) => (
          <div key={index}>
            <h4>Skill: {skill}</h4>
          </div>
        ));
    };

    const sections = [
        {title: 'Education', content: renderEducationContent()},
        {title: 'Experience', content: renderExperienceContent()},
        {title: 'Skills', content: renderSkillsContent()},
    ];

    return (
    <>
      <div className="scroll-section-outer">
        <ParallaxProvider scrollAxis="horizontal">
          <div ref={triggerRef}>
            <div ref={sectionRef} className="scroll-section-inner">
              {sections.map((section, index) => (
                <Parallax y={[-30, 30]} key={index}>
                  <div
                    ref={backgroundRef}
                    style={{
                      backgroundImage: "url('/Forest.png')",
                      backgroundSize: "cover",
                      backgroundPosition: "center",
                      width: "2000px",
                    }}
                    className="h-screen"
                  >
                    <section className="scroll-section">
                      <h3>{section.title}</h3>
                      <div>{section.content}</div>
                    </section>
                  </div>
                </Parallax>
              ))}
            </div>
          </div>
        </ParallaxProvider>
      </div>
    </>
    );

}
const Portfolio = ({ education, experience, skills }) => {
    const backgroundRef = useRef(null)
    const sectionRef = useRef(null)
    const triggerRef = useRef(null)

    gsap.registerPlugin(ScrollTrigger);

    useEffect(() => {
        const pin = gsap.fromTo(sectionRef.current, {
            translateX: 0
        }, {
            // increase and decrease based on section
            translateX: "-300vw",
            ease: "none",
            direction: 1,
            scrollTrigger: {
                trigger: triggerRef.current,
                start: "top top",
                // 2000 px at the top of the next section
                end: "2000 top",
                scrub: 0.6,
                pin: true
            }
        })

        // kills animation when the component gets unordered
        return () => {
            pin.kill()
        }
    }, {})


  return (
      <PortfolioSection
          backgroundRef={backgroundRef}
          sectionRef={sectionRef}
          triggerRef={triggerRef}
          education={education}
          experience={experience}
          skills={skills}
      />
  );
};

export default Portfolio;

Am I doing this right? Everything seems to work, except for the Modal somehow breaking my ability to scroll for some reason.

I have tried to add prevent defaults to the openmodal function, I have tried to put the form right on the main page, and that doesn't break it. For some reason, the only thing that breaks my scrolling is clicking on the Nav.Link, and opening the modal.

 

Link to comment
Share on other sites

It's pretty tough to troubleshoot without a minimal demo - the issue could be caused by CSS, markup, a third party library, your browser, an external script that's totally unrelated to GSAP, etc. Would you please provide a very simple CodePen or CodeSandbox that demonstrates the issue? 

 

Please don't include your whole project. Just some colored <div> elements and the GSAP code is best (avoid frameworks if possible). See if you can recreate the issue with as few dependancies as possible. If not, incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, then at least we have a reduced test case which greatly increases your chances of getting a relevant answer.

 

Here's a starter CodePen that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo

See the Pen aYYOdN by GreenSock (@GreenSock) on CodePen

 

If you're using something like React/Next/Vue/Nuxt or some other framework, you may find StackBlitz easier to use. We have a series of collections with different templates for you to get started on these different frameworks: React/Next/Vue/Nuxt.

 

Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. 

Link to comment
Share on other sites

  • 1 month later...

Make sure you're not conditionally rendering your `<Modal />`, but instead utilizing the `show` boolean attribute in the `<Modal />` component:

Wrong:
 

...

{modalVisible && (

  <Modal ...>

  </Modal>

)}
...


Right:
 

...

<Modal ... show={modalVisible}>

</Modal>

...
  • Like 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...