Open nahasco opened 1 month ago
i tried the same, with query params it opens but there is something wierd with vaul i guess it the moment you close it it also does force a navigation which is not the case with a normal portal if i use it
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Fragment, useEffect, useState } from 'react';
import { Route, Switch } from 'wouter';
import BottomSheet from '~components/BottomSheet/BottomSheet';
import MiniPlayer from '~components/MiniPlayer/MiniPlayer';
import PlayerScreen from '~components/Player/Player';
import BottomNavContainer from '~containers/BottomNavContainer';
import { LayoutContainer } from '~containers/LayoutContainer';
import { routes } from './routes';
const Modal = ({
children,
isOpen,
onClose,
}: {
children: React.ReactNode;
isOpen: boolean;
onClose: () => void;
}) => {
if (!isOpen) return null;
return (
<div className='w-full h-full'>
<BottomSheet isOpen={isOpen} onClose={onClose}>
{children}
</BottomSheet>
</div>
);
};
const Router = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
const toggleModal = () => {
const currentUrl = new URL(window.location.href);
if (isModalOpen) {
currentUrl.searchParams.delete('modal');
} else {
currentUrl.searchParams.set('modal', 'open');
}
window.history.pushState({}, '', currentUrl.toString());
setIsModalOpen(!isModalOpen);
};
const closeModal = () => {
const currentUrl = new URL(window.location.href);
currentUrl.searchParams.delete('modal');
window.history.back();
setIsModalOpen(false);
};
useEffect(() => {
const handlePopState = () => {
const currentUrl = new URL(window.location.href);
setIsModalOpen(currentUrl.searchParams.get('modal') === 'open');
};
window.addEventListener('popstate', handlePopState);
// Initial check for modal query param
const currentUrl = new URL(window.location.href);
setIsModalOpen(currentUrl.searchParams.get('modal') === 'open');
return () => {
window.removeEventListener('popstate', handlePopState);
};
}, []);
return (
<Fragment>
<LayoutContainer>
<Switch>
{routes.map((route) => (
<Route path={route.path} component={route.element as any} key={route.path} />
))}
</Switch>
</LayoutContainer>
<div onClick={toggleModal}>
<MiniPlayer />
</div>
<BottomNavContainer />
<Modal isOpen={isModalOpen} onClose={closeModal}>
<PlayerScreen />
</Modal>
</Fragment>
);
};
export default Router;
@nahasco this is how i have implemented, i am using wouter though hopefully it can help
I went with a simpler method, but I wouldnt call it a solution since it messes up the browser history, a bit.
const Drawer = ({ shouldScaleBackground = true, ...props }: React.ComponentProps<typeof DrawerPrimitive.Root>) => {
const router = useRouter()
const pathname = usePathname()
const handlePopState = React.useCallback(() => {
if (props.open) {
props.onOpenChange && props.onOpenChange(false)
router.replace(pathname)
}
}, [props.open, props.onOpenChange, router])
React.useEffect(() => {
window.addEventListener("popstate", handlePopState)
return () => {
window.removeEventListener("popstate", handlePopState)
}
}, [handlePopState])
React.useEffect(() => {
if (props.open) {
window.history.pushState({ drawerOpen: true }, "", pathname)
}
}, [props.open, pathname])
return <DrawerPrimitive.Root shouldScaleBackground={shouldScaleBackground} {...props} />
}
Hoping we get a better built in solution
Mobile users are used to swipe back to close an app drawer. When they use my web app and swipe back, they are navigated to the previous page. How can I make it so the drawer gets closed and stay on the same page instead of navigating to a previoud page?
Thought of using query params, but I think its a very complicated solution.