Skip to content

Commit

Permalink
Feat(web): Introduce vertical alignment options for Modal #DS-940
Browse files Browse the repository at this point in the history
New alignment classes can be used: `.Modal--top`, `.Modal--center` (default),
and `.Modal--bottom`.
  • Loading branch information
adamkudrna committed Jan 15, 2024
1 parent b1d558b commit d8246b2
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 67 deletions.
32 changes: 22 additions & 10 deletions packages/web/src/scss/components/Modal/_Modal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
.Modal {
--modal-scale: #{theme.$transition-scale-ratio};
--modal-translate-x: -50%;
--modal-translate-y: #{theme.$transition-shift-distance};

all: unset;
position: fixed;
Expand Down Expand Up @@ -40,10 +39,6 @@
opacity: 0;
}

@include breakpoint.up(map.get(theme.$breakpoints, tablet)) {
--modal-translate-y: 50%;
}

@media (prefers-reduced-motion: no-preference) {
transition-property: visibility, opacity;
transition-duration: theme.$transition-duration;
Expand All @@ -55,9 +50,30 @@
}
}

.Modal--center,
.Modal:not(.Modal--top, .Modal--bottom) {
--modal-top: auto;
--modal-bottom: 50%;
--modal-translate-y: 50%;
--modal-transform-origin: center center;
}

.Modal--top {
--modal-top: 0;
--modal-bottom: auto;
--modal-translate-y: #{theme.$padding-y};
--modal-transform-origin: top center;
}

.Modal--bottom {
--modal-top: auto;
--modal-bottom: 0;
--modal-translate-y: #{-1 * theme.$padding-y};
--modal-transform-origin: bottom center;
}

.Modal[open] {
--modal-scale: 1;
--modal-translate-y: 0;

visibility: visible;
opacity: 1;
Expand All @@ -69,8 +85,4 @@
visibility: visible;
opacity: 1;
}

@include breakpoint.up(map.get(theme.$breakpoints, tablet)) {
--modal-translate-y: 50%;
}
}
113 changes: 58 additions & 55 deletions packages/web/src/scss/components/Modal/_ModalDialog.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,58 @@
// the tablet breakpoint.
// 2. Use ScrollView's backdoor to fix its height inside ModalDialog in Safari.
// 3. We need to set the box-sizing again because the parent element unsets styles using `all: unset`.
// 4. Suppress bottom alignment of the docked variant and use the alignment variants of `.Modal` instead.

@use 'sass:map';
@use '../../settings/feature-flags';
@use '../../tools/breakpoint';
@use '../../tools/typography';
@use 'theme';

