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

Modified the Modal component to allow modalRoot to also be the target… #444

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions pages/modal/alt-modal-root.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useRef, useState } from 'react';
import ScreenshotArea from '../utils/screenshot-area';
import { Modal, Button } from '~components';
import styles from './styles.scss';

export default function () {
const [visible, setVisible] = useState(false);
const [confine, setConfine] = useState(true);
const appRootRef = useRef<HTMLDivElement>(null);

/**
* Here I am creating a box that is scrollable. I have also included a button for removing the
* box confines and the modalRoot prop on the modal. You can compare how my changes to the modal
* component by allowing the modalRoot to become the target of the modal window can work in default
* cases where you want it applied globally on the body tag but also for cases where you want it applied
* within another container (for micro-frontend integrations).
*/

return (
<div>
<div ref={appRootRef} className={confine ? styles.root : undefined}>
<article>
<h1>Alternate Modal Root</h1>
<Button onClick={() => setVisible(true)}>Show modal</Button>
<Button onClick={() => setConfine(!confine)}>Toggle box size</Button>
<p style={{ fontSize: '30px' }}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Orci porta non pulvinar neque laoreet suspendisse. Urna nec tincidunt praesent semper.
Fermentum posuere urna nec tincidunt. Adipiscing at in tellus integer feugiat scelerisque varius morbi enim.
Quis auctor elit sed vulputate mi sit. Nibh sit amet commodo nulla facilisi nullam vehicula ipsum. Vitae
tortor condimentum lacinia quis vel eros donec ac. Amet tellus cras adipiscing enim eu turpis egestas
pretium aenean. Aliquet lectus proin nibh nisl condimentum id. Ut pharetra sit amet aliquam id. Odio tempor
orci dapibus ultrices in. Amet venenatis urna cursus eget nunc. Viverra orci sagittis eu volutpat odio
facilisis mauris sit amet. Scelerisque eleifend donec pretium vulputate sapien nec sagittis. Vivamus arcu
felis bibendum ut tristique et egestas. Quam vulputate dignissim suspendisse in est. Dapibus ultrices in
iaculis nunc sed augue lacus viverra. Et ligula ullamcorper malesuada proin. Pretium aenean pharetra magna
ac placerat vestibulum lectus. Mauris cursus mattis molestie a iaculis at erat pellentesque adipiscing.
Vitae justo eget magna fermentum iaculis eu non diam. Metus vulputate eu scelerisque felis imperdiet proin
fermentum leo vel. Sem et tortor consequat id porta nibh. Donec adipiscing tristique risus nec. Sit amet
mauris commodo quis imperdiet. Lacinia at quis risus sed. Ultricies mi quis hendrerit dolor magna eget. Urna
et pharetra pharetra massa massa. Arcu felis bibendum ut tristique et egestas quis. Tortor consequat id
porta nibh. Suspendisse faucibus interdum posuere lorem ipsum. Tincidunt augue interdum velit euismod in.
Aliquam id diam maecenas ultricies mi. Tortor dignissim convallis aenean et tortor at. Laoreet sit amet
cursus sit amet dictum. Neque convallis a cras semper auctor neque vitae tempus quam. Mattis vulputate enim
nulla aliquet porttitor. Tortor vitae purus faucibus ornare suspendisse sed nisi lacus sed. Purus semper
eget duis at tellus at. Urna cursus eget nunc scelerisque viverra mauris in aliquam. Nibh cras pulvinar
mattis nunc sed. Sodales ut eu sem integer vitae justo eget. Ultrices neque ornare aenean euismod elementum
nisi quis eleifend. Cursus vitae congue mauris rhoncus. Ipsum dolor sit amet consectetur adipiscing.
Volutpat ac tincidunt vitae semper quis. Justo eget magna fermentum iaculis eu non diam. Amet justo donec
enim diam vulputate ut. Massa tincidunt dui ut ornare lectus sit amet est placerat. Auctor eu augue ut
lectus arcu bibendum at varius vel. Tempus urna et pharetra pharetra massa. Mauris commodo quis imperdiet
massa tincidunt nunc pulvinar sapien. Elementum tempus egestas sed sed risus pretium quam. Mattis
ullamcorper velit sed ullamcorper morbi tincidunt ornare massa eget. Risus commodo viverra maecenas
accumsan. Ultrices neque ornare aenean euismod elementum nisi. Tellus mauris a diam maecenas sed enim.
Scelerisque in dictum non consectetur a. Convallis convallis tellus id interdum velit laoreet id donec. Ac
tincidunt vitae semper quis lectus nulla at. Est lorem ipsum dolor sit amet. Consequat interdum varius sit
amet mattis vulputate enim nulla aliquet. Amet dictum sit amet justo. Hac habitasse platea dictumst quisque.
Leo in vitae turpis massa sed elementum tempus egestas sed. Massa placerat duis ultricies lacus sed. Rutrum
tellus pellentesque eu tincidunt. Tincidunt augue interdum velit euismod in pellentesque massa placerat
duis. Tempor orci eu lobortis elementum nibh tellus molestie nunc.
</p>
<ScreenshotArea>
<Modal
header="Delete instance"
visible={visible}
onDismiss={() => setVisible(false)}
closeAriaLabel="Close modal"
modalRoot={confine ? appRootRef.current ?? undefined : undefined}
footer={
<span style={{ display: 'flex', justifyContent: 'flex-end' }}>
<Button variant="link">Cancel</Button>
<Button variant="primary">Delete</Button>
</span>
}
>
This will permanently delete your instance, and may affect the performance of other resources.
</Modal>
</ScreenshotArea>
</article>
</div>
</div>
);
}
7 changes: 7 additions & 0 deletions pages/modal/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,10 @@
.awsui-util-f-r {
float: right;
}

