'Position Fixed Sidebar Content Moves on Bootstrap Modal Close

We have an simple React application with a basic sidebar & a bootstrap modal. With Modal Open 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. With Modal Open after "X" MouseDown 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).



Solution 1:[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;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Igor Gonak