Improve "Scroll lock" scrollbar width for Dialog component (#1457)

* improve scroll lock, scrollbarWidth

The idea is as follow:
If you currently have a scrollbar, and you open a Dialog then we enable
a "Scroll lock" so that you can't scroll in the background behind the
modal. We can achieve this by adding a `overflow: hidden;` to the
`html`.

The issue is that by doing this, we lose the scrollbar and therefore the
page will jump to right because now there is a bit more room.

To account for this, we set a `padding-right` on the `html` of the
scrollbarWidth in pixels. This counteracts the visual jump you would
see.

The issue with this approach is that there could *still* be a scrollbar
once we add the `overflow: hidden`. This can happen if you use new css
features like the `scrollbar-gutter: stable;`.

To take this into account, we will measure the scrollbar again after we
set the `overflow: hidden`. Now we will only apply that counteracting
offset if there would actually be a jump by measuring the before and
after widths and applying the diff if there is one.

* update changelog
This commit is contained in:
Robin Malfait
2022-05-16 12:47:19 +02:00
committed by GitHub
parent 2390615ca0
commit 7344846fad
3 changed files with 16 additions and 6 deletions
+2
View File
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improve `FocusTrap` behaviour ([#1432](https://github.com/tailwindlabs/headlessui/pull/1432))
- Simplify `Popover` Tab logic by using sentinel nodes instead of keydown event interception ([#1440](https://github.com/tailwindlabs/headlessui/pull/1440))
- Ensure the `PopoverPanel` is clickable without closing the `Popover` ([#1443](https://github.com/tailwindlabs/headlessui/pull/1443))
- Improve "Scroll lock" scrollbar width for `Dialog` component ([#1457](https://github.com/tailwindlabs/headlessui/pull/1457))
## [Unreleased - @headlessui/react]
@@ -24,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Improve `FocusTrap` behaviour ([#1432](https://github.com/tailwindlabs/headlessui/pull/1432))
- Simplify `Popover` Tab logic by using sentinel nodes instead of keydown event interception ([#1440](https://github.com/tailwindlabs/headlessui/pull/1440))
- Ensure the `Popover.Panel` is clickable without closing the `Popover` ([#1443](https://github.com/tailwindlabs/headlessui/pull/1443))
- Improve "Scroll lock" scrollbar width for `Dialog` component ([#1457](https://github.com/tailwindlabs/headlessui/pull/1457))
## [@headlessui/react@1.6.1] - 2022-05-03
@@ -255,10 +255,14 @@ let DialogRoot = forwardRefWithAs(function Dialog<
let overflow = documentElement.style.overflow
let paddingRight = documentElement.style.paddingRight
let scrollbarWidth = ownerWindow.innerWidth - documentElement.clientWidth
let scrollbarWidthBefore = ownerWindow.innerWidth - documentElement.clientWidth
documentElement.style.overflow = 'hidden'
documentElement.style.paddingRight = `${scrollbarWidth}px`
if (scrollbarWidthBefore > 0) {
let scrollbarWidthAfter = documentElement.clientWidth - documentElement.offsetWidth
let scrollbarWidth = scrollbarWidthBefore - scrollbarWidthAfter
documentElement.style.paddingRight = `${scrollbarWidth}px`
}
return () => {
documentElement.style.overflow = overflow
@@ -225,10 +225,14 @@ export let Dialog = defineComponent({
let overflow = documentElement.style.overflow
let paddingRight = documentElement.style.paddingRight
let scrollbarWidth = ownerWindow.innerWidth - documentElement.clientWidth
let scrollbarWidthBefore = ownerWindow.innerWidth - documentElement.clientWidth
documentElement.style.overflow = 'hidden'
documentElement.style.paddingRight = `${scrollbarWidth}px`
if (scrollbarWidthBefore > 0) {
let scrollbarWidthAfter = documentElement.clientWidth - documentElement.offsetWidth
let scrollbarWidth = scrollbarWidthBefore - scrollbarWidthAfter
documentElement.style.paddingRight = `${scrollbarWidth}px`
}
onInvalidate(() => {
documentElement.style.overflow = overflow