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
Modal | JS | Add page scrolling option #1304
Conversation
...ages/pattern-lab/_patterns/02-components/modal/custom-events/-modal-usage-custom-events.twig
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested and working as expected. Nice job @danielamorse.
As we chatted about, I'd recommend we make a two small tweaks to this:
- Move the two helper functions into
@bolt/core/utils
for easier maintainability - Try setting the data we're storing for later on the HTML elements as a property vs data attribute (double check to keep me honest on this one 😉)
// If the browser body has scrollbar, set padding on the element the width of the scrollbar
export const setScrollbarPadding = function(element, hasScrollbar, scrollbarWidth) {
if (!element) {
return;
}
if (hasScrollbar) {
const originalPaddingRight = element.style.paddingRight;
const calculatedPadding = window.getComputedStyle(element)[
'padding-right'
];
// Save original padding value for later
element.originalPaddingRight = originalPaddingRight;
element.style.paddingRight = parseFloat(calculatedPadding) + scrollbarWidth + 'px';
}
}
// Reset the padding on that element after modal is hidden
export const resetScrollbarPadding = function(element) {
if (!element) {
return;
}
if (typeof element.originalPaddingRight === 'undefined') {
element.style.paddingRight = '';
} else {
element.style.paddingRight = element.originalPaddingRight; // Restore original padding value
}
}
- Make sure our example shows how to account for selecting multiple elements + uses a
js-
selector
// Arbitrary fixed element, could be .c-page-header
const fixedElements = Array.from(document.querySelectorAll('.js-fixed-position'));
// Listen for 'modal:show' on the body, event will bubble up from the modal
document.body.addEventListener('modal:show', function(e) {
fixedElements.map(element => {
setScrollbarPadding(element, e.detail.hasScrollbar, e.detail.scrollbarWidth);
});
});
// Listen for 'modal:hidden', fires after the modal has animated out
document.body.addEventListener('modal:hidden', function(e) {
fixedElements.map(element => {
resetScrollbarPadding(element);
});
});
…ss, add 'preventBodyScroll' as prop
@@ -58,7 +58,10 @@ properties: | |||
uuid: | |||
type: string | |||
description: Unique ID for modal, randomly generated if not provided. | |||
|
|||
prevent_body_scroll: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@danielamorse would no_body_scroll
make more sense here?
packages/core/utils/scrollbar.js
Outdated
*/ | ||
export const getScrollbarWidth = () => { | ||
const scrollDiv = document.createElement('div'); | ||
scrollDiv.className = 'c-bolt-modal__scrollbar-measure'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure to remove this ;)
/** | ||
* Set padding on a given element equal to the browser's scrollbar width, used to prevent content shifting when scrollbars are turned off, e.g. when a modal opens | ||
* @param {HTMLElement} element - The target element | ||
* @param {(string\|number)} scrollbarWidth - The scrollbar width, with or without unit, e.g. 15 or 15px |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👏 we need to start doing this for all net-new JS coming in. Nice!!
@@ -52,7 +52,7 @@ bolt-modal:not([ready]) { | |||
position: fixed; | |||
top: 0; | |||
left: 0; | |||
width: 100vw; | |||
width: 100%; // Use % instead of vh or modal scrollbar is hidden behind bold scrollbar in IE11 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for commenting on this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work @danielamorse!
Make sure to nix that one modal-specific class on the new utility function + rename the new modal body scroll prop if you like the proposed name change. Other than that, this looks good to go. 👍
no_body_scroll: | ||
type: boolean | ||
description: Prevent background page content from scrolling when modal is open | ||
hidden: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sort of a nitpick, but can we make the default value (false) explicit the schema?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although, now that I think about it, do we ultimately want it to actually default to true
? That's the ideal UX after all once we can get it working...
I suppose the way you have it is the path of least resistance though. Don't let me derail it.
Done.
You both mentioned this point, and I say, if we're going to be strict about breaking changes, the default should be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’m good with this. @remydenton, any thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! I think that's an excellent choice @danielamorse. The behavior may change in the future (e.g. the background will stop scrolling), but that's not a breaking change if we never had a prop that would let you pick one or the other. And frankly, I don't think you should be able to pick one or the other-- we know which one's the better UX.
Jira
http://vjira2:8080/browse/BDS-1681
Summary
Allow page scroll behind modal to prevent content from shifting.
Details
Until we have a solid solution for content shifting / page scrolling when modal is open, just let the page scroll. The previous work to prevent the page from scrolling is now conditional based on the
preventBodyScrolling
prop.Code changes:
BoltModal
class, so that they are only called once (per feedback in Modal | JS | Visible shift of content when opening/closing video modal #1296).preventBodyScroll
as prop, default tofalse
.How to test