From e568cd28f414d76c392ce5d0b0925bcc3232141a Mon Sep 17 00:00:00 2001 From: Adam Kudrna Date: Wed, 15 May 2024 11:25:20 +0200 Subject: [PATCH] BREAKING CHANGE(web): Turn off scrolling inside `ModalDialog` by default #DS-1184 --- docs/migrations/web/MIGRATION-v2.md | 3 + packages/web/DEPRECATIONS-v2.md | 18 +- .../web/src/scss/components/Modal/README.md | 132 +++---- .../web/src/scss/components/Modal/_Modal.scss | 8 +- .../src/scss/components/Modal/_ModalBody.scss | 4 +- .../scss/components/Modal/_ModalDialog.scss | 43 ++- .../web/src/scss/components/Modal/_theme.scss | 24 +- .../web/src/scss/components/Modal/index.html | 346 ++++++++---------- 8 files changed, 272 insertions(+), 306 deletions(-) diff --git a/docs/migrations/web/MIGRATION-v2.md b/docs/migrations/web/MIGRATION-v2.md index d04f470707..21bee550cc 100644 --- a/docs/migrations/web/MIGRATION-v2.md +++ b/docs/migrations/web/MIGRATION-v2.md @@ -120,6 +120,9 @@ The `.ModalDialog--nonScrollable` modifier was removed and the ModalDialog is ma In the new version, use the `.ModalDialog--scrollable` modifier class to make the ModalDialog scrollable. +If you use `ScrollView` for scrolling the content of your modal, you must also add the `.ModalDialog--scrollable` class +to the `.ModalDialog` element. + - `.ModalDialog` → `.ModalDialog .ModalDialog--scrollable` ### Modal: Uniform Variant Feature Flag diff --git a/packages/web/DEPRECATIONS-v2.md b/packages/web/DEPRECATIONS-v2.md index 5c44c165b0..1f3df0fc26 100644 --- a/packages/web/DEPRECATIONS-v2.md +++ b/packages/web/DEPRECATIONS-v2.md @@ -1,23 +1,13 @@ # Deprecations List -Following deprecations will be removed in version 2 of the _spirit-web_ package. +This document lists all deprecations that will be removed in the next major version of the _spirit-web_ package. -> Please follow these steps to safely upgrade your design system to Spirit Design System v2 components. - -[What are deprecations?][readme-deprecations] +> Please follow the migration guides to safely upgrade your design system components. ## Deprecations -### Modal (Non)Scrollable - -The `.ModalDialog--nonScrollable` modifier will be removed and the ModalDialog will be made non-scrollable by default. - -#### Migration Guide - -In the new version, use the `.ModalDialog--scrollable` modifier class to make the ModalDialog scrollable. +Nothing here right now! 🎉 -- `.ModalDialog` → `.ModalDialog .ModalDialog--scrollable` +👉 [What are deprecations?][readme-deprecations] [readme-deprecations]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web/README.md#deprecations -[readme-feature-flags]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web/README.md#feature-flags -[dictionary-placement]: https://github.com/lmc-eu/spirit-design-system/blob/main/docs/DICTIONARIES.md#placement diff --git a/packages/web/src/scss/components/Modal/README.md b/packages/web/src/scss/components/Modal/README.md index 77908d05c0..1f30328f83 100644 --- a/packages/web/src/scss/components/Modal/README.md +++ b/packages/web/src/scss/components/Modal/README.md @@ -39,56 +39,6 @@ Example: ``` -### Custom Height - -By default, Modal expands to fit the height of its content, as long as it fits the viewport (see [more below](#custom-max-height)). -You can override this behavior by setting a custom preferred height using a custom property: - -- `--modal-preferred-height-mobile` for mobile screens, and -- `--modal-preferred-height-tablet` for tablet screens and up. - -This is useful for Modals with dynamic content, e.g. a list of items that can be added or removed, or a multistep wizard. - -```html - - - -``` - -👉 Please note the preferred height options are ignored when scrolling inside ModalDialog is -[turned off](#disable-scrolling-inside-modaldialog). - -👉 Please note the custom height values are considered **preferred:** Modal will not expand beyond the viewport height. - -### Custom Max Height - -The default maximum height of Modal is: - -- viewport height minus 1100 spacing on mobile screens, and -- 600 px on tablet screens and up (shrunk if necessary). - -You can use the custom property `--modal-max-height-tablet` to override the max height on tablet screens and up: - -```html - - - -``` - -👉 Please note the max height is ignored when scrolling inside ModalDialog is [turned off](#disable-scrolling-inside-modaldialog). - -👉 Please note the max height on mobile screens is currently not customizable. Let us know if you need this feature! 🙏 - ## ModalDialog ModalDialog is the actual dialog window, a place for the header, body, and footer of the dialog. @@ -134,7 +84,7 @@ class. #### Expanded Variant -By default the docked dialog on mobile screens shrinks to fit the height of its content +By default, the docked dialog on mobile screens shrinks to fit the height of its content (if smaller than the viewport). Use the `ModalDialog--expandOnMobile` class to expand the dialog on mobile. ```html @@ -282,47 +232,87 @@ You can still close modal with close buttons or ESC key. ## Scrolling Long Content -When Modals become too long for the user's viewport or device, they scroll independently of the page itself. By default, -ModalBody has `overflow-y: auto` applied to it, so it scrolls vertically. +In case the content is longer than user's viewport or device, the ModalBody will expand to fit the height of its content +and the whole ModalDialog will scroll. + +### Enable Scrolling Inside ModalDialog + +Scrolling inside ModalDialog can be turned on by adding the `ModalDialog--scrollable` modifier class: + +```html +
+ +
+``` ### Scrolling with ScrollView -Alternatively, you can wrap the ModalBody content in a [ScrollView][scroll-view] to take over the responsibility for +Additionally, you can wrap the ModalBody content in a [ScrollView][scroll-view] to take over the responsibility for scrolling, e.g.: ```html -
-
-
-
- +
+ +
+
+
+
+ +
+
- -
+ + ``` -### Disable Scrolling Inside ModalDialog +### Custom Height + +By default, ModalDialog grows to the height of its content until it reaches the [maximum height](#custom-max-height) +limit. + +You can set a custom preferred height of ModalDialog using a custom property: + +- `--modal-preferred-height-mobile` for mobile screens, and +- `--modal-preferred-height-tablet` for tablet screens and up. -Scrolling inside ModalDialog can be turned off by adding the `ModalDialog--nonScrollable` modifier class: +This is useful for Modals with dynamic content, e.g. a list of items that can be added or removed, or a multistep wizard. ```html -
+
``` -This way, the ModalBody will expand to fit the height of its content and the whole ModalDialog will scroll in case the -content is longer than user's viewport. +⚠️ This feature is only available for ModalDialogs with the `ModalDialog--scrollable` modifier class. + +👉 Please note the custom height values are considered **preferred**. Scrollable ModalDialog will never expand beyond +the viewport height. See the [Custom Max Height](#custom-max-height) section for more information. + +### Custom Max Height -👉 Please note that this modifier class can produce unexpected results when used in combination with ScrollView. +The default maximum height of a scrollable ModalDialog is **600 px**, as long as it can fit the viewport. + +If the viewport is smaller, scrollable ModalDialog will shrink to fit the viewport. In such case, the ModalDialog height +will calculate as "viewport height (`100dvh`) minus 1100 spacing". + +You can use the custom property `--modal-max-height-tablet` to override the default maximum height limit on tablet +screens and up: + +```html +
+ +
+``` -#### ⚠️ DEPRECATION NOTICE +⚠️ This feature is only available for ModalDialogs with the `ModalDialog--scrollable` modifier class. -The `.ModalDialog--nonScrollable` modifier will be removed in the next major release and the ModalDialog will be made -non-scrollable by default. It will be possible to re-enable the inside scrolling by adding the -`.ModalDialog--scrollable` modifier class (which will remain the recommended default usage). +👉 If a [custom height](#custom-height) is set, the custom max height is only applied if it's smaller than the custom +height. ## Stacking Modals diff --git a/packages/web/src/scss/components/Modal/_Modal.scss b/packages/web/src/scss/components/Modal/_Modal.scss index 9698309e37..147f51314e 100644 --- a/packages/web/src/scss/components/Modal/_Modal.scss +++ b/packages/web/src/scss/components/Modal/_Modal.scss @@ -7,8 +7,6 @@ // 5. Allow scrolling through the modal. Has no effect unless the modal is taller than the viewport. // 6. Restore text selection after `all: unset`. -@use 'sass:map'; -@use '../../tools/breakpoint'; @use 'theme'; .Modal { @@ -20,7 +18,7 @@ z-index: 1; display: flex; // 1. padding-block: theme.$padding-y; - overflow: hidden; // 4. + overflow-y: auto; // 5. background: linear-gradient(#{theme.$backdrop-background-color}, #{theme.$backdrop-background-color}); // 2., 3. visibility: hidden; // 1. opacity: 0; // 1. @@ -38,8 +36,8 @@ } } -.Modal:has(.ModalDialog--nonScrollable) { - overflow-y: auto; // 5. +.Modal:has(.ModalDialog--scrollable) { + overflow: hidden; // 4. } .Modal--center, diff --git a/packages/web/src/scss/components/Modal/_ModalBody.scss b/packages/web/src/scss/components/Modal/_ModalBody.scss index bdc07da565..4f9a8a4c96 100644 --- a/packages/web/src/scss/components/Modal/_ModalBody.scss +++ b/packages/web/src/scss/components/Modal/_ModalBody.scss @@ -10,8 +10,8 @@ min-height: map.get(theme.$typography, mobile, font-size) * map.get(theme.$typography, mobile, line-height); // 1. padding-inline: theme.$common-padding-x; padding-block: theme.$body-padding-y; - overflow-x: var(--modal-body-overflow-x, hidden); - overflow-y: var(--modal-body-overflow-y, auto); + overflow-x: var(--modal-body-overflow-x, visible); + overflow-y: var(--modal-body-overflow-y, visible); overscroll-behavior: contain; @include breakpoint.up(map.get(theme.$breakpoints, tablet)) { diff --git a/packages/web/src/scss/components/Modal/_ModalDialog.scss b/packages/web/src/scss/components/Modal/_ModalDialog.scss index 312dcb7121..e0876e5288 100644 --- a/packages/web/src/scss/components/Modal/_ModalDialog.scss +++ b/packages/web/src/scss/components/Modal/_ModalDialog.scss @@ -24,8 +24,8 @@ margin-inline: auto; margin-top: var(--modal-top); margin-bottom: var(--modal-bottom); - overflow-x: var(--modal-body-overflow-x, hidden); - overflow-y: var(--modal-body-overflow-y, auto); + overflow-x: var(--modal-body-overflow-x, visible); + overflow-y: var(--modal-body-overflow-y, visible); color: theme.$dialog-text-color; border-radius: theme.$dialog-border-radius; background-color: theme.$dialog-background-color; @@ -34,11 +34,6 @@ transform-origin: var(--modal-transform-origin); overscroll-behavior: contain; - @include breakpoint.up(map.get(theme.$breakpoints, tablet)) { - height: theme.$dialog-height-tablet; - max-height: theme.$dialog-max-height-tablet; - } - @include breakpoint.up(map.get(theme.$breakpoints, desktop)) { width: theme.$dialog-width-desktop; } @@ -49,6 +44,19 @@ } } +.ModalDialog--scrollable { + --modal-body-overflow-x: hidden; + --modal-body-overflow-y: auto; + + height: theme.$dialog-scrollable-height; + max-height: theme.$dialog-scrollable-max-height; + + @include breakpoint.up(map.get(theme.$breakpoints, tablet)) { + height: theme.$dialog-scrollable-height-tablet; + max-height: theme.$dialog-scrollable-max-height-tablet; + } +} + .ModalDialog--dockOnMobile { @include breakpoint.down(map.get(theme.$breakpoints, tablet)) { --modal-top: auto; @@ -58,12 +66,17 @@ width: theme.$dialog-docked-width; max-width: none; - height: theme.$dialog-docked-height; - max-height: theme.$dialog-docked-expanded-height; border-radius: theme.$dialog-border-radius theme.$dialog-border-radius 0 0; } } +.ModalDialog--dockOnMobile.ModalDialog--scrollable { + @include breakpoint.down(map.get(theme.$breakpoints, tablet)) { + height: theme.$dialog-docked-scrollable-height; + max-height: theme.$dialog-docked-scrollable-max-height; + } +} + [open] > .ModalDialog--dockOnMobile { @include breakpoint.down(map.get(theme.$breakpoints, tablet)) { --modal-translate-y: 0; @@ -72,16 +85,6 @@ .ModalDialog--dockOnMobile.ModalDialog--expandOnMobile { @include breakpoint.down(map.get(theme.$breakpoints, tablet)) { - min-height: theme.$dialog-docked-expanded-height; + min-height: theme.$dialog-docked-expanded-min-height; } } - -// @deprecated The non-scrollable modal dialog is deprecated and will be removed in the next major release. -// Migration: In CSS, make the modal dialog non-scrollable by default so scrolling inside is turned on by a modifier class. -.ModalDialog--nonScrollable { - --modal-body-overflow-x: visible; - --modal-body-overflow-y: visible; - - height: auto; - max-height: none; -} diff --git a/packages/web/src/scss/components/Modal/_theme.scss b/packages/web/src/scss/components/Modal/_theme.scss index ff6c20eb07..904b678695 100644 --- a/packages/web/src/scss/components/Modal/_theme.scss +++ b/packages/web/src/scss/components/Modal/_theme.scss @@ -18,19 +18,31 @@ $common-padding-x-tablet: tokens.$space-800; // ModalDialog $dialog-width: 640px; $dialog-width-desktop: 680px; -$dialog-height: var(--modal-preferred-height-mobile, min-content); -$dialog-height-tablet: var(--modal-preferred-height-tablet, min-content); -$dialog-max-height: min(var(--modal-max-height-mobile, 600px), calc(100dvh - #{2 * $padding-y})); -$dialog-max-height-tablet: min(var(--modal-max-height-tablet, 600px), calc(100dvh - #{2 * $padding-y})); +$dialog-height: auto; +$dialog-max-height: none; $dialog-text-color: tokens.$text-primary-default; $dialog-border-radius: tokens.$radius-200; $dialog-background-color: tokens.$background-basic; $dialog-shadow: tokens.$shadow-300; +$dialog-scrollable-height: var(--modal-preferred-height-mobile, min-content); +$dialog-scrollable-height-tablet: var( + --modal-preferred-height-tablet, + var(--modal-preferred-height-mobile, min-content) +); +$dialog-scrollable-max-height: min(var(--modal-max-height-mobile, 600px), calc(100dvh - #{2 * $padding-y})); +$dialog-scrollable-max-height-tablet: min( + var(--modal-max-height-tablet, var(--modal-max-height-mobile, 600px)), + calc(100dvh - #{2 * $padding-y}) +); + $dialog-docked-width: 100%; -$dialog-docked-height: var(--modal-preferred-height-mobile, min-content); $dialog-docked-margin-top: tokens.$space-1100; -$dialog-docked-expanded-height: calc(100dvh - #{$dialog-docked-margin-top}); + +$dialog-docked-expanded-min-height: calc(100dvh - #{$dialog-docked-margin-top}); + +$dialog-docked-scrollable-height: var(--modal-preferred-height-mobile, min-content); +$dialog-docked-scrollable-max-height: $dialog-docked-expanded-min-height; // ModalHeader $header-gap: tokens.$space-400; diff --git a/packages/web/src/scss/components/Modal/index.html b/packages/web/src/scss/components/Modal/index.html index e9c22ee1dc..76cca445e2 100644 --- a/packages/web/src/scss/components/Modal/index.html +++ b/packages/web/src/scss/components/Modal/index.html @@ -38,7 +38,7 @@ } const toggleScrolling = (selector) => { - document.querySelector(selector).classList.toggle('ModalDialog--nonScrollable'); + document.querySelector(selector).classList.toggle('ModalDialog--scrollable'); } @@ -140,8 +140,8 @@

Modal Title

Expand on mobile (docked only) -
+
+ Optional description +
@@ -334,7 +347,7 @@

Modal with Custo type="button" class="Button Button--secondary Button--medium" data-spirit-dismiss="modal" - data-spirit-target="#example-custom-height" + data-spirit-target="#example-dropdown" > Secondary action @@ -351,6 +364,7 @@

Modal with Custo

+

Scrolling Long Content

@@ -394,6 +408,90 @@

+ +
+ + + {{setVar "blocks" 1 2 3 4 5 6 7 8 9 }} + {{#each @root.blocks}} +

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam at excepturi laudantium magnam mollitia + perferendis reprehenderit, voluptate. Cum delectus dicta ducimus eligendi excepturi natus perferendis + provident unde. Eveniet, iste, molestiae? +

+ {{/each}} + + +
+ + + +
+
+ + +
+
+ + + + + + + + + + + + + + +
+ + +
+

+ Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam at excepturi laudantium magnam mollitia perferendis reprehenderit, voluptate. Cum delectus dicta +

+ +
+ +
@@ -407,27 +505,7 @@

perferendis reprehenderit, voluptate. Cum delectus dicta ducimus eligendi excepturi natus perferendis provident unde. Eveniet, iste, molestiae?

-

- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam at excepturi laudantium magnam mollitia - perferendis reprehenderit, voluptate. Cum delectus dicta ducimus eligendi excepturi natus perferendis - provident unde. Eveniet, iste, molestiae? -

-

- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam at excepturi laudantium magnam mollitia - perferendis reprehenderit, voluptate. Cum delectus dicta ducimus eligendi excepturi natus perferendis - provident unde. Eveniet, iste, molestiae? -

-

- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam at excepturi laudantium magnam mollitia - perferendis reprehenderit, voluptate. Cum delectus dicta ducimus eligendi excepturi natus perferendis - provident unde. Eveniet, iste, molestiae? -

-

- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam at excepturi laudantium magnam mollitia - perferendis reprehenderit, voluptate. Cum delectus dicta ducimus eligendi excepturi natus perferendis - provident unde. Eveniet, iste, molestiae? -

-

+

Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam at excepturi laudantium magnam mollitia perferendis reprehenderit, voluptate. Cum delectus dicta ducimus eligendi excepturi natus perferendis provident unde. Eveniet, iste, molestiae? @@ -448,7 +526,7 @@

type="button" class="Button Button--primary Button--medium" data-spirit-dismiss="modal" - data-spirit-target="#example-long-content" + data-spirit-target="#example-non-scrolling-modal" > Primary action @@ -456,7 +534,7 @@

type="button" class="Button Button--secondary Button--medium" data-spirit-dismiss="modal" - data-spirit-target="#example-long-content" + data-spirit-target="#example-non-scrolling-modal" > Secondary action @@ -485,7 +563,7 @@

-
+
@@ -599,122 +677,35 @@

type="button" class="Button Button--primary Button--medium" data-spirit-toggle="modal" - data-spirit-target="#example-non-scrolling-modal" - aria-controls="example-non-scrolling-modal" + data-spirit-target="#example-custom-height" + aria-controls="example-custom-height" aria-expanded="false" > - Open Modal with Disabled Scrolling Inside + Open Modal with Custom Height - - - -
- - -
-

- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam at excepturi laudantium magnam mollitia perferendis reprehenderit, voluptate. Cum delectus dicta -

- -
- - - -
- -

- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam at excepturi laudantium magnam mollitia - perferendis reprehenderit, voluptate. Cum delectus dicta ducimus eligendi excepturi natus perferendis - provident unde. Eveniet, iste, molestiae? -

-

- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam at excepturi laudantium magnam mollitia - perferendis reprehenderit, voluptate. Cum delectus dicta ducimus eligendi excepturi natus perferendis - provident unde. Eveniet, iste, molestiae? -

-

- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam at excepturi laudantium magnam mollitia - perferendis reprehenderit, voluptate. Cum delectus dicta ducimus eligendi excepturi natus perferendis - provident unde. Eveniet, iste, molestiae? -

-

- Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam at excepturi laudantium magnam mollitia - perferendis reprehenderit, voluptate. Cum delectus dicta ducimus eligendi excepturi natus perferendis - provident unde. Eveniet, iste, molestiae? -

- -
- - - -
-
- - -
-
- - -
- - -
- - - - - - -
+
-

Modal Title

+

Modal with Custom Height

- -

+

+ This modal has a custom height of 500px set via the --modal-preferred-height-tablet CSS + custom property. +

+ +