Position Fixed Sidebar Content Moves on Bootstrap Modal Close

We have an simple React application with a basic sidebar & a bootstrap modal.
Position Fixed Sidebar Content Moves on Bootstrap Modal Close
And here is where we are observing strange behavior. If we click the “X” our sidebar drops down the page just for a moment until the modal closes.
Position Fixed Sidebar Content Moves on Bootstrap Modal Close
This behavior is not observed with any other button or input. Even if we click the “Close” button, which does the same thing (closes the modal), the sidebar does not move. It only moves when we mousedown on the “X”.

If I mouse down on the “X” and move my cursor away, then mouse up, the sidebar remains in the “moved down” state, until I close the modal.

This is very strange and we have no idea what could be going on here, any help would be greatly appreciated.

Here is the code for the React Component:

import React, { useContext, useEffect, useState, FC } from 'react'
import { NavLink } from 'react-router-dom'
import { BoxSeam, House, Check2Circle, Download } from 'react-bootstrap-icons'
import { GlobalContext } from '../context/GlobalContext'
import Header from '../components/Header'
import Snackbar from '../components/Snackbar'
import SelectLocationModal from '../components/SelectLocationModal'
import IPropsWithChildren from '../ts/interfaces/IPropsWithChildren.interface'
import INavLink from '../ts/interfaces/INavLink.interface'
import styles from '../styles/layouts/Layout.module.scss'

const PrivateLayout: FC<IPropsWithChildren> = ({ children }) => {
    // Sidebar default is closed below 768px screens & open on larger
    // Therefore, isSidebarOpen is only an appropriate name for smaller screens
    // On larger screens this would be interpreted as isSidebarClosed
    const [isSidebarOpen, setIsSidebarOpen] = useState(false);
    const { location, setLocation } = useContext(GlobalContext);
    const navLinks: INavLink[] = [
        {
            to: '/',
            icon: <BoxSeam />,
            displayText: 'Containers',
            disabled: false
        },
        {
            to: '/receiving',
            icon: <Download />,
            displayText: "Receiving",
            disabled: false
        },
        {
            to: '/approve',
            icon: <Check2Circle />,
            displayText: "Approve",
            disabled: false
        }
    ]

    const closeOnSmScreen = () => {
        setIsSidebarOpen(false);
    }

    useEffect(() => {
        const location = localStorage.getItem('LocationID');
        if (location) {
            setLocation(location);
        }
    }, [setLocation])

    return (
        <div>
            <SelectLocationModal    
                isOpen={location === ''} 
                handleClose={() => null}
            />

            <Header 
                setIsSidebarOpen={setIsSidebarOpen} 
                isSidebarOpen={isSidebarOpen} 
            />

            <div className={styles.wrapper}>
                <nav className={`${styles.sidebar} ${isSidebarOpen ? styles.active : ''} bg-light`}>
                    <div className={styles.sidebarContent}>
                        <ul className="ps-0">
                            {
                                navLinks.map((navLink, i) => (
                                    <li key={i}>
                                        <NavLink 
                                            to={ navLink.to }
                                            activeClassName={ navLink.disabled ? '' : styles.activeLink }
                                            className={`${navLink.disabled ? styles.disabledLink : ''} d-flex align-items-center flex-md-column py-2 navLink`}
                                            onClick={closeOnSmScreen}
                                            exact
                                        >
                                            {navLink.icon}
                                            <span>{navLink.displayText}</span>
                                        </NavLink>
                                    </li>
                                ))
                            }
                        </ul>
                    </div>
                </nav>
                <div className={"childrenContainer container"}>
                    {children}
                    <Snackbar />
                </div>
            </div>
        </div>
    )
}

export default PrivateLayout

And the CSS:

@import '../variables.scss';

.childrenContainer {
    padding-top: $headerHeight;
}

.activeLink {
    color: white !important;
    background-color: $primary;
}

// Sidebar
.wrapper {
    display: flex;
    align-items: stretch;
    width: 100%;
}

.sidebar {
    position: fixed;
    top: $headerHeight;
    z-index: 999;
    min-width: 85vw;
    min-height: calc(100vh - #{$headerHeight}); 
    margin-left: -85vw;
    transition: .2s ease-in;
}

.sidebar.active {
    margin-left: 0;
    box-shadow: 2px 0px 15px 0px #000;
}

.sidebarContent {
    position: sticky;
    li {
        list-style: none;
        a {
            text-decoration: none;
            color: var(--dark);
        }
    }
}


.disabledLink {
    text-decoration: line-through !important;
}

.navLink {
    padding-left: 1rem;
    span {
        padding-left: .5rem;
    }
    svg {
        height: 1.25rem;
        width: 1.25rem;    
    }
}


@media screen and (min-width:768px) {
    .childrenContainer {
        padding-top: $headerLgHeight;
    }

    .sidebar {
        position: sticky;
        padding-top: $headerLgHeight;
        margin-left: 0;
        max-width: $sidebarWidth;
        min-width: $sidebarWidth;
        height: 100vh;
    }

    .sidebar.active {
        margin-left: -$sidebarWidth;
        box-shadow: none;
        background: white !important;
    }

    .sidebarContent {
        position: fixed;
        width: $sidebarWidth;
    }

    .navLink {
        display: flex;
        flex-direction: column;
        align-items: center;
        padding-left: 0;
        span {
            padding-left: 0;
            font-size: .67rem;
        }
        svg {
            height: 1.25rem;
            width: 1.25rem;
        }
    }
}

Here is a code snadbox that reproduces the behavior described above (thanks Igor Gonak for initiating this).

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Just remove “top” and it stops flipping:

.sidebar {
    position: fixed;
    // top: $headerHeight;
    z-index: 999;
    min-width: 85vw;
    min-height: calc(100vh - #{$headerHeight}); 
    margin-left: -85vw;
    transition: .2s ease-in;
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x