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

fix(VDialog): allow nested elements to overflow scroll #13548

Merged
merged 4 commits into from
Jul 19, 2021

Conversation

jonathanrbowman
Copy link
Contributor

Description

While the Overlayable mixin's scroll listeners are active, its shouldScroll method now recursively checks the target element AND its ancestors to evaluate if we should allow the scroll event to go through. The check stops if the element being evaluated has the v-application class.

I originally had this stopping at the first ancestor with class v-dialog, but am not sure if there are other components or instances where the overlay is used. It seems to work fine using v-application to get the desired effect, though.

Motivation and Context

I created a component that has several scrollable elements - some nested - to display analytics/charts/lots of other stuff. When this content is rendered within a v-dialog, you are only able to scroll your target element. This means that you have to have your mouse cursor directly over an element in order to scroll it. So, at certain resolutions where the dialog is filled with a nested scrollable element, you would never be able to scroll the parent, and become stuck.

The goal of Overlayable's scroll event listener seems to be to prevent the background/body from scrolling while an overlay is active. This tweak seeks to maintain this intention, but while allowing the active elements within the overlay to still scroll correctly.

How Has This Been Tested?

Visually, by recreating conditions for the issue to arise.

Markup:

<template>
  <v-container>
    <h4>
      This is a scrollable element, with nested scrollable elements, outside of
      a dialog. You can scroll the blue area by scrolling through the green
      areas first, and eventually scroll even the body.
    </h4>
    <div class="outer-overflow">
      <div
        v-for="(x, y) in 3"
        :key="y"
        class="inner-overflow mb-4"
      >
        <p>
          words and words and words and words and words and words and words and
          words and words and words and words and words and words and words and
          words and words and words and words and words and words and words and
          words and words and words and words and words and words and words and
          words and words and words and words and words and words and words and
          words and words and words and words
        </p>
      </div>
    </div>

    <h4 class="my-6">
      Trying to do the same within a v-dialog, however, did not work. You could
      only scroll an element your mouse was directly over, due to the scroll
      event listeners added by the overlayable mixin. It should now allow you to
      scroll normally, while still preventing the background to scroll.
    </h4>

    <v-btn @click="dialogSize = 7">Show Big Dialog</v-btn>
    <v-btn @click="dialogSize = 1">Show Small Dialog</v-btn>

    <v-dialog
      :value="show"
      scrollable
      @input="dialogSize = $event"
    >
      <v-card>
        <v-card-title>Scrolling should work correctly in all elements</v-card-title>
        <v-card-text>
          <div
            v-for="(a, b) in dialogSize"
            :key="b"
            class="outer-overflow mb-8"
          >
            <div
              v-for="(x, y) in 3"
              :key="y"
              class="inner-overflow mb-4"
            >
              <p>
                words and words and words and words and words and words and
                words and words and words and words and words and words and
                words and words and words and words and words and words and
                words and words and words and words and words and words and
                words and words and words and words and words and words and
                words and words and words and words and words and words and
                words and words and words
              </p>
            </div>
          </div>
        </v-card-text>
      </v-card>
    </v-dialog>

    <v-card
      v-for="(n, i) in 10"
      :key="i"
      class="mt-10"
    >
      <v-card-title>I'm just here to make the page longer and scrollable</v-card-title>
      <v-card-text>
        <p>
          words and words and words and words and words and words and words and
          words and words and words and words and words and words and words and
          words and words and words and words and words and words and words and
          words and words and words and words and words and words and words and
          words and words and words and words and words and words and words and
          words and words and words and words
        </p>
      </v-card-text>
    </v-card>
  </v-container>
</template>

<script>
  export default {
    data: () => ({
      dialogSize: 0,
    }),

    computed: {
      show () {
        return !!this.dialogSize
      },
    },
  }
</script>

<style>
.outer-overflow {
  padding: 8px;
  width: 300px;
  height: 150px;
  background-color: blue;
  overflow-y: auto;
}

.inner-overflow {
  padding: 8px;
  background-color: green;
  max-height: 100px;
  overflow-y: auto;
}
</style>

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Improvement/refactoring (non-breaking change that doesn't add any features but makes things better)

Checklist:

  • The PR title is no longer than 64 characters.
  • The PR is submitted to the correct branch (master for bug fixes and documentation updates, dev for new features and backwards compatible changes and next for non-backwards compatible changes).
  • My code follows the code style of this project.
  • I've added relevant changes to the documentation (applies to new features and breaking changes in core library)

@jonathanrbowman jonathanrbowman changed the title Fix(Overlayable): Allow nested elements to overflow scroll fix(Overlayable): Allow nested elements to overflow scroll Apr 25, 2021
if (isAppWrapper) return false

const alreadyAtTop = el.scrollTop === 0
const alreadyAtBottom = el.scrollTop + el.clientHeight === el.scrollHeight
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it might be pretty expensive to do recursively on every scroll event?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's been working alright for me, but yes if you have tons of nested content it could be slow...but since we're overriding default scroll behavior I'm not sure how else to bubble the scroll event up through parents to mimic the default behavior we lost.

I'm definitely open to suggestions, though, if there is a more performant way to do this, or a way to skip elements that don't have the ability to scroll/are not overflowing content.

@KaelWD KaelWD added C: VOverlay VOverlay T: bug Functionality that does not work as intended/expected labels Jun 1, 2021
@johnleider johnleider added this to the v2.5.x milestone Jun 4, 2021
@johnleider johnleider added the S: stale This issue is untriaged and hasn't seen any activity in at least six months. label Jun 11, 2021
@johnleider johnleider marked this pull request as draft June 17, 2021 17:33
@jonathanrbowman jonathanrbowman marked this pull request as ready for review July 1, 2021 21:41
@jonathanrbowman
Copy link
Contributor Author

@KaelWD Sorry for the huge delay in seeing this - for some reason I wasn't getting notifications from GitHub when you left the above feedback for me.

@KaelWD KaelWD removed the S: stale This issue is untriaged and hasn't seen any activity in at least six months. label Jul 19, 2021
@KaelWD KaelWD changed the title fix(Overlayable): Allow nested elements to overflow scroll fix(VDialog): allow nested elements to overflow scroll Jul 19, 2021
@KaelWD KaelWD merged commit 24af61e into vuetifyjs:master Jul 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: VOverlay VOverlay T: bug Functionality that does not work as intended/expected
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants