Skip to content

Commit

Permalink
BREAKING CHANGE(web): Enhance custom height and max height options of…
Browse files Browse the repository at this point in the history
… `ModalDialog` #DS-1134

1. Custom height and custom max height can be set individually on all breakpoints now.
2. The `--modal-preferred-height-mobile` and `--modal-preferred-height-tablet` custom
   properties were renamed.
  • Loading branch information
adamkudrna committed May 16, 2024
1 parent cf7db9c commit 6c26337
Show file tree
Hide file tree
Showing 5 changed files with 273 additions and 23 deletions.
11 changes: 11 additions & 0 deletions docs/migrations/web/MIGRATION-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,17 @@ to the `.ModalDialog` element.

- `.ModalDialog``.ModalDialog .ModalDialog--scrollable`

### Modal: Custom Height

The `--modal-preferred-height-mobile` and `--modal-preferred-height-tablet` custom properties were renamed.

#### Migration Guide

Update the custom properties in your project to use the new names:

- `--modal-preferred-height-mobile``--modal-height`
- `--modal-preferred-height-tablet``--modal-height-tablet`

### Modal: Uniform Variant Feature Flag

The feature flag enabling the uniform variant of modal was removed and the
Expand Down
27 changes: 21 additions & 6 deletions packages/web/src/scss/components/Modal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -274,15 +274,20 @@ 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.
- `--modal-height` for mobile screens and up,
- `--modal-height-tablet` for tablet screens and up.
- `--modal-height-desktop` for desktop screens and up.

The custom properties fall back to the previous breakpoint using the mobile-first approach. For example, if you set
`--modal-height-tablet` while leaving `--modal-height-desktop` unset, the value will be used for
both tablet and desktop screens.

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
<article
class="ModalDialog ModalDialog--scrollable"
style="--modal-preferred-height-mobile: 400px; --modal-preferred-height-tablet: 500px;"
style="--modal-height: 400px; --modal-height-tablet: 500px; --modal-height-desktop: 600px;"
>
<!---->
</article>
Expand All @@ -300,11 +305,21 @@ The default maximum height of a scrollable ModalDialog is **600 px**, as long as
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:
You can set a custom preferred height of ModalDialog using a custom property:

- `--modal-max-height` for mobile screens and up,
- `--modal-max-height-tablet` for tablet screens and up.
- `--modal-max-height-desktop` for desktop screens and up.

The custom properties fall back to the previous breakpoint using the mobile-first approach. For example, if you set
`--modal-max-height-tablet` while leaving `--modal-max-height-desktop` unset, the value will be used for both tablet and
desktop screens.

```html
<article class="ModalDialog ModalDialog--scrollable" style="--modal-max-height-tablet: 400px">
<article
class="ModalDialog ModalDialog--scrollable"
style="--modal-max-height: 300px; --modal-max-height-tablet: 400px; --modal-max-height-desktop: 500px;"
>
<!---->
</article>
```
Expand Down
5 changes: 5 additions & 0 deletions packages/web/src/scss/components/Modal/_ModalDialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@
height: theme.$dialog-scrollable-height-tablet;
max-height: theme.$dialog-scrollable-max-height-tablet;
}

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

