Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug Report][3.3.19] Clicking close button of VSnackbar opened after VDialog closes the dialog too #18384

Closed
MetRonnie opened this issue Oct 2, 2023 · 7 comments · Fixed by #19393

Comments

@MetRonnie
Copy link
Contributor

MetRonnie commented Oct 2, 2023

Environment

Vuetify Version: 3.5.1
Last working version: 3.1.8
Vue Version: 3.4.15
Browsers: Edge 117.0.2045.47
OS: Windows 10

Steps to reproduce

  1. Have a v-snackbar that opens after a v-dialog (e.g. showing an error message after submitting a form in the dialog).
  2. Click the close button in the snackbar

Expected Behavior

The snackbar closes.

Actual Behavior

Both the snackbar and the dialog close.

Reproduction Link

https://play.vuetifyjs.com/#...

Other comments

Probably related to the fix for #16893.

I tried using @click.stop in the snackbar's close button but that didn't do anything.

This is a recreation of #17013 after that was closed as a duplicate of #7310 but then the latter was closed as only applying to v2

@3aluw
Copy link
Contributor

3aluw commented Oct 6, 2023

The dialog will close on every click outside of it, you can use the persistent prop to alter that behavior. Demo

@MetRonnie
Copy link
Contributor Author

See #17398 for why I am not currently using persistent

@loihp
Copy link

loihp commented Nov 13, 2023

The problem has been resolved ? have any new update ? pls help me

@ThomasWestrelin
Copy link

This also applies to datepickers.

@MetRonnie
Copy link
Contributor Author

I ended up having to use persistent and then manually adding back in the close-on-click-outside and close-on-escape functionality

  1. Using v-click-outside directive with a handler:

    onClickOutside = (e) => {
      // Only close on click outside if it's the "scrim", i.e. we are
      // not clicking on an error snackbar for example
      if (e.target?.classList.contains('v-overlay__scrim')) {
        close()
      }
    }
  2. onKeydown = (e) => {
      if (e.key === 'Escape') {
        close()
      }
    }
    
    onMounted(() => {
      document.addEventListener('keydown', onKeydown)
    })
    
    onBeforeUnmount(() => {
      document.removeEventListener('keydown', onKeydown)
    })

However I haven't figured out how to re-enable the browser back button closing the dialog

@AntonioDell
Copy link

AntonioDell commented Feb 16, 2024

I ran into this issue too and the only solution I found is to use the attach property to teleport the snackbar inside the dialog if one exists. I created a small helper composable to have a reactive attach variable, which will either be the dialogs overlay content or true, based on whether or not a dialog exists when the snackbar text changes.

I don't like this solution. There should be a way to make the dialog aware of the snackbar and setting an exception for the outside click close.

Composable:

type Teleport = boolean | string | HTMLElement;
const useDialogAwareTeleport = (
  teleportOverride?: MaybeRefOrGetter<Teleport | undefined>,
  elementRef?: MaybeRefOrGetter<undefined | { $el: Node | null }>,
  resetOnChange?: MaybeRefOrGetter,
  dialogSelector: string = ".v-dialog > .v-overlay__content"
) => {
  const dialogAwareTeleport = ref<Teleport>();

  watchEffect(() => {
    toValue(resetOnChange); // This makes sure the watcher is run on changes of resetOnChange refs
    if (toValue(teleportOverride) !== undefined) {
      dialogAwareTeleport.value = toValue(teleportOverride)
      return;
    }

    const containingDialog = findContainingDialog();
    dialogAwareTeleport.value = containingDialog ? containingDialog : true;
  });

  function findContainingDialog() {
    const dialogs = document.querySelectorAll<HTMLElement>(dialogSelector);
    if (dialogs.length === 0) return null;

    const elementContainer = toValue(elementRef);
    if (!elementContainer) return dialogs[0];

    let containingDialog = null;
    for (let i = 0; i < dialogs.length && containingDialog === null; i++) {
      const dialog = dialogs[i];
      if (dialog.contains(elementContainer.$el)) {
        containingDialog = dialog;
      }
    }
    return containingDialog;
  }

  return { dialogAwareTeleport };
};

export { useDialogAwareTeleport };

Usage (some business logic code left out):

<template>
  <v-snackbar
    v-model="isOpen"
    :timeout="-1"
    multi-line
    :attach="dialogAwareTeleport"
  >
    <span>{{snackbarText}}</span>

    <template #actions>
      <e-button
        ref="closeButtonRef"
        variant="text"
        icon="mdi-close"
        @click="closeSnackbar"
      />
    </template>
  </v-snackbar>
</template>
<script setup lang="ts">

const isOpen = ref(false);
const snackbarText = ref("");
const closeButtonRef = ref();


const snackbarIsVisible = useElementVisibility(closeButtonRef);
watch(snackbarIsVisible, (isVisible) => {
  if (!isVisible && isOpen.value) closeSnackbar();
});


const { dialogAwareTeleport } = useDialogAwareTeleport(
  undefined,
  undefined,
  snackbarText,
  ".v-dialog > .v-overlay__content"
);
</script>

@MetRonnie
Copy link
Contributor Author

I think I've got a fix for this, will open a PR soon

MetRonnie added a commit to MetRonnie/vuetify that referenced this issue Mar 13, 2024
fixes vuetifyjs#18384
Don't close on click outside if using scrim and the click is on an
element above the scrim.
MetRonnie added a commit to MetRonnie/vuetify that referenced this issue Mar 13, 2024
fixes vuetifyjs#18384
Don't close on click outside if using scrim and the click is on an
element above the scrim.
MetRonnie added a commit to MetRonnie/vuetify that referenced this issue Mar 14, 2024
fixes vuetifyjs#18384
Don't close on click outside if using scrim and the click is on an
element above the scrim.
johnleider pushed a commit to MetRonnie/vuetify that referenced this issue Mar 19, 2024
fixes vuetifyjs#18384
Don't close on click outside if using scrim and the click is on an
element above the scrim.
johnleider added a commit that referenced this issue Mar 19, 2024
fixes #18384

Co-authored-by: John Leider <john@vuetifyjs.com>
MetRonnie added a commit to cylc/cylc-ui that referenced this issue Mar 20, 2024
MetRonnie added a commit to cylc/cylc-ui that referenced this issue Mar 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants