feat(modal): add expandToScroll property to allow scrolling at all breakpoints (#30097)

Issue number: resolves #24631

Co-authored-by: Maria Hutt <13530427+thetaPC@users.noreply.github.com>
Co-authored-by: Brandy Smith <brandyscarney@users.noreply.github.com>
This commit is contained in:
Israel de la Barrera
2025-02-03 19:45:15 +01:00
committed by GitHub
parent 621333d927
commit 166e43554e
23 changed files with 365 additions and 32 deletions

View File

@ -130,6 +130,18 @@ export class Modal implements ComponentInterface, OverlayInterface {
*/
@Prop() breakpoints?: number[];
/**
* Controls whether scrolling or dragging within the sheet modal expands
* it to a larger breakpoint. This only takes effect when `breakpoints`
* and `initialBreakpoint` are set.
*
* If `true`, scrolling or dragging anywhere in the modal will first expand
* it to the next breakpoint. Once fully expanded, scrolling will affect the content.
* If `false`, scrolling will always affect the content, and the modal will only expand
* when dragging the header or handle.
*/
@Prop() expandToScroll = true;
/**
* A decimal value between 0 and 1 that indicates the
* initial point the modal will open at when creating a
@ -562,6 +574,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
presentingEl: presentingElement,
currentBreakpoint: this.initialBreakpoint,
backdropBreakpoint: this.backdropBreakpoint,
expandToScroll: this.expandToScroll,
});
/* tslint:disable-next-line */
@ -616,7 +629,10 @@ export class Modal implements ComponentInterface, OverlayInterface {
// should be in the DOM and referenced by now, except
// for the presenting el
const animationBuilder = this.leaveAnimation || config.get('modalLeave', iosLeaveAnimation);
const ani = (this.animation = animationBuilder(el, { presentingEl: this.presentingElement }));
const ani = (this.animation = animationBuilder(el, {
presentingEl: this.presentingElement,
expandToScroll: this.expandToScroll,
}));
const contentEl = findIonContent(el);
if (!contentEl) {
@ -668,6 +684,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
presentingEl: this.presentingElement,
currentBreakpoint: initialBreakpoint,
backdropBreakpoint,
expandToScroll: this.expandToScroll,
}));
ani.progressStart(true, 1);
@ -680,6 +697,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
backdropBreakpoint,
ani,
this.sortedBreakpoints,
this.expandToScroll,
() => this.currentBreakpoint ?? 0,
() => this.sheetOnDismiss(),
(breakpoint: number) => {
@ -778,6 +796,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
presentingEl: presentingElement,
currentBreakpoint: this.currentBreakpoint ?? this.initialBreakpoint,
backdropBreakpoint: this.backdropBreakpoint,
expandToScroll: this.expandToScroll,
}
);
@ -927,9 +946,16 @@ export class Modal implements ComponentInterface, OverlayInterface {
};
render() {
const { handle, isSheetModal, presentingElement, htmlAttributes, handleBehavior, inheritedAttributes, focusTrap } =
this;
const {
handle,
isSheetModal,
presentingElement,
htmlAttributes,
handleBehavior,
inheritedAttributes,
focusTrap,
expandToScroll,
} = this;
const showHandle = handle !== false && isSheetModal;
const mode = getIonMode(this);
const isCardModal = presentingElement !== undefined && mode === 'ios';
@ -948,6 +974,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
['modal-default']: !isCardModal && !isSheetModal,
[`modal-card`]: isCardModal,
[`modal-sheet`]: isSheetModal,
[`modal-no-expand-scroll`]: isSheetModal && !expandToScroll,
'overlay-hidden': true,
[FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false,
...getClassMap(this.cssClass),
@ -1019,6 +1046,12 @@ interface ModalOverlayOptions {
* to fade in when using a sheet modal.
*/
backdropBreakpoint: number;
/**
* Whether or not the modal should scroll/drag
* the content only when fully expanded.
*/
expandToScroll?: boolean;
}
type ModalPresentOptions = ModalOverlayOptions;