diff --git a/core/api.txt b/core/api.txt index 56cc9f460a..7bdebea2a7 100644 --- a/core/api.txt +++ b/core/api.txt @@ -1395,6 +1395,7 @@ ion-modal,prop,keyboardClose,boolean,true,false,false ion-modal,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false ion-modal,prop,mode,"ios" | "md",undefined,false,false ion-modal,prop,presentingElement,HTMLElement | undefined,undefined,false,false +ion-modal,prop,shape,"rectangular" | "round" | "soft" | undefined,undefined,false,false ion-modal,prop,showBackdrop,boolean,true,false,false ion-modal,prop,theme,"ios" | "md" | "ionic",undefined,false,false ion-modal,prop,trigger,string | undefined,undefined,false,false diff --git a/core/src/components.d.ts b/core/src/components.d.ts index 30a49f8125..f0d3a0636f 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -2097,6 +2097,10 @@ export namespace Components { * Move a sheet style modal to a specific breakpoint. The breakpoint value must be a value defined in your `breakpoints` array. */ "setCurrentBreakpoint": (breakpoint: number) => Promise; + /** + * Set to `"soft"` for a modal with slightly rounded corners, `"round"` for a modal with fully rounded corners, or `"rectangular"` for a modal without rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes. + */ + "shape"?: 'soft' | 'round' | 'rectangular'; /** * If `true`, a backdrop will be displayed behind the modal. This property controls whether or not the backdrop darkens the screen when the modal is presented. It does not control whether or not the backdrop is active or present in the DOM. */ @@ -7431,6 +7435,10 @@ declare namespace LocalJSX { * The element that presented the modal. This is used for card presentation effects and for stacking multiple modals on top of each other. Only applies in iOS mode. */ "presentingElement"?: HTMLElement; + /** + * Set to `"soft"` for a modal with slightly rounded corners, `"round"` for a modal with fully rounded corners, or `"rectangular"` for a modal without rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes. + */ + "shape"?: 'soft' | 'round' | 'rectangular'; /** * If `true`, a backdrop will be displayed behind the modal. This property controls whether or not the backdrop darkens the screen when the modal is presented. It does not control whether or not the backdrop is active or present in the DOM. */ diff --git a/core/src/components/modal/modal.ionic.scss b/core/src/components/modal/modal.ionic.scss new file mode 100644 index 0000000000..232efd7b1a --- /dev/null +++ b/core/src/components/modal/modal.ionic.scss @@ -0,0 +1,19 @@ +@use "../../themes/ionic/ionic.globals.scss" as globals; +@import "./modal"; + +// Ionic Modal +// -------------------------------------------------- + +// Shape +// ------------------------------------- +:host(.modal-round) { + --border-radius: #{globals.$ionic-border-radius-1000}; +} + +:host(.modal-soft) { + --border-radius: #{globals.$ionic-border-radius-400}; +} + +:host(.modal-rectangular) { + --border-radius: #{globals.$ionic-border-radius-0}; +} diff --git a/core/src/components/modal/modal.tsx b/core/src/components/modal/modal.tsx index d240c2b48c..7b870b613c 100644 --- a/core/src/components/modal/modal.tsx +++ b/core/src/components/modal/modal.tsx @@ -62,7 +62,7 @@ import { setCardStatusBarDark, setCardStatusBarDefault } from './utils'; styleUrls: { ios: 'modal.ios.scss', md: 'modal.md.scss', - ionic: 'modal.md.scss', + ionic: 'modal.ionic.scss', }, shadow: true, }) @@ -291,6 +291,15 @@ export class Modal implements ComponentInterface, OverlayInterface { */ @Prop() canDismiss: boolean | ((data?: any, role?: string) => Promise) = true; + /** + * Set to `"soft"` for a modal with slightly rounded corners, + * `"round"` for a modal with fully rounded corners, or `"rectangular"` + * for a modal without rounded corners. + * + * Defaults to `"round"` for the `ionic` theme, undefined for all other themes. + */ + @Prop() shape?: 'soft' | 'round' | 'rectangular'; + /** * Emitted after the modal has presented. */ @@ -888,6 +897,22 @@ export class Modal implements ComponentInterface, OverlayInterface { return true; } + private getShape(): string | undefined { + const theme = getIonTheme(this); + const { shape } = this; + + // TODO(ROU-11167): Remove theme check when shapes are defined for all themes. + if (theme !== 'ionic') { + return undefined; + } + + if (shape === undefined) { + return 'round'; + } + + return shape; + } + private onHandleClick = () => { const { sheetTransition, handleBehavior } = this; if (handleBehavior !== 'cycle' || sheetTransition !== undefined) { @@ -936,6 +961,7 @@ export class Modal implements ComponentInterface, OverlayInterface { const theme = getIonTheme(this); const isCardModal = presentingElement !== undefined && theme === 'ios'; const isHandleCycle = handleBehavior === 'cycle'; + const shape = this.getShape(); return ( + + + + Modal - Shape + + + + + + + + + + + + + + + + + Modal - Shape + + + + +
+

Sheet

+ + + + +
+ +
+

Card

+ + + + +
+
+
+ + + + diff --git a/core/src/components/modal/test/shape/modal.e2e.ts b/core/src/components/modal/test/shape/modal.e2e.ts new file mode 100644 index 0000000000..c5c2ecc927 --- /dev/null +++ b/core/src/components/modal/test/shape/modal.e2e.ts @@ -0,0 +1,57 @@ +import { expect } from '@playwright/test'; +import { configs, test } from '@utils/test/playwright'; + +/** + * This behavior does not vary across directions. + */ +configs({ directions: ['ltr'], modes: ['ionic-md'] }).forEach(({ config, screenshot, title }) => { + test.beforeEach(async ({ page }) => { + await page.goto('/src/components/modal/test/shape', config); + }); + + test.describe(title('modal: shape'), () => { + test.describe('sheet', () => { + ['default', 'round', 'soft', 'rectangular'].forEach((shape) => { + test(`${shape} - should not have visual regressions`, async ({ page }) => { + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + + await page.click(`#sheet-modal-${shape}`); + await ionModalDidPresent.next(); + + await expect(page).toHaveScreenshot(screenshot(`modal-shape-sheet-${shape}`), { + /** + * Animations must be enabled to capture the screenshot. + * By default, animations are disabled with toHaveScreenshot, + * and when capturing the screenshot will call animation.finish(). + * This will cause the modal to close and the screenshot capture + * to be invalid. + */ + animations: 'allow', + }); + }); + }); + }); + + test.describe('card', () => { + ['default', 'round', 'soft', 'rectangular'].forEach((shape) => { + test(`${shape} - should not have visual regressions`, async ({ page }) => { + const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent'); + + await page.click(`#card-modal-${shape}`); + await ionModalDidPresent.next(); + + await expect(page).toHaveScreenshot(screenshot(`modal-shape-card-${shape}`), { + /** + * Animations must be enabled to capture the screenshot. + * By default, animations are disabled with toHaveScreenshot, + * and when capturing the screenshot will call animation.finish(). + * This will cause the popover to close and the screenshot capture + * to be invalid. + */ + animations: 'allow', + }); + }); + }); + }); + }); +}); diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-default-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-default-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..839dc8ffcd Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-default-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-default-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-default-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..94dc24a477 Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-default-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-default-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-default-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..03695f5388 Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-default-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-rectangular-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-rectangular-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..b6ab34e4b2 Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-rectangular-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-rectangular-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-rectangular-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..5d2afb99aa Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-rectangular-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-rectangular-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-rectangular-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..1ec53d61e3 Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-rectangular-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-round-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-round-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..839dc8ffcd Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-round-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-round-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-round-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..94dc24a477 Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-round-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-round-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-round-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..03695f5388 Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-round-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-soft-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-soft-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..69a62e1abc Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-soft-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-soft-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-soft-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..d0cbcecc89 Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-soft-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-soft-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-soft-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..fdf1f0cabc Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-card-soft-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-default-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-default-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..1fdebe5ea3 Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-default-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-default-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-default-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..d85e3ce999 Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-default-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-default-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-default-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..6f7117b4a9 Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-default-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-rectangular-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-rectangular-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..491b841619 Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-rectangular-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-rectangular-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-rectangular-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..2d6a53aece Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-rectangular-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-rectangular-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-rectangular-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..afc200e2a9 Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-rectangular-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-round-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-round-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..1fdebe5ea3 Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-round-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-round-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-round-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..d85e3ce999 Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-round-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-round-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-round-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..6f7117b4a9 Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-round-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-soft-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-soft-ionic-md-ltr-light-Mobile-Chrome-linux.png new file mode 100644 index 0000000000..6c5b471bd9 Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-soft-ionic-md-ltr-light-Mobile-Chrome-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-soft-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-soft-ionic-md-ltr-light-Mobile-Firefox-linux.png new file mode 100644 index 0000000000..c1ba62220b Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-soft-ionic-md-ltr-light-Mobile-Firefox-linux.png differ diff --git a/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-soft-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-soft-ionic-md-ltr-light-Mobile-Safari-linux.png new file mode 100644 index 0000000000..91eada497d Binary files /dev/null and b/core/src/components/modal/test/shape/modal.e2e.ts-snapshots/modal-shape-sheet-soft-ionic-md-ltr-light-Mobile-Safari-linux.png differ diff --git a/packages/vue/src/components/Overlays.ts b/packages/vue/src/components/Overlays.ts index e02bd93fb7..23921286d1 100644 --- a/packages/vue/src/components/Overlays.ts +++ b/packages/vue/src/components/Overlays.ts @@ -27,7 +27,7 @@ export const IonPickerLegacy = /*@__PURE__*/ defineOverlayContainer('ion-toast', defineIonToastCustomElement, ['animated', 'buttons', 'color', 'cssClass', 'duration', 'enterAnimation', 'header', 'htmlAttributes', 'icon', 'isOpen', 'keyboardClose', 'layout', 'leaveAnimation', 'message', 'mode', 'position', 'positionAnchor', 'swipeGesture', 'theme', 'translucent', 'trigger']); -export const IonModal = /*@__PURE__*/ defineOverlayContainer('ion-modal', defineIonModalCustomElement, ['animated', 'backdropBreakpoint', 'backdropDismiss', 'breakpoints', 'canDismiss', 'enterAnimation', 'focusTrap', 'handle', 'handleBehavior', 'htmlAttributes', 'initialBreakpoint', 'isOpen', 'keepContentsMounted', 'keyboardClose', 'leaveAnimation', 'mode', 'presentingElement', 'showBackdrop', 'theme', 'trigger'], true); +export const IonModal = /*@__PURE__*/ defineOverlayContainer('ion-modal', defineIonModalCustomElement, ['animated', 'backdropBreakpoint', 'backdropDismiss', 'breakpoints', 'canDismiss', 'enterAnimation', 'focusTrap', 'handle', 'handleBehavior', 'htmlAttributes', 'initialBreakpoint', 'isOpen', 'keepContentsMounted', 'keyboardClose', 'leaveAnimation', 'mode', 'presentingElement', 'shape', 'showBackdrop', 'theme', 'trigger'], true); export const IonPopover = /*@__PURE__*/ defineOverlayContainer('ion-popover', defineIonPopoverCustomElement, ['alignment', 'animated', 'arrow', 'backdropDismiss', 'component', 'componentProps', 'dismissOnSelect', 'enterAnimation', 'event', 'focusTrap', 'htmlAttributes', 'isOpen', 'keepContentsMounted', 'keyboardClose', 'leaveAnimation', 'mode', 'reference', 'showBackdrop', 'side', 'size', 'theme', 'translucent', 'trigger', 'triggerAction']);