.ModalDialog--dockOnMobile {
Expand Down
29 changes: 23 additions & 6 deletions packages/web/src/scss/components/Modal/_theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,31 @@ $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-default-height: min-content;
$_dialog-scrollable-default-max-height: 600px;

$dialog-scrollable-height: var(--modal-height, #{$_dialog-scrollable-default-height});
$dialog-scrollable-height-tablet: var(
--modal-preferred-height-tablet,
var(--modal-preferred-height-mobile, min-content)
--modal-height-tablet,
var(--modal-height, #{$_dialog-scrollable-default-height})
);
$dialog-scrollable-height-desktop: var(
--modal-height-desktop,
var(--modal-height-tablet, var(--modal-height, #{$_dialog-scrollable-default-height}))
);
$dialog-scrollable-max-height: min(
var(--modal-max-height, #{$_dialog-scrollable-default-max-height}),
calc(100dvh - #{2 * $padding-y})
);
$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)),
var(--modal-max-height-tablet, var(--modal-max-height, #{$_dialog-scrollable-default-max-height})),
calc(100dvh - #{2 * $padding-y})
);
$dialog-scrollable-max-height-desktop: min(
var(
--modal-max-height-desktop,
var(--modal-max-height-tablet, var(--modal-max-height, #{$_dialog-scrollable-default-max-height}))
),
calc(100dvh - #{2 * $padding-y})
);

Expand All @@ -41,7 +58,7 @@ $dialog-docked-margin-top: tokens.$space-1100;

$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-height: var(--modal-height, #{$_dialog-scrollable-default-height});
$dialog-docked-scrollable-max-height: $dialog-docked-expanded-min-height;

// ModalHeader
Expand Down
224 changes: 213 additions & 11 deletions packages/web/src/scss/components/Modal/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ <h2 id="example-scroll-view-title" class="ModalHeader__title">
<!-- ModalDialog: start -->
<article
class="ModalDialog ModalDialog--scrollable"
style="--modal-preferred-height-mobile: 400px; --modal-preferred-height-tablet: 500px"
style="--modal-height: 400px; --modal-height-tablet: 500px; --modal-height-desktop: 600px"
>

<!-- ModalHeader: start -->
Expand All @@ -719,16 +719,218 @@ <h2 id="example-custom-height-title" class="ModalHeader__title">Modal with Custo
<!-- ModalBody: start -->
<div class="ModalBody">
<!-- Content: start -->
<p class="d-tablet-none">
This modal has a custom height of <code>400px</code> set via the <code>--modal-preferred-height-mobile</code> CSS
custom property.
</p>
<p class="d-none d-tablet-block">
This modal has a custom height of <code>500px</code> set via the <code>--modal-preferred-height-tablet</code> CSS
custom property.
</p>
<!-- TODO: add a checkbox "show more content to force scrolling" -->
<!-- TODO: add text fields to manually set values of available custom properties -->
<!-- Modal custom height demo: start -->
<script>
const toggleCustomHeight = (event, selector, breakpoint) => {
const isCustomHeightEnabled = event.target.checked;

const modalElement = document.querySelector(selector);
const modalHeightInputElement = document.querySelector(`#custom-height-${breakpoint}`);
const modalHeightValueElement = document.querySelector(`#custom-height-${breakpoint}-value`);
const modalMaxHeightInputElement = document.querySelector(`#custom-max-height-${breakpoint}`);
const modalMaxHeightValueElement = document.querySelector(`#custom-max-height-${breakpoint}-value`);

if (isCustomHeightEnabled) {
modalElement.style.setProperty(`--modal-height-${breakpoint}`, `${modalHeightInputElement.value}px`);
modalElement.style.setProperty(`--modal-max-height-${breakpoint}`, `${modalMaxHeightInputElement.value}px`);
modalHeightInputElement.disabled = false;
modalHeightValueElement.textContent = `${modalHeightInputElement.value} px`;
modalMaxHeightInputElement.disabled = false;
modalMaxHeightValueElement.textContent = `${modalMaxHeightInputElement.value} px`;
} else {
modalElement.style.setProperty(`--modal-height-${breakpoint}`, 'unset');
modalElement.style.setProperty(`--modal-max-height-${breakpoint}`, 'unset');
modalHeightInputElement.disabled = true;
modalHeightValueElement.textContent = '—';
modalMaxHeightInputElement.disabled = true;
modalMaxHeightValueElement.textContent = '—';
}
};

const setModalHeight = (event, selector, breakpoint) => {
const modalElement = document.querySelector(selector);
const modalHeightValueElement = document.querySelector(`#custom-height-${breakpoint}-value`);

modalElement.style.setProperty(`--modal-height-${breakpoint}`, `${event.target.value}px`);
modalHeightValueElement.textContent = `${event.target.value} px`;
};

const setModalMaxHeight = (event, selector, breakpoint) => {
const modalElement = document.querySelector(selector);
const modalHeightValueElement = document.querySelector(`#custom-max-height-${breakpoint}-value`);

modalElement.style.setProperty(`--modal-max-height-${breakpoint}`, `${event.target.value}px`);
modalHeightValueElement.textContent = `${event.target.value} px`;
};
</script>
<form>
<fieldset class="Stack Stack--hasSpacing mb-800" style="border: 0;">
<legend hidden>Mobile</legend>
<label for="custom-height-mobile-enabled" class="Checkbox">
<input
type="checkbox"
id="custom-height-mobile-enabled"
class="Checkbox__input"
onchange="toggleCustomHeight(event, '#example-custom-height > .ModalDialog', 'mobile')"
checked autocomplete="off"
/>
<span class="Checkbox__text">
<span class="Checkbox__label">Mobile</span>
</span>
</label>
<div class="Grid" style="column-gap: var(--spirit-space-600)">
<label for="custom-height-mobile" class="GridItem" style="--grid-item-column-start: 1; --grid-item-column-end: 6; --grid-item-column-end-tablet: 4;">
Height
</label>
<span id="custom-height-mobile-value" class="GridItem" style="--grid-item-column-start: 6; --grid-item-column-end: 13; --grid-item-column-start-tablet: 4; --grid-item-column-end-tablet: 7;">
400 px
</span>
<input
type="range"
id="custom-height-mobile"
class="GridItem"
style="--grid-item-column-start: 1; --grid-item-column-end: 13; --grid-item-column-start-tablet: 7;"
onchange="setModalHeight(event, '#example-custom-height > .ModalDialog', 'mobile')"
min="200"
max="1000"
step="100"
value="400"
autocomplete="off"
/>
</div>
<div class="Grid" style="column-gap: var(--spirit-space-600)">
<label for="custom-max-height-mobile" class="GridItem" style="--grid-item-column-start: 1; --grid-item-column-end: 6; --grid-item-column-end-tablet: 4;">
Max height
</label>
<span id="custom-max-height-mobile-value" class="GridItem" style="--grid-item-column-start: 6; --grid-item-column-end: 13; --grid-item-column-start-tablet: 4; --grid-item-column-end-tablet: 7;">
600 px
</span>
<input
type="range"
id="custom-max-height-mobile"
class="GridItem"
style="--grid-item-column-start: 1; --grid-item-column-end: 13; --grid-item-column-start-tablet: 7;"
onchange="setModalMaxHeight(event, '#example-custom-height > .ModalDialog', 'mobile')"
min="200"
max="1000"
step="100"
value="600"
autocomplete="off"
/>
</div>
</fieldset>
<fieldset class="Stack Stack--hasSpacing d-none d-tablet-grid mb-tablet-800" style="border: 0;">
<legend hidden>Tablet</legend>
<label for="custom-height-tablet-enabled" class="Checkbox">
<input
type="checkbox"
id="custom-height-tablet-enabled"
class="Checkbox__input"
onchange="toggleCustomHeight(event, '#example-custom-height > .ModalDialog', 'tablet')"
checked autocomplete="off"
/>
<span class="Checkbox__text">
<span class="Checkbox__label">Tablet</span>
</span>
</label>
<div class="Grid" style="column-gap: var(--spirit-space-600)">
<label for="custom-height-tablet" class="GridItem" style="--grid-item-column-start: 1; --grid-item-column-end: 6; --grid-item-column-end-tablet: 4;">
Height
</label>
<span id="custom-height-tablet-value" class="GridItem" style="--grid-item-column-start: 6; --grid-item-column-end: 13; --grid-item-column-start-tablet: 4; --grid-item-column-end-tablet: 7;">
500 px
</span>
<input
type="range"
id="custom-height-tablet"
class="GridItem"
style="--grid-item-column-start: 1; --grid-item-column-end: 13; --grid-item-column-start-tablet: 7;"
onchange="setModalHeight(event, '#example-custom-height > .ModalDialog', 'tablet')"
min="200"
max="1000"
step="100"
value="500"
autocomplete="off"
/>
</div>
<div class="Grid" style="column-gap: var(--spirit-space-600)">
<label for="custom-max-height-tablet" class="GridItem" style="--grid-item-column-start: 1; --grid-item-column-end: 6; --grid-item-column-end-tablet: 4;">
Max height
</label>
<span id="custom-max-height-tablet-value" class="GridItem" style="--grid-item-column-start: 6; --grid-item-column-end: 13; --grid-item-column-start-tablet: 4; --grid-item-column-end-tablet: 7;">
600 px
</span>
<input
type="range"
id="custom-max-height-tablet"
class="GridItem"
style="--grid-item-column-start: 1; --grid-item-column-end: 13; --grid-item-column-start-tablet: 7;"
onchange="setModalMaxHeight(event, '#example-custom-height > .ModalDialog', 'tablet')"
min="200"
max="1000"
step="100"
value="600"
autocomplete="off"
/>
</div>
</fieldset>
<fieldset class="Stack Stack--hasSpacing d-none d-desktop-grid" style="border: 0;">
<legend hidden>Desktop</legend>
<label for="custom-height-desktop-enabled" class="Checkbox">
<input
type="checkbox"
id="custom-height-desktop-enabled"
class="Checkbox__input"
onchange="toggleCustomHeight(event, '#example-custom-height > .ModalDialog', 'desktop')"
checked autocomplete="off"
/>
<span class="Checkbox__text">
<span class="Checkbox__label">Desktop</span>
</span>
</label>
<div class="Grid" style="column-gap: var(--spirit-space-600)">
<label for="custom-height-desktop" class="GridItem" style="--grid-item-column-start: 1; --grid-item-column-end: 6; --grid-item-column-end-tablet: 4;">
Height
</label>
<span id="custom-height-desktop-value" class="GridItem" style="--grid-item-column-start: 6; --grid-item-column-end: 13; --grid-item-column-start-tablet: 4; --grid-item-column-end-tablet: 7;">
600 px
</span>
<input
type="range"
id="custom-height-desktop"
class="GridItem"
style="--grid-item-column-start: 1; --grid-item-column-end: 13; --grid-item-column-start-tablet: 7;"
onchange="setModalHeight(event, '#example-custom-height > .ModalDialog', 'desktop')"
min="200"
max="1000"
step="100"
value="600"
autocomplete="off"
/>
</div>
<div class="Grid" style="column-gap: var(--spirit-space-600)">
<label for="custom-max-height-desktop" class="GridItem" style="--grid-item-column-start: 1; --grid-item-column-end: 6; --grid-item-column-end-tablet: 4;">
Max height
</label>
<span id="custom-max-height-desktop-value" class="GridItem" style="--grid-item-column-start: 6; --grid-item-column-end: 13; --grid-item-column-start-tablet: 4; --grid-item-column-end-tablet: 7;">
600 px
</span>
<input
type="range"
id="custom-max-height-desktop"
class="GridItem"
style="--grid-item-column-start: 1; --grid-item-column-end: 13; --grid-item-column-start-tablet: 7;"
onchange="setModalMaxHeight(event, '#example-custom-height > .ModalDialog', 'desktop')"
min="200"
max="1000"
step="100"
value="600"
autocomplete="off"
/>
</div>
</fieldset>
</form>
<!-- Modal custom height demo: end -->
<!-- Content: end -->
</div>
<!-- ModalBody: end -->
Expand Down

0 comments on commit 6c26337

Please sign in to comment.