diff --git a/src/dom/events.ts b/src/dom/events.ts index a5c7423d2..79e4214ee 100644 --- a/src/dom/events.ts +++ b/src/dom/events.ts @@ -1,4 +1,5 @@ import { throttle } from '@pacote/throttle' +import { getStyle } from '@pacote/get-style' import { off, on } from 'delegated-events' import { CoreDriver, FootnoteAction, FootnoteLookup } from '../core' @@ -9,7 +10,6 @@ const SELECTOR_BUTTON = '[data-footnote-button]' const SELECTOR_FOOTNOTE = '[data-footnote-id]' const SELECTOR_POPOVER = '[data-footnote-popover]' const CLASS_FULLY_SCROLLED = 'is-fully-scrolled' -const CLASS_NO_SCROLL = 'littlefoot-no-scroll' function target(event: Event) { return event.target as HTMLElement @@ -19,6 +19,32 @@ function getFootnoteId(element: HTMLElement | null): string | undefined { return element?.dataset.footnoteId } +let initialBodyStyleOverflow: string | undefined +let initialBodyPadding: string | undefined + +function lockBodyScroll(): void { + if (initialBodyStyleOverflow === undefined) { + initialBodyPadding = getStyle(document.body, 'paddingRight') + initialBodyStyleOverflow = getStyle(document.body, 'overflow') + const scrollBarWidth = + window.innerWidth - document.documentElement.clientWidth + document.body.style.overflow = 'hidden' + document.body.style.paddingRight = scrollBarWidth + 'px' + } +} + +function unlockBodyScroll(): void { + if (initialBodyStyleOverflow) { + document.body.style.overflow = initialBodyStyleOverflow + initialBodyStyleOverflow = undefined + } + + if (initialBodyPadding) { + document.body.style.paddingRight = initialBodyPadding + initialBodyPadding = undefined + } +} + function handleTouch( lookup: FootnoteLookup, action: FootnoteAction, @@ -54,7 +80,12 @@ function handleHover( } function handleEscape(fn: () => void): EventHandler { - return event => event.keyCode === 27 && fn() + return event => { + if (event.keyCode === 27) { + unlockBodyScroll() + fn() + } + } } function handleScroll(popover: HTMLElement): EventHandler { @@ -81,12 +112,8 @@ export function bindScrollHandler( popover: HTMLElement ): void { content.addEventListener('wheel', throttle(handleScroll(popover), FRAME)) - content.addEventListener('mouseover', () => { - document.body.classList.add(CLASS_NO_SCROLL) - }) - content.addEventListener('mouseout', () => { - document.body.classList.remove(CLASS_NO_SCROLL) - }) + content.addEventListener('mouseover', lockBodyScroll) + content.addEventListener('mouseout', unlockBodyScroll) } export function addListeners({ diff --git a/src/dom/footnote.ts b/src/dom/footnote.ts index 248aeddf4..85e4451b9 100644 --- a/src/dom/footnote.ts +++ b/src/dom/footnote.ts @@ -43,7 +43,7 @@ export function createFootnote({ button.insertAdjacentElement('afterend', popover) - popover.style.maxWidth = `${document.body.clientWidth}px` + popover.style.maxWidth = document.body.clientWidth + 'px' const contentMaxHeight = getStyle(content, 'maxHeight') maxHeight = Math.round(pixels(contentMaxHeight, content)) diff --git a/styles/_littlefoot-content.scss b/styles/_littlefoot-content.scss index b1b7df1c5..67d2859c4 100644 --- a/styles/_littlefoot-content.scss +++ b/styles/_littlefoot-content.scss @@ -14,10 +14,6 @@ // @state .is-positioned-top - The popover is above the button. // @state .is-positioned-bottom - The popover is below the button. -.littlefoot-no-scroll { - overflow: hidden; -} - .littlefoot-footnote { background: $popover-color-background; border-radius: $popover-border-radius;