Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion core/src/components/content/content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,26 @@ export class Content implements ComponentInterface {
return forceOverscroll === undefined ? mode === 'ios' && isPlatform('ios') : forceOverscroll;
}

/**
* Whether this component should size itself to its contents height, which
* is the case inside any popover and inside a modal whose `--height` is a
* content-based value. Those overlays give the content no definite height
* to fill.
*/
private shouldSizeToContent() {
if (hostContext('ion-popover', this.el)) {
return true;
}

const modal = this.el.closest('ion-modal');
if (modal === null) {
return false;
}

const height = getComputedStyle(modal).getPropertyValue('--height').trim();
return CONTENT_SIZED_HEIGHTS.includes(height);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could this also handle changes to --height after ion-content has rendered?
For example : if a media query changes --height from 300px to auto, the computed value changes but the content-sizing class is not updated.
I tested this with the PR build, and ion-content stayed at 0px so only the header was visible.
would it make sense to update the class when the modal height changes and add a test for this case?

}

private resize() {
/**
* Only force update if the component is rendered in a browser context.
Expand Down Expand Up @@ -538,7 +558,7 @@ export class Content implements ComponentInterface {
class={createColorClasses(this.color, {
[mode]: true,
'content-fullscreen': this.fullscreen,
'content-sizing': hostContext('ion-popover', this.el),
'content-sizing': this.shouldSizeToContent(),
overscroll: forceOverscroll,
[`content-${rtl}`]: true,
})}
Expand Down Expand Up @@ -579,6 +599,12 @@ export class Content implements ComponentInterface {
}
}

/**
* `ion-modal` `--height` values that size the modal to its contents, leaving
* children an indefinite height to resolve against.
*/
const CONTENT_SIZED_HEIGHTS = ['auto', 'fit-content', 'min-content', 'max-content'];

const getParentElement = (el: any) => {
if (el.parentElement) {
// normal element with a parent element
Expand Down
15 changes: 14 additions & 1 deletion core/src/components/modal/modal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@
--max-width: auto;
--height: 100%;
--min-height: auto;
--max-height: auto;
/**
* Clamps a content-sized `--height` (auto, fit-content, ...) to the
* overlay, giving the wrapper's flex children something to shrink
* toward so `ion-content` scrolls instead of overflowing.
*/
--max-height: 100%;
--overflow: hidden;
--border-radius: 0;
--border-width: 0;
Expand Down Expand Up @@ -87,8 +92,16 @@ ion-backdrop {
/**
* The wrapper receives programmatic focus for screen readers but should not
* show a visible focus ring, which is meant only for keyboard navigation.
*
* A flex layout is required for the wrapper to size itself to its content
* when the modal is content-sized (`--height` is auto, fit-content, ...).
* This makes it so that the content can scroll when it overflows the wrapper.
*/
.modal-wrapper {
display: flex;

flex-direction: column;

outline: none;
}

Expand Down
Loading
Loading