ui
ui copied to clipboard
Drawer custom onOpenChange is not working.
I convert isModalOpen from true to false with zustand, but it doesn't work.
'use client';
import { cn } from '@/utils';
import { useMediaQuery } from '@/hooks/custom/use-media-query';
import { Button } from '@/components/ui/button';
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog';
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from '@/components/ui/drawer';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { useModal } from '@/hooks/stores/use-modal-store';
import React from 'react';
export function AgendaDetailContentModal() {
const { isOpen, onClose, type, data } = useModal();
const { detailContent } = data;
const isModalOpen = isOpen && type === 'showAgendaDetailContent';
// const [open, setOpen] = React.useState(isModalOpen);
// This return not working in the mobile environment.
return (
<Drawer open={isModalOpen} onOpenChange={onClose}>
<DrawerContent>
<DrawerHeader className='text-left'>
<DrawerTitle>Edit profile</DrawerTitle>
<DrawerDescription>
Make changes to your profile here. Click save when you're done.
</DrawerDescription>
</DrawerHeader>
<ProfileForm className='px-4' />
<DrawerFooter className='pt-2'>
<DrawerClose asChild>
<Button variant='outline'>Cancel</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
);
}
function ProfileForm({ className }: React.ComponentProps<'form'>) {
return <form className={cn('grid items-start gap-4', className)}></form>;
}
This is zustand code.
import { create } from 'zustand';
export type ModalType = 'showAgendaDetailContent';
interface ModalData {
detailContent?: any;
}
interface ModalStore {
type: ModalType | null;
data: ModalData;
isOpen: boolean;
onOpen: (type: ModalType, data?: ModalData) => void;
onClose: () => void;
}
export const useModal = create<ModalStore>((set) => ({
type: null,
data: {},
isOpen: false,
onOpen: (type, data = {}) => set({ isOpen: true, type, data }),
onClose: () => set({ type: null, isOpen: false }),
}));
When I checked the console, 'isModalOpen' changed to false as soon as it changed to true. How can i fix this?
From republic of korea
remove the onOpenChange function from the drawer and call onClose function in the cancel button onclick event and that should work fine
Any fix to this. I have the exact same Zustand configuration. I made a ModalWrapper which will render Dialog or Drawer responsively but the drawer won't open. Dialog is opening fine:
"use client";
import { useMediaQuery } from "@/helpers/(hooks)/useMediaQuery";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "../ui/dialog";
import {
Drawer,
DrawerContent,
DrawerDescription,
DrawerHeader,
DrawerTitle,
} from "../ui/drawer";
import { useModal } from "@/helpers/(store)/ModalStore";
const ModalWrapper = ({
children,
open,
onOpenChange,
title,
description,
}: {
children: React.ReactNode;
open: boolean;
onOpenChange: () => void;
title: string;
description?: string;
}) => {
const isDesktop = useMediaQuery("(min-width: 768px)");
if (isDesktop) {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>{title}</DialogTitle>
{description ? (
<DialogDescription>{description}</DialogDescription>
) : null}
</DialogHeader>
<div className="py-4">{children}</div>
</DialogContent>
</Dialog>
);
}
return (
<Drawer open={open} onOpenChange={onOpenChange}>
<DrawerContent>
<DrawerHeader className="text-left">
<DrawerTitle>{title}</DrawerTitle>
<DrawerDescription>{description}</DrawerDescription>
</DrawerHeader>
<div className="py-4">{children}</div>
</DrawerContent>
</Drawer>
);
};
export default ModalWrapper;
I am having the same issue. When console logging the isOpen state, it changes to true but immediately back to false.
remove the onOpenChange function from the drawer and call onClose function in the cancel button onclick event and that should work fine
This works, but it creates an issue wherein, user can click on the backgroup and the drawer won't close. Any solution for this?
I think I found a temporary workaround. You can define a breakpoint variable in your state and when calling your onClose function, just do a check with Date.now() - breakpoint < 100.
onOpen: () =>
set({ isOpen: true, breakPoint: Date.now() }),
onClose: () => {
set((state) => {
if (Date.now() - state.breakPoint < 100) {
return { isOpen: true };
}
return { isOpen: false };
});
},
This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.
Sorry that I comment on a closed issue, but I created a Stackblitz reproducing this issue, https://stackblitz.com/edit/stackblitz-starters-pl9qx5?file=app%2Fpage.tsx.
Not sure if this bug is related to this issue in Vaul: https://github.com/emilkowalski/vaul/pull/291.
+1, did someone find the solution?
function, just do a check with Date.now() - breakpoint < 100.
onOpen: () => set({ isOpen: true, breakPoint: Date.now() }), onClose: () => { set((state) => { if (Date.now() - state.breakPoint < 100) { return { isOpen: true }; } return { isOpen: false }; }); },
You saved my day , Thanks alot
Guys, these functions (onEscapeKeyDown) are being called but don't know why it is not preventing closing the Drawer, any help?
const [isProcessing, setIsProcessing] = useState<boolean>(true)
<Drawer open={isOpen} onOpenChange={onOpenChange} direction="right">
<DrawerContent
onEscapeKeyDown={(e) => isProcessing && e.preventDefault()}
onInteractOutside={(e) => isProcessing && e.preventDefault()}
className="h-screen top-0 right-0 left-auto mt-0 w-[40%] rounded-none rounded-tl-2xl rounded-bl-2xl"
>
</DrawerContent>
</Drawer>
Any help would be appreciated.
I use this workaround if you don't use Zustand:
const prevOpen = useRef(open);
useEffect(() => {
if (prevOpen.current && !open) {
setTimeout(() => {
document.body.style.pointerEvents = "auto";
}, 400);
}
prevOpen.current = open;
}, [open]);
In my case Drawer adds pointer events to the body tag, making it impossible to scroll anymore.