Skip to content

Commit

Permalink
fixup! fixup! Feat(web): Introduce option to disable scrolling inside…
Browse files Browse the repository at this point in the history
… `Modal` #DS-732
  • Loading branch information
adamkudrna committed Feb 3, 2024
1 parent 42b53cb commit a7c761f
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 51 deletions.
19 changes: 14 additions & 5 deletions packages/web/src/scss/components/Modal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ This is useful for Modals with dynamic content, e.g. a list of items that can be
</dialog>
```

👉 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
Expand All @@ -82,7 +85,7 @@ You can use the custom property `--modal-max-height-tablet` to override the max
</dialog>
```

👉 Please note the max height is ignored when scrolling inside ModalDialog is [turned off](#non-scrolling-modal-dialog).
👉 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! 🙏

Expand Down Expand Up @@ -282,20 +285,26 @@ scrolling, e.g.:
</div>
```

### Non-Scrolling Modal Dialog
### Disable Scrolling Inside ModalDialog

Scrolling inside ModalDialog can be turned off by adding the `ModalDialog--nonScrolling` modifier class:
Scrolling inside ModalDialog can be turned off by adding the `ModalDialog--nonScrollable` modifier class:

```html
<article class="ModalDialog ModalDialog--nonScrolling">
<article class="ModalDialog ModalDialog--nonScrollable">
<!---->
</article>
```

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.

👉 Please note that this modifier class can produce unexpected results when used with ScrollView.
👉 Please note that this modifier class can produce unexpected results when used in combination with ScrollView.

#### ⚠️ DEPRECATION NOTICE

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).

## Stacking Modals

Expand Down
75 changes: 34 additions & 41 deletions packages/web/src/scss/components/Modal/_ModalDialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// 5. Unfortunately, the open state cannot be part of the parent `-docked-modal-dialog()` mixin because it's not
// possible to generate selector for the feature class scenario.
// 6. Override bottom padding of parent `.Modal` in the docked variant.
// 7. Override the min-height of the expanded docked variant.

@use 'sass:map';
@use '../../settings/feature-flags';
Expand Down Expand Up @@ -53,20 +54,29 @@
width: theme.$dialog-uniform-width;
max-width: calc(100% - #{theme.$padding-x});
height: theme.$dialog-uniform-height;
max-height: theme.$dialog-uniform-max-height;
min-height: unset; // 7. @deprecated Can be removed once the uniform modal dialog has been made default.
border-radius: theme.$dialog-border-radius;
}

@include breakpoint.up(map.get(theme.$breakpoints, tablet)) {
height: theme.$dialog-uniform-height;
max-height: theme.$dialog-uniform-max-height-tablet;
height: theme.$dialog-uniform-height-tablet;
}

@include breakpoint.up(map.get(theme.$breakpoints, desktop)) {
width: theme.$dialog-width-desktop;
}
}

@mixin -scrollable-uniform-modal-dialog($from-breakpoint) {
@if $from-breakpoint == 0 {
max-height: theme.$dialog-uniform-max-height;
}

@include breakpoint.up(map.get(theme.$breakpoints, tablet)) {
max-height: theme.$dialog-uniform-max-height-tablet;
}
}

@mixin -docked-modal-dialog() {
@include breakpoint.down(map.get(theme.$breakpoints, tablet)) {
--modal-top: auto;
Expand All @@ -77,7 +87,6 @@
width: theme.$dialog-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;
}
}
Expand All @@ -91,24 +100,21 @@

@mixin -expand-docked-modal-dialog() {
@include breakpoint.down(map.get(theme.$breakpoints, tablet)) {
height: theme.$dialog-docked-expanded-height;
min-height: theme.$dialog-docked-expanded-height;
}
}

@mixin -non-scrolling-modal-dialog() {
max-height: none;
}

@mixin -non-scrolling-docked-modal-dialog() {
@mixin -scrollable-docked-modal-dialog() {
@include breakpoint.down(map.get(theme.$breakpoints, tablet)) {
height: theme.$dialog-docked-height;
max-height: theme.$dialog-docked-expanded-height;
}
}

@mixin -non-scrolling-docked-expanded-modal-dialog() {
@include breakpoint.down(map.get(theme.$breakpoints, tablet)) {
min-height: theme.$dialog-docked-expanded-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.
@mixin -non-scrollable-modal-dialog() {
height: auto;
max-height: none;
}

.ModalDialog {
Expand All @@ -118,20 +124,19 @@
// Migration: Remove the feature flag and make the uniform dialog the default.
@if feature-flags.$modal-enable-uniform-dialog {
@include -uniform-modal-dialog($from-breakpoint: map.get(theme.$breakpoints, mobile));
@include -scrollable-uniform-modal-dialog($from-breakpoint: map.get(theme.$breakpoints, mobile));
} @else {
@include -docked-modal-dialog();
@include -scrollable-docked-modal-dialog();
@include -uniform-modal-dialog($from-breakpoint: map.get(theme.$breakpoints, tablet));
@include -scrollable-uniform-modal-dialog($from-breakpoint: map.get(theme.$breakpoints, tablet));

[open] > & {
@include -open-docked-modal-dialog();
}
}
}

.ModalDialog--nonScrolling {
@include -non-scrolling-modal-dialog();
}

// @deprecated The "uniform" dialog variant is deprecated and will be removed in the next major release.
// Migration: Remove the feature flag and make the uniform dialog the default.
@if feature-flags.$modal-enable-uniform-dialog {
Expand All @@ -147,26 +152,18 @@
@include -expand-docked-modal-dialog();
}

.ModalDialog--dockOnMobile.ModalDialog--nonScrolling {
@include -non-scrolling-modal-dialog();
@include -non-scrolling-docked-modal-dialog();
}

// stylelint-disable-next-line selector-max-class -- Only target the expanded docked variant.
.ModalDialog--dockOnMobile.ModalDialog--expandOnMobile.ModalDialog--nonScrolling {
@include -non-scrolling-docked-expanded-modal-dialog();
.ModalDialog--nonScrollable {
@include -non-scrollable-modal-dialog();
}
} @else {
.spirit-feature-modal-enable-uniform-dialog .ModalDialog {
@include -uniform-modal-dialog($from-breakpoint: map.get(theme.$breakpoints, mobile));
@include -scrollable-uniform-modal-dialog($from-breakpoint: map.get(theme.$breakpoints, mobile));
}

.spirit-feature-modal-enable-uniform-dialog .ModalDialog--dockOnMobile {
@include -docked-modal-dialog();
}

.spirit-feature-modal-enable-uniform-dialog .ModalDialog--nonScrolling {
@include -non-scrolling-modal-dialog();
@include -scrollable-docked-modal-dialog();
}

.spirit-feature-modal-enable-uniform-dialog [open] > .ModalDialog--dockOnMobile {
Expand All @@ -178,16 +175,12 @@
.spirit-feature-modal-enable-uniform-dialog .ModalDialog--dockOnMobile.ModalDialog--expandOnMobile {
@include -expand-docked-modal-dialog();
}
// stylelint-enable selector-max-class

.ModalDialog--nonScrolling,
.spirit-feature-modal-enable-uniform-dialog .ModalDialog--dockOnMobile.ModalDialog--nonScrolling {
@include -non-scrolling-docked-modal-dialog();
}

.ModalDialog--expandOnMobile.ModalDialog--nonScrolling,
.spirit-feature-modal-enable-uniform-dialog
.ModalDialog--dockOnMobile.ModalDialog--expandOnMobile.ModalDialog--nonScrolling {
@include -non-scrolling-docked-expanded-modal-dialog();
// @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,
.spirit-feature-modal-enable-uniform-dialog .ModalDialog--nonScrollable {
@include -non-scrollable-modal-dialog();
}
// stylelint-enable selector-max-class
}
1 change: 1 addition & 0 deletions packages/web/src/scss/components/Modal/_theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ $dialog-shadow: tokens.$shadow-300;
// Migration: Rename the variables containing the `uniform` keyword to remove it.
$dialog-uniform-width: 640px;
$dialog-uniform-height: var(--modal-preferred-height-mobile, min-content);
$dialog-uniform-height-tablet: var(--modal-preferred-height-tablet, min-content);
$dialog-uniform-max-height: min(var(--modal-max-height-mobile, 600px), calc(100dvh - #{2 * $padding-y}));
$dialog-uniform-max-height-tablet: min(var(--modal-max-height-tablet, 600px), calc(100dvh - #{2 * $padding-y}));

Expand Down
10 changes: 5 additions & 5 deletions packages/web/src/scss/components/Modal/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
}

const toggleScrolling = (selector) => {
document.querySelector(selector).classList.toggle('ModalDialog--nonScrolling');
document.querySelector(selector).classList.toggle('ModalDialog--nonScrollable');
}
</script>

Expand Down Expand Up @@ -580,14 +580,14 @@ <h2 id="example-scroll-view-title" class="ModalHeader__title">
aria-controls="example-non-scrolling-modal"
aria-expanded="false"
>
Open Non-Scrolling Modal
Open Modal with Disabled Scrolling Inside
</button>

<!-- Modal: start -->
<dialog id="example-non-scrolling-modal" class="Modal Modal--center" aria-labelledby="example-non-scrolling-modal-title">

<!-- ModalDialog: start -->
<article class="ModalDialog ModalDialog--nonScrolling">
<article class="ModalDialog ModalDialog--nonScrollable">

<!-- ModalHeader: start -->
<header class="ModalHeader">
Expand Down Expand Up @@ -991,9 +991,9 @@ <h2 id="example-uniform-title" class="ModalHeader__title">Modal Title</h2>
</span>
</label>
<label for="modal-uniform-non-scrolling" class="Checkbox">
<input type="checkbox" id="modal-uniform-non-scrolling" class="Checkbox__input" onchange="toggleScrolling('#example-uniform-dialog')" autocomplete="off" />
<input type="checkbox" id="modal-uniform-non-scrolling" class="Checkbox__input" onchange="toggleScrolling('#example-uniform-dialog')" autocomplete="off" checked />
<span class="Checkbox__text">
<span class="Checkbox__label">Non-scrolling body</span>
<span class="Checkbox__label">Scrolling inside</span>
</span>
</label>
</form>
Expand Down

0 comments on commit a7c761f

Please sign in to comment.