.root {
position: relative;
width: 800px;
height: 800px;
overflow: scroll;
}
34 changes: 17 additions & 17 deletions src/modal/body-scroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,42 @@ import { browserScrollbarSize } from '../internal/utils/browser-scrollbar-size';

let initialBodyPaddingRightStyle: string | undefined = undefined;

export function disableBodyScrolling() {
setBodyScrollbarPadding();
document.body.classList.add(styles['modal-open']);
export function disableScrolling(target: HTMLElement = document.body) {
setScrollbarPadding(target);
target.classList.add(styles['modal-open']);
}

export function enableBodyScrolling() {
document.body.classList.remove(styles['modal-open']);
restoreBodyScrollbarPadding();
export function enableScrolling(target: HTMLElement = document.body) {
target.classList.remove(styles['modal-open']);
restoreScrollbarPadding(target);
}

function setBodyScrollbarPadding() {
if (bodyHasScrollbar()) {
initialBodyPaddingRightStyle = document.body.style.paddingRight;
function setScrollbarPadding(target: HTMLElement = document.body) {
if (targetHasScrollbar(target)) {
initialBodyPaddingRightStyle = target.style.paddingRight;
const initialBodyPaddingRight = computedBodyPaddingRightPixels();
const scrollbarWidth = browserScrollbarSize().width;
const newBodyPaddingRight = initialBodyPaddingRight + scrollbarWidth;
document.body.style.paddingRight = newBodyPaddingRight + 'px';
target.style.paddingRight = newBodyPaddingRight + 'px';
}
}

function computedBodyPaddingRightPixels() {
return parseInt(window.getComputedStyle(document.body).paddingRight, 10);
function computedBodyPaddingRightPixels(target: HTMLElement = document.body) {
return parseInt(window.getComputedStyle(target).paddingRight, 10);
}

function restoreBodyScrollbarPadding() {
function restoreScrollbarPadding(target: HTMLElement = document.body) {
if (initialBodyPaddingRightStyle) {
document.body.style.setProperty('padding-right', initialBodyPaddingRightStyle);
target.style.setProperty('padding-right', initialBodyPaddingRightStyle);
} else {
document.body.style.removeProperty('padding-right');
target.style.removeProperty('padding-right');
}
initialBodyPaddingRightStyle = undefined;
}

function bodyHasScrollbar() {
function targetHasScrollbar(target: HTMLElement = document.body) {
// Unfortunately this difference doesn't appear to match the scrollbar width during testing,
// otherwise we could remove browserScrollbarSize(). Bootstrap also doesn't use this difference
// directly.
return document.body.clientWidth < window.innerWidth;
return target.clientWidth < window.innerWidth;
}
12 changes: 6 additions & 6 deletions src/modal/internal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import Portal from '../internal/components/portal';
import { useContainerBreakpoints } from '../internal/hooks/container-queries';
import { useVisualRefresh } from '../internal/hooks/use-visual-mode';

import { disableBodyScrolling, enableBodyScrolling } from './body-scroll';
import { disableScrolling, enableScrolling } from './body-scroll';
import { ModalProps } from './interfaces';
import styles from './styles.css.js';
import { SomeRequired } from '../internal/types';
Expand Down Expand Up @@ -53,18 +53,18 @@ export default function InternalModal({
// enable body scroll and restore focus if unmounting while visible
useEffect(() => {
return () => {
enableBodyScrolling();
enableScrolling(modalRoot);
};
}, []);
}, [modalRoot]);

// enable / disable body scroll
useEffect(() => {
if (visible) {
disableBodyScrolling();
disableScrolling(modalRoot);
} else {
enableBodyScrolling();
enableScrolling(modalRoot);
}
}, [visible]);
}, [visible, modalRoot]);

// Because we hide the element with styles (and not actually detach it from DOM), we need to scroll to top
useEffect(() => {
Expand Down
2 changes: 1 addition & 1 deletion src/modal/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ $modal-z-index: 5000;
left: 0;
right: 0;
top: 0;
position: fixed;
position: absolute;
z-index: $modal-z-index;

outline: 0;
Expand Down