emilkowalski / vaul

An unstyled drawer component for React.
https://vaul.emilkowal.ski
MIT License
5.77k stars 194 forks source link

React only on close inside drawer (by drag or click close) #163

Closed beautyfree closed 1 week ago

beautyfree commented 10 months ago

Looks like onOpenChange trigger when I change the open property, but I want to react only on close inside drawer. also onClose triggers then I change open to false and it doesn't allow me to make needed flow.


I use open there I pass boolean which check should this drawer be opened or not (I use name of drawer and compare it with state) then I click on Continue button in drawer it change state to name of another drawer and onClose I set name of previous drawer

In the current realization of this library instead of opening the next drawer after clicking on Continue button, it triggers also onClose (because open changing to false) which return user to the previous drawer

beautyfree commented 10 months ago

I made example to demonstrate what all react HTML primitives (select in this case) don't call some onChange callback on value prop changes https://codesandbox.io/s/blissful-firefly-f32tg3?file=/src/App.tsx

beautyfree commented 10 months ago

and this is my code that I talked about above:

export const TransactionDetails = () => {
  const [state, send] = useStateMachine();

  const open = state.matches("SEND_TOKEN.TRANSACTION_DETAILS");

  return (
    <Sheet
      open={open}
      onClose={() => send("back")}
      icon="settings_ethernet"
      title="Transaction details"
    >
      <div
        className="grid gap-4 mt-4"
        onClick={() => send("transactionSubmitted")}
      >
        <Button>Continue</Button>
      </div>
    </Sheet>
  );
};

export const Sheet: FunctionComponent<Props> = ({
  trigger,
  open,
  onClose,
  icon,
  title,
  children,
}) => {
  return (
    <Drawer.Root open={open} onClose={onClose}>
      {trigger ? <Drawer.Trigger asChild>{trigger}</Drawer.Trigger> : null}
      <Drawer.Portal>
        <Drawer.Overlay className="fixed inset-0 bg-black/40" />
        <Drawer.Content className="bg-white flex flex-col rounded-t-[10px] mt-24 fixed bottom-0 left-0 right-0">
          <div className="p-4 bg-white rounded-t-[10px] flex-1">
            <div className="mx-auto w-12 h-1 flex-shrink-0 rounded-full bg-outline mb-4" />
            <div className="max-w-md mx-auto">
              <Icon name={icon} className="w-6 h-6 mb-4" />
              <Drawer.Title className="text-[22px] font-normal font-['Roboto'] leading-7 mb-[18px]">
                {title}
              </Drawer.Title>
              {children}
            </div>
          </div>
        </Drawer.Content>
      </Drawer.Portal>
    </Drawer.Root>
  );
};
samcanonkim commented 10 months ago

Also experiencing this issue.

With shadcn, I used onOpenChange to handle modal closing logic for Sheet and Dialog -- combining clean up functions with onClose().

With vaul, onOpenChange gets triggered immediately when open is set to true. This makes the clean up functions inside onOpenChange close Drawer immediately after opening it.

emilkowalski commented 1 week ago

Fixed in #408