Skip to content

Commit d8bdf39

Browse files
feat(toast): implement new shapes (#29936)
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 shape of the toast component could not be customized. ## What is the new behavior? - I have introduced a new shape property which determines whether the toast widget has soft, round or rectangular corners. ## 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. -->
1 parent 15d6104 commit d8bdf39

18 files changed

+199
-6
lines changed

core/api.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2376,6 +2376,7 @@ ion-toast,prop,message,IonicSafeString | string | undefined,undefined,false,fals
23762376
ion-toast,prop,mode,"ios" | "md",undefined,false,false
23772377
ion-toast,prop,position,"bottom" | "middle" | "top",'bottom',false,false
23782378
ion-toast,prop,positionAnchor,HTMLElement | string | undefined,undefined,false,false
2379+
ion-toast,prop,shape,"rectangular" | "round" | "soft" | undefined,undefined,false,false
23792380
ion-toast,prop,swipeGesture,"vertical" | undefined,undefined,false,false
23802381
ion-toast,prop,theme,"ios" | "md" | "ionic",undefined,false,false
23812382
ion-toast,prop,translucent,boolean,false,false,false

core/src/components.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3771,6 +3771,10 @@ export namespace Components {
37713771
* Present the toast overlay after it has been created.
37723772
*/
37733773
"present": () => Promise<void>;
3774+
/**
3775+
* Set to `"soft"` for a toast with slightly rounded corners, `"round"` for a toast with fully rounded corners, or `"rectangular"` for a toast without rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
3776+
*/
3777+
"shape"?: 'soft' | 'round' | 'rectangular';
37743778
/**
37753779
* If set to 'vertical', the Toast can be dismissed with a swipe gesture. The swipe direction is determined by the value of the `position` property: `top`: The Toast can be swiped up to dismiss. `bottom`: The Toast can be swiped down to dismiss. `middle`: The Toast can be swiped up or down to dismiss.
37763780
*/
@@ -9161,6 +9165,10 @@ declare namespace LocalJSX {
91619165
* The element to anchor the toast's position to. Can be set as a direct reference or the ID of the element. With `position="bottom"`, the toast will sit above the chosen element. With `position="top"`, the toast will sit below the chosen element. With `position="middle"`, the value of `positionAnchor` is ignored.
91629166
*/
91639167
"positionAnchor"?: HTMLElement | string;
9168+
/**
9169+
* Set to `"soft"` for a toast with slightly rounded corners, `"round"` for a toast with fully rounded corners, or `"rectangular"` for a toast without rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
9170+
*/
9171+
"shape"?: 'soft' | 'round' | 'rectangular';
91649172
/**
91659173
* If set to 'vertical', the Toast can be dismissed with a swipe gesture. The swipe direction is determined by the value of the `position` property: `top`: The Toast can be swiped up to dismiss. `bottom`: The Toast can be swiped down to dismiss. `middle`: The Toast can be swiped up or down to dismiss.
91669174
*/
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<!DOCTYPE html>
2+
<html lang="en" dir="ltr">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>Toast - Shape</title>
6+
<meta
7+
name="viewport"
8+
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"
9+
/>
10+
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
11+
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
12+
<script src="../../../../../scripts/testing/scripts.js"></script>
13+
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
14+
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
15+
</head>
16+
<script type="module">
17+
import { toastController } from '../../../../dist/ionic/index.esm.js';
18+
window.toastController = toastController;
19+
</script>
20+
<body>
21+
<ion-app>
22+
<ion-header>
23+
<ion-toolbar>
24+
<ion-title>Toast - Shape</ion-title>
25+
</ion-toolbar>
26+
</ion-header>
27+
28+
<ion-content class="ion-padding" id="content">
29+
(Only available for ionic theme)
30+
<button class="expand" id="default-toast" onclick="openToast({ message: 'Hello, world!', duration: 2000 })">
31+
Default Toast
32+
</button>
33+
34+
<button
35+
class="expand"
36+
id="soft-shape-toast"
37+
onclick="openToast({ message: 'Hello, world!', duration: 2000, shape: 'soft' })"
38+
>
39+
Soft Toast
40+
</button>
41+
42+
<button
43+
class="expand"
44+
id="round-shape-toast"
45+
onclick="openToast({ message: 'Hello, world!', duration: 2000, shape: 'round' })"
46+
>
47+
Round Toast
48+
</button>
49+
50+
<button
51+
class="expand"
52+
id="rect-shape-toast"
53+
onclick="openToast({ message: 'Hello, world!', duration: 2000, shape: 'rectangular' })"
54+
>
55+
Rectangular Toast
56+
</button>
57+
</ion-content>
58+
</ion-app>
59+
<script>
60+
async function openToast(opts) {
61+
const toast = await toastController.create(opts);
62+
await toast.present();
63+
}
64+
</script>
65+
</body>
66+
</html>
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { expect, type Locator } from '@playwright/test';
2+
import { configs, test } from '@utils/test/playwright';
3+
import type { E2EPage, E2EPageOptions, ScreenshotFn, EventSpy } from '@utils/test/playwright';
4+
5+
class ToastFixture {
6+
readonly page: E2EPage;
7+
8+
private ionToastDidPresent!: EventSpy;
9+
10+
constructor(page: E2EPage) {
11+
this.page = page;
12+
}
13+
14+
async goto(config: E2EPageOptions) {
15+
const { page } = this;
16+
await page.goto(`/src/components/toast/test/shape`, config);
17+
this.ionToastDidPresent = await page.spyOnEvent('ionToastDidPresent');
18+
}
19+
20+
async openToast(selector: string) {
21+
const { page, ionToastDidPresent } = this;
22+
const button = page.locator(selector);
23+
await button.click();
24+
25+
await ionToastDidPresent.next();
26+
27+
return {
28+
toast: page.locator('ion-toast'),
29+
container: page.locator('ion-toast .toast-container'),
30+
};
31+
}
32+
33+
async screenshot(screenshotModifier: string, screenshot: ScreenshotFn, el?: Locator) {
34+
const { page } = this;
35+
36+
const screenshotString = screenshot(`toast-${screenshotModifier}`);
37+
38+
if (el === undefined) {
39+
await expect(page).toHaveScreenshot(screenshotString);
40+
} else {
41+
await expect(el).toHaveScreenshot(screenshotString);
42+
}
43+
}
44+
}
45+
46+
/**
47+
* This behavior does not vary across directions.
48+
*/
49+
configs({ modes: ['ionic-md'], directions: ['ltr'] }).forEach(({ config, screenshot, title }) => {
50+
test.describe(title('toast: shape'), () => {
51+
let toastFixture: ToastFixture;
52+
53+
test.beforeEach(async ({ page }) => {
54+
toastFixture = new ToastFixture(page);
55+
await toastFixture.goto(config);
56+
});
57+
58+
test('should render the default toast', async () => {
59+
await toastFixture.openToast('#default-toast');
60+
await toastFixture.screenshot('shape-round', screenshot);
61+
});
62+
63+
test('should render a soft toast', async () => {
64+
await toastFixture.openToast('#soft-shape-toast');
65+
await toastFixture.screenshot('shape-soft', screenshot);
66+
});
67+
68+
test('should render a round toast', async () => {
69+
await toastFixture.openToast('#round-shape-toast');
70+
await toastFixture.screenshot('shape-round', screenshot);
71+
});
72+
73+
test('should render a rectangular toast', async () => {
74+
await toastFixture.openToast('#rect-shape-toast');
75+
await toastFixture.screenshot('shape-rectangular', screenshot);
76+
});
77+
});
78+
});
17.2 KB
Loading
26.1 KB
Loading
16.6 KB
Loading
17.9 KB
Loading
26.6 KB
Loading
17.4 KB
Loading

0 commit comments

Comments
 (0)