From 12e8f35f37dbd60de95a74bf932c27f6b5d082ce Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Mon, 16 May 2022 12:37:58 +0200 Subject: [PATCH 1/2] 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. --- .../@headlessui-react/src/components/dialog/dialog.tsx | 10 +++++++--- .../@headlessui-vue/src/components/dialog/dialog.ts | 10 +++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/@headlessui-react/src/components/dialog/dialog.tsx b/packages/@headlessui-react/src/components/dialog/dialog.tsx index b30176c22e..1881c12b4c 100644 --- a/packages/@headlessui-react/src/components/dialog/dialog.tsx +++ b/packages/@headlessui-react/src/components/dialog/dialog.tsx @@ -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 diff --git a/packages/@headlessui-vue/src/components/dialog/dialog.ts b/packages/@headlessui-vue/src/components/dialog/dialog.ts index e191758308..0845d073f8 100644 --- a/packages/@headlessui-vue/src/components/dialog/dialog.ts +++ b/packages/@headlessui-vue/src/components/dialog/dialog.ts @@ -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 From 2218fa4a34257e3d67c9daaecda8d98cb4656fe0 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Mon, 16 May 2022 12:42:52 +0200 Subject: [PATCH 2/2] update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0eb898b47..ecb306b1bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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