@mixin -uniform-modal-dialog() {
--modal-translate-y: 50%;
@mixin -modal-dialog() {
@include typography.generate(theme.$typography);

--scroll-view-vertical-height: auto; // 2.

position: fixed;
top: var(--modal-top);
bottom: var(--modal-bottom);
left: 50%;
display: flex;
flex-direction: column;
box-sizing: border-box; // 3.
width: theme.$dialog-width;
overflow-x: hidden;
overflow-y: auto;
color: theme.$dialog-text-color;
background-color: theme.$dialog-background-color;
box-shadow: theme.$dialog-shadow;
transform: translate(var(--modal-translate-x), var(--modal-translate-y)) scale(var(--modal-scale));
overscroll-behavior: contain;
transform-origin: var(--modal-transform-origin);

@media (prefers-reduced-motion: no-preference) {
transition-property: bottom, width, height, max-height, border-radius, transform; // 1.
transition-duration: inherit;
}
}

bottom: 50%;
width: theme.$dialog-uniform-width;
max-width: calc(100% - #{theme.$padding-x});
height: theme.$dialog-uniform-height;
max-height: theme.$dialog-uniform-max-height;
border-radius: theme.$dialog-border-radius;
transform-origin: center center;
@mixin -uniform-modal-dialog($from-breakpoint) {
@include breakpoint.up($from-breakpoint) {
// 4.
@if $from-breakpoint == 0 {
--modal-top: unset;
--modal-bottom: unset;
--modal-translate-y: unset;
--modal-transform-origin: unset;
}

width: theme.$dialog-uniform-width;
max-width: calc(100% - #{theme.$padding-x});
height: theme.$dialog-uniform-height;
max-height: theme.$dialog-uniform-max-height;
border-radius: theme.$dialog-border-radius;
}

@include breakpoint.up(map.get(theme.$breakpoints, tablet)) {
height: theme.$dialog-height-tablet;
Expand All @@ -32,15 +67,20 @@

@mixin -docked-modal-dialog() {
@include breakpoint.down(map.get(theme.$breakpoints, tablet)) {
--modal-translate-y: 0;
--modal-top: auto;
--modal-bottom: 0;
--modal-translate-y: #{theme.$transition-shift-distance};
--modal-transform-origin: bottom center;

bottom: 0;
width: theme.$dialog-width;
max-width: none;
height: theme.$dialog-height;
max-height: theme.$dialog-max-height;
border-radius: theme.$dialog-border-radius theme.$dialog-border-radius 0 0;
transform-origin: bottom center;

[open] & {
--modal-translate-y: 0;
}
}
}

Expand All @@ -51,54 +91,17 @@
}

.ModalDialog {
@include typography.generate(theme.$typography);

--scroll-view-vertical-height: auto; // 2.

position: fixed;
bottom: 0;
left: 50%;
display: flex;
flex-direction: column;
box-sizing: border-box; // 3.
width: theme.$dialog-width;
height: theme.$dialog-height;
max-height: theme.$dialog-max-height;
overflow-x: hidden;
overflow-y: auto;
color: theme.$dialog-text-color;
border-radius: theme.$dialog-border-radius theme.$dialog-border-radius 0 0;
background-color: theme.$dialog-background-color;
box-shadow: theme.$dialog-shadow;
transform: translate(var(--modal-translate-x), var(--modal-translate-y)) scale(var(--modal-scale));
transform-origin: bottom center;
overscroll-behavior: contain;

@include breakpoint.up(map.get(theme.$breakpoints, tablet)) {
bottom: 50%;
width: theme.$dialog-width-tablet;
max-width: calc(100% - #{theme.$padding-x-tablet});
height: theme.$dialog-height-tablet;
max-height: theme.$dialog-max-height-tablet;
border-radius: theme.$dialog-border-radius;
transform-origin: center center;
}

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

// @deprecated The "uniform" dialog variant is deprecated and will be removed in the next major release.
// Migration:
// 1. Remove the feature flag and make the uniform dialog the default.
// 2. Adjust transitions below.
@if feature-flags.$modal-enable-uniform-dialog {
@include -uniform-modal-dialog();
}

@media (prefers-reduced-motion: no-preference) {
transition-property: bottom, width, border-radius, transform; // 1.
transition-duration: inherit;
@include -uniform-modal-dialog($from-breakpoint: map.get(theme.$breakpoints, mobile));
} @else {
@include -docked-modal-dialog();
@include -uniform-modal-dialog($from-breakpoint: map.get(theme.$breakpoints, tablet));
}
}

Expand All @@ -114,7 +117,7 @@
}
} @else {
.spirit-feature-modal-enable-uniform-dialog .ModalDialog {
@include -uniform-modal-dialog();
@include -uniform-modal-dialog($from-breakpoint: map.get(theme.$breakpoints, mobile));
}

.spirit-feature-modal-enable-uniform-dialog .ModalDialog--dockOnMobile {
Expand Down
2 changes: 1 addition & 1 deletion packages/web/src/scss/components/Modal/_theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
@use '../../settings/transitions';

$breakpoints: tokens.$breakpoints;
$padding: tokens.$space-600;
$padding-x: tokens.$space-700;
$padding-x-tablet: tokens.$space-1100;
$padding-y: tokens.$space-600;
$typography: tokens.$body-medium-text-regular;
$transition-duration: transitions.$duration-medium;
$transition-scale-ratio: transitions.$scale-ratio-large-objects;
Expand Down
27 changes: 26 additions & 1 deletion packages/web/src/scss/components/Modal/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,31 @@ <h2 id="example-basic-title" class="ModalHeader__title">Modal Title</h2>
perferendis reprehenderit, voluptate. Cum delectus dicta ducimus eligendi excepturi natus perferendis
provident unde. Eveniet, iste, molestiae?
</p>
<!-- Modal alignment demo: start -->
<script>
const setModalAlignment = (event) => {
const modalElement = document.querySelector('#example-basic');

modalElement.classList.remove('Modal--top', 'Modal--center', 'Modal--bottom');
modalElement.classList.add(`Modal--${event.target.value}`);
};
</script>
<form onchange="setModalAlignment(event)" class="d-none d-tablet-block mb-600">
<div>Modal alignment (from tablet up):</div>
<label for="modal_alignment_top" class="Radio mr-600">
<input type="radio" id="modal_alignment_top" name="modal_alignment" value="top" class="Radio__input" autocomplete="off" />
<span class="Radio__label">Top</span>
</label>
<label for="modal_alignment_center" class="Radio mr-600">
<input type="radio" id="modal_alignment_center" name="modal_alignment" value="center" class="Radio__input" autocomplete="off" checked />
<span class="Radio__label">Center</span>
</label>
<label for="modal_alignment_bottom" class="Radio mr-600">
<input type="radio" id="modal_alignment_bottom" name="modal_alignment" value="bottom" class="Radio__input" autocomplete="off" />
<span class="Radio__label">Bottom</span>
</label>
</form>
<!-- Modal alignment demo: end -->
<!-- Footer alignment demo: start -->
<script>
const setFooterAlignment = (event) => {
Expand Down Expand Up @@ -789,7 +814,7 @@ <h2 class="docs-Heading">Feature Flag: Uniform Modal on Mobile</h2>
</button>

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

<!-- ModalDialog: start -->
<article id="example-uniform-dialog" class="ModalDialog">
Expand Down

0 comments on commit d8246b2

Please sign in to comment.