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

Add Dialog.Backdrop and Dialog.Panel components #1333

Merged
merged 3 commits into from
Apr 14, 2022

Conversation

RobinMalfait
Copy link
Collaborator

@RobinMalfait RobinMalfait commented Apr 14, 2022

Update: Since merging this PR we've realized Dialog.Backdrop is unnecessary and we consider it deprecated and won't be including it in the documentation. Since we didn't realize this until a couple of hours after the v1.6 release, we're leaving it in to not break semantic versioning, but it will be removed whenever we eventually do a v2.0.


This PR adds 2 new components:

  • Dialog.Backdrop (React), DialogPanel (Vue)
  • Dialog.Panel (React), DialogPanel (Vue)

The Dialog.Backdrop will replace the Dialog.Overlay in a backwards compatible way, because the Dialog.Overlay will still be available.

What does this solve?

If you have a Dialog with a lot of content, then you want to scroll the Dialog, however in a lot of usage implementations the Dialog.Overlay gets in the way, and you will only be able to scroll with your mouse while it's over the panel itself (the typical white area in the center of your screen). You usually can't scroll the overlay (the gray area) so that is not good.

In addition, the scrollbar is typically hidden by the Dialog.Overlay, so if your users use the scrollbar itself, they can either not reach it because the overlay sits on top of it, or they can't click it to drag up/down because the Dialog will then close.

To fix those problems, we introduced a Dialog.Backdrop, this is very similar to the Dialog.Overlay, but there is a technical difference, it will be rendered in a portal as a sibling of the Dialog, not as a child of the Dialog. This fixes the scrolling issues. We created a new component to guarantee backwards compatibility, otherwise this would be a breaking change because now the component will be rendered in a different spot in the DOM.

This introduces another issue, the "outside click" behaviour is now technically broken. Because in most cases you are not clicking outside the Dialog component because they are typically rendered in "full screen" (especially if you use the Tailwind UI dialogs). To fix this, the Dialog.Overlay had a click listener to close the Dialog, but this new Dialog.Backdrop replacement is now rendered in a different spot and you can't even click it in most cases. To solve this issue we introduced a Dialog.Panel where you can mark that typical white box in the middle of the screen and if you click outside of that box, the Dialog will close.

There is also a hard dependency between the Dialog.Backdrop and the Dialog.Panel. If you start using the new Dialog.Backdrop then you have to use the Dialog.Panel as well to guarantee that all features keep working as they did before.

Upgrade example:

React

  import { useState } from 'react'
  import { Dialog } from '@headlessui/react'

  function MyDialog() {
    let [isOpen, setIsOpen] = useState(true)

    return (
      <Dialog open={isOpen} onClose={() => setIsOpen(false)}>
-       <Dialog.Overlay />
+       <Dialog.Backdrop />

+       <Dialog.Panel>
          <Dialog.Title>Deactivate account</Dialog.Title>
          <Dialog.Description>
            This will permanently deactivate your account
          </Dialog.Description>

          <p>
            Are you sure you want to deactivate your account? All of your data will
            be permanently removed. This action cannot be undone.
          </p>

          <button onClick={() => setIsOpen(false)}>Deactivate</button>
          <button onClick={() => setIsOpen(false)}>Cancel</button>
+       </Dialog.Panel>
      </Dialog>
    )
  }

Vue

  <template>
    <Dialog :open="isOpen" @close="setIsOpen">
-     <DialogOverlay />
+     <DialogBackdrop />

+     <DialogPanel>
        <DialogTitle>Deactivate account</DialogTitle>
        <DialogDescription>
          This will permanently deactivate your account
        </DialogDescription>

        <p>
          Are you sure you want to deactivate your account? All of your data will be
          permanently removed. This action cannot be undone.
        </p>

        <button @click="setIsOpen(false)">Deactivate</button>
        <button @click="setIsOpen(false)">Cancel</button>
+     </DialogPanel>
    </Dialog>
  </template>

  <script setup>
    import { ref } from 'vue'
    import {
      Dialog,
-     DialogOverlay,
+     DialogBackdrop,
+     DialogPanel,
      DialogTitle,
      DialogDescription,
    } from '@headlessui/vue'

    const isOpen = ref(true)

    function setIsOpen(value) {
      isOpen.value = value
    }
  </script>

Fixes: #1056
Fixes: #1132

@vercel
Copy link

vercel bot commented Apr 14, 2022

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployments, click below or on the icon next to each commit.

headlessui-react – ./packages/playground-react

🔍 Inspect: https://vercel.com/tailwindlabs/headlessui-react/4B4StKv84sZyL4rpakrw9Dhn6mgD
✅ Preview: https://headlessui-react-git-add-dialog-backdrop-and-panel-tailwindlabs.vercel.app

headlessui-vue – ./packages/playground-vue

🔍 Inspect: https://vercel.com/tailwindlabs/headlessui-vue/7FAr95CHegj4DqodZyxXBy6doE3A
✅ Preview: https://headlessui-vue-git-add-dialog-backdrop-and-panel-tailwindlabs.vercel.app

@jarcoal
Copy link

jarcoal commented Aug 8, 2022

@RobinMalfait I'm curious where the conversation is on Dialog.Backdrop being unnecessary. The reason I ask is because it did resolve my scrolling issues whereas the examples in the official docs did not (e.g. just using <div className="fixed inset-0 bg-black/30" />).

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

bug: scroll not working if I scroll over overlay in dialog Scrolling long content outside body not working
2 participants