feat(modal): add static backdrop behaviour when using ionic theme (#29932)
Issue number: internal --------- <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. --> ## What is the current behavior? The modal's backdrop opacity changes dynamically according to the current breakpoint, independently of what theme is being used. ## What is the new behavior? - The modal's backdrop opacity is now static once it has finished entering the screen and while dragging the modal's handle. ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change: 1. Describe the impact and migration path for existing applications below. 2. Update the BREAKING.md file with the breaking change. 3. Add "BREAKING CHANGE: [...]" to the commit description when merging. See https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer for more information. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. -->
@ -4,7 +4,7 @@ import type { ModalAnimationOptions } from '../modal-interface';
|
||||
import { getBackdropValueForSheet } from '../utils';
|
||||
|
||||
export const createSheetEnterAnimation = (opts: ModalAnimationOptions) => {
|
||||
const { currentBreakpoint, backdropBreakpoint } = opts;
|
||||
const { currentBreakpoint, backdropBreakpoint, staticBackdropOpacity } = opts;
|
||||
|
||||
/**
|
||||
* If the backdropBreakpoint is undefined, then the backdrop
|
||||
@ -12,7 +12,9 @@ export const createSheetEnterAnimation = (opts: ModalAnimationOptions) => {
|
||||
* current breakpoint, then the backdrop should be fading in.
|
||||
*/
|
||||
const shouldShowBackdrop = backdropBreakpoint === undefined || backdropBreakpoint < currentBreakpoint!;
|
||||
const initialBackdrop = shouldShowBackdrop ? `calc(var(--backdrop-opacity) * ${currentBreakpoint!})` : '0';
|
||||
const initialBackdrop = shouldShowBackdrop
|
||||
? `calc(var(--backdrop-opacity) * ${staticBackdropOpacity ? 1 : currentBreakpoint!})`
|
||||
: '0';
|
||||
|
||||
const backdropAnimation = createAnimation('backdropAnimation').fromTo('opacity', 0, initialBackdrop);
|
||||
|
||||
|
@ -51,18 +51,19 @@ export const createSheetGesture = (
|
||||
breakpoints: number[] = [],
|
||||
getCurrentBreakpoint: () => number,
|
||||
onDismiss: () => void,
|
||||
onBreakpointChange: (breakpoint: number) => void
|
||||
onBreakpointChange: (breakpoint: number) => void,
|
||||
staticBackdropOpacity: boolean
|
||||
) => {
|
||||
// Defaults for the sheet swipe animation
|
||||
const defaultBackdrop = [
|
||||
{ offset: 0, opacity: 'var(--backdrop-opacity)' },
|
||||
{ offset: 1, opacity: 0.01 },
|
||||
{ offset: 1, opacity: staticBackdropOpacity ? 'var(--backdrop-opacity)' : 0.01 },
|
||||
];
|
||||
|
||||
const customBackdrop = [
|
||||
{ offset: 0, opacity: 'var(--backdrop-opacity)' },
|
||||
{ offset: 1 - backdropBreakpoint, opacity: 0 },
|
||||
{ offset: 1, opacity: 0 },
|
||||
{ offset: 1 - backdropBreakpoint, opacity: staticBackdropOpacity ? 'var(--backdrop-opacity)' : 0 },
|
||||
{ offset: 1, opacity: staticBackdropOpacity ? 'var(--backdrop-opacity)' : 0 },
|
||||
];
|
||||
|
||||
const SheetDefaults = {
|
||||
@ -312,14 +313,15 @@ export const createSheetGesture = (
|
||||
backdropAnimation.keyframes([
|
||||
{
|
||||
offset: 0,
|
||||
opacity: `calc(var(--backdrop-opacity) * ${getBackdropValueForSheet(
|
||||
1 - breakpointOffset,
|
||||
backdropBreakpoint
|
||||
)})`,
|
||||
opacity: staticBackdropOpacity
|
||||
? 'var(--backdrop-opacity)'
|
||||
: `calc(var(--backdrop-opacity) * ${getBackdropValueForSheet(1 - breakpointOffset, backdropBreakpoint)})`,
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
opacity: `calc(var(--backdrop-opacity) * ${getBackdropValueForSheet(snapToBreakpoint, backdropBreakpoint)})`,
|
||||
opacity: staticBackdropOpacity
|
||||
? 'var(--backdrop-opacity)'
|
||||
: `calc(var(--backdrop-opacity) * ${getBackdropValueForSheet(snapToBreakpoint, backdropBreakpoint)})`,
|
||||
},
|
||||
]);
|
||||
|
||||
|
@ -27,6 +27,7 @@ export interface ModalAnimationOptions {
|
||||
presentingEl?: HTMLElement;
|
||||
currentBreakpoint?: number;
|
||||
backdropBreakpoint?: number;
|
||||
staticBackdropOpacity?: boolean;
|
||||
}
|
||||
|
||||
export interface ModalBreakpointChangeEventDetail {
|
||||
|
@ -7,7 +7,7 @@
|
||||
:host {
|
||||
--background: #{globals.$ionic-color-base-white};
|
||||
--box-shadow: #{globals.$ionic-elevation-300};
|
||||
--backdrop-opacity: 1;
|
||||
--backdrop-opacity: 0.7;
|
||||
|
||||
color: globals.$ionic-color-neutral-1200;
|
||||
}
|
||||
|
@ -573,6 +573,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
presentingEl: presentingElement,
|
||||
currentBreakpoint: this.initialBreakpoint,
|
||||
backdropBreakpoint: this.backdropBreakpoint,
|
||||
staticBackdropOpacity: getIonTheme(this) === 'ionic',
|
||||
});
|
||||
|
||||
/* tslint:disable-next-line */
|
||||
@ -679,6 +680,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
presentingEl: this.presentingElement,
|
||||
currentBreakpoint: initialBreakpoint,
|
||||
backdropBreakpoint,
|
||||
staticBackdropOpacity: getIonTheme(this) === 'ionic',
|
||||
}));
|
||||
|
||||
ani.progressStart(true, 1);
|
||||
@ -698,7 +700,8 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
this.currentBreakpoint = breakpoint;
|
||||
this.ionBreakpointDidChange.emit({ breakpoint });
|
||||
}
|
||||
}
|
||||
},
|
||||
getIonTheme(this) === 'ionic'
|
||||
);
|
||||
|
||||
this.gesture = gesture;
|
||||
@ -1044,10 +1047,17 @@ interface ModalOverlayOptions {
|
||||
*/
|
||||
currentBreakpoint?: number;
|
||||
/**
|
||||
* The point after which the backdrop will being
|
||||
* The point after which the backdrop will begin
|
||||
* to fade in when using a sheet modal.
|
||||
*/
|
||||
backdropBreakpoint: number;
|
||||
/**
|
||||
* Defines whether the backdrop should have a
|
||||
* static opacity = var(--backdrop-opacity).
|
||||
* This option is true only when the widget
|
||||
* is using the ionic theme.
|
||||
*/
|
||||
staticBackdropOpacity?: boolean;
|
||||
}
|
||||
|
||||
type ModalPresentOptions = ModalOverlayOptions;
|
||||
|
@ -60,7 +60,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
|
||||
});
|
||||
});
|
||||
|
||||
configs().forEach(({ title, screenshot, config }) => {
|
||||
configs({ modes: ['ios', 'md', 'ionic-md'] }).forEach(({ title, screenshot, config }) => {
|
||||
test.describe(title('modal: rendering'), () => {
|
||||
const runVisualTests = async (page: E2EPage, screenshotModifier = '') => {
|
||||
await page.goto('/src/components/modal/test/basic', config);
|
||||
|
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 28 KiB |