diff --git a/packages/web/src/scss/components/Modal/_Modal.scss b/packages/web/src/scss/components/Modal/_Modal.scss index 18da28ca02..ba166b8425 100644 --- a/packages/web/src/scss/components/Modal/_Modal.scss +++ b/packages/web/src/scss/components/Modal/_Modal.scss @@ -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; @@ -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; @@ -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; @@ -69,8 +85,4 @@ visibility: visible; opacity: 1; } - - @include breakpoint.up(map.get(theme.$breakpoints, tablet)) { - --modal-translate-y: 50%; - } } diff --git a/packages/web/src/scss/components/Modal/_ModalDialog.scss b/packages/web/src/scss/components/Modal/_ModalDialog.scss index 125a4ee2b1..5574198a07 100644 --- a/packages/web/src/scss/components/Modal/_ModalDialog.scss +++ b/packages/web/src/scss/components/Modal/_ModalDialog.scss @@ -2,6 +2,7 @@ // 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'; @@ -9,16 +10,50 @@ @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; @@ -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; + } } } @@ -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)); } } @@ -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 { diff --git a/packages/web/src/scss/components/Modal/_theme.scss b/packages/web/src/scss/components/Modal/_theme.scss index e20fb18e15..3f24094c78 100644 --- a/packages/web/src/scss/components/Modal/_theme.scss +++ b/packages/web/src/scss/components/Modal/_theme.scss @@ -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; diff --git a/packages/web/src/scss/components/Modal/index.html b/packages/web/src/scss/components/Modal/index.html index d55782cbbf..1eabfe38e2 100644 --- a/packages/web/src/scss/components/Modal/index.html +++ b/packages/web/src/scss/components/Modal/index.html @@ -50,6 +50,31 @@