feat(toast): add icon property to show icon at start of toast content (#23596)

resolves #23524

Co-authored-by: William Martin <contact@willmartin.dev>
Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>
This commit is contained in:
Dominik Geng
2021-07-23 18:46:01 +02:00
committed by GitHub
parent fffef8acd2
commit df24c8c5ae
11 changed files with 72 additions and 15 deletions

View File

@ -1345,6 +1345,7 @@ ion-toast,prop,cssClass,string | string[] | undefined,undefined,false,false
ion-toast,prop,duration,number,0,false,false
ion-toast,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-toast,prop,header,string | undefined,undefined,false,false
ion-toast,prop,icon,string | undefined,undefined,false,false
ion-toast,prop,keyboardClose,boolean,false,false,false
ion-toast,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-toast,prop,message,IonicSafeString | string | undefined,undefined,false,false
@ -1379,6 +1380,7 @@ ion-toast,css-prop,--width
ion-toast,part,button
ion-toast,part,container
ion-toast,part,header
ion-toast,part,icon
ion-toast,part,message
ion-toggle,shadow

View File

@ -2770,6 +2770,10 @@ export namespace Components {
* Header to be shown in the toast.
*/
"header"?: string;
/**
* The name of the icon to display, or the path to a valid SVG file. See `ion-icon`. https://ionic.io/ionicons
*/
"icon"?: string;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
@ -6366,6 +6370,10 @@ declare namespace LocalJSX {
* Header to be shown in the toast.
*/
"header"?: string;
/**
* The name of the icon to display, or the path to a valid SVG file. See `ion-icon`. https://ionic.io/ionicons
*/
"icon"?: string;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/

View File

@ -10,6 +10,10 @@ Toasts can be positioned at the top, bottom or middle of the viewport. The posit
The toast can be dismissed automatically after a specific amount of time by passing the number of milliseconds to display it in the `duration` of the toast options. If a button with a role of `"cancel"` is added, then that button will dismiss the toast. To dismiss the toast after creation, call the `dismiss()` method on the instance.
## Icons
An icon can be added next to the content inside of the toast. In general, icons in toasts should be used to add additional style or context, not to grab the user's attention or elevate the priority of the toast. If you wish to convey a higher priority message to the user or guarantee a response, we recommend using an [Alert](../alert) instead.
## Interfaces
### ToastButton
@ -80,6 +84,7 @@ export class ToastExample {
const toast = await this.toastController.create({
header: 'Toast header',
message: 'Click to Close',
icon: 'information-circle',
position: 'top',
buttons: [
{
@ -99,7 +104,7 @@ export class ToastExample {
]
});
await toast.present();
const { role } = await toast.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
}
@ -124,6 +129,7 @@ async function presentToastWithOptions() {
const toast = document.createElement('ion-toast');
toast.header = 'Toast header';
toast.message = 'Click to Close';
toast.icon = 'information-circle',
toast.position = 'top';
toast.buttons = [
{
@ -144,7 +150,7 @@ async function presentToastWithOptions() {
document.body.appendChild(toast);
await toast.present();
const { role } = await toast.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
}
@ -198,6 +204,7 @@ const ToastExample: React.FC = () => {
import React, { useState } from 'react';
import { IonToast, IonContent, IonButton } from '@ionic/react';
import { informationCircle } from 'ionicons/icons';
export const ToastExample: React.FC = () => {
const [showToast1, setShowToast1] = useState(false);
@ -218,6 +225,7 @@ export const ToastExample: React.FC = () => {
isOpen={showToast2}
onDidDismiss={() => setShowToast2(false)}
message="Click to Close"
icon={informationCircle}
position="top"
buttons={[
{
@ -267,6 +275,7 @@ export class ToastExample {
const toast = await toastController.create({
header: 'Toast header',
message: 'Click to Close',
icon: 'information-circle',
position: 'top',
buttons: [
{
@ -286,7 +295,7 @@ export class ToastExample {
]
});
await toast.present();
const { role } = await toast.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
}
@ -317,6 +326,7 @@ export class ToastExample {
<script>
import { IonButton, IonContent, IonPage, toastController } from '@ionic/vue';
import { informationCircle } from 'ionicons/icons';
export default {
components: { IonButton, IonContent, IonPage },
@ -334,6 +344,7 @@ export default {
.create({
header: 'Toast header',
message: 'Click to Close',
icon: informationCircle,
position: 'top',
buttons: [
{
@ -353,7 +364,7 @@ export default {
]
})
await toast.present();
const { role } = await toast.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
},
@ -385,7 +396,7 @@ export default defineComponent({
setup() {
const isOpenRef = ref(false);
const setOpen = (state: boolean) => isOpenRef.value = state;
return { isOpenRef, setOpen }
}
});
@ -405,6 +416,7 @@ export default defineComponent({
| `duration` | `duration` | How many milliseconds to wait before hiding the toast. By default, it will show until `dismiss()` is called. | `number` | `0` |
| `enterAnimation` | -- | Animation to use when the toast is presented. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
| `header` | `header` | Header to be shown in the toast. | `string \| undefined` | `undefined` |
| `icon` | `icon` | The name of the icon to display, or the path to a valid SVG file. See `ion-icon`. https://ionic.io/ionicons | `string \| undefined` | `undefined` |
| `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `false` |
| `leaveAnimation` | -- | Animation to use when the toast is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
| `message` | `message` | Message to be shown in the toast. | `IonicSafeString \| string \| undefined` | `undefined` |
@ -473,6 +485,7 @@ Type: `Promise<void>`
| `"button"` | Any button element that is displayed inside of the toast. |
| `"container"` | The element that wraps all child elements. |
| `"header"` | The header text of the toast. |
| `"icon"` | The icon that appears next to the toast content. |
| `"message"` | The body text of the toast. |

View File

@ -35,7 +35,7 @@
Position Middle
</ion-button>
<ion-button expand="block" onclick="openToast({header: 'Toast header', message: 'Toast message'})">
<ion-button expand="block" onclick="openToast({header: 'Toast header', message: 'Toast message', duration: 2000})">
Header Toast
</ion-button>
@ -83,6 +83,18 @@
Show HTML Toast
</ion-button>
<ion-button expand="block" id="toast-with-icon" onclick="openToast({ header: 'Bluetooth', message: 'Device connected.', icon: 'bluetooth', duration: 2000 })">
Toast with Icon
</ion-button>
<ion-button expand="block" id="toast-with-icon-2" onclick="openToast({ message: 'An error has occurred!', icon: 'warning', color: 'danger', duration: 2000 })">
Toast with Icon 2
</ion-button>
<ion-button expand="block" id="toast-with-icon-3" onclick="openToast({ message: 'Debug me...', icon: 'bug', buttons: ['Close'] })">
Toast with Icon 3
</ion-button>
<ion-grid>
<ion-row>
<ion-col size="6">
@ -211,4 +223,4 @@
</style>
</body>
</html>
</html>

View File

@ -120,6 +120,9 @@
justify-content: center;
}
.toast-icon {
@include margin(null, null, null, 16px);
}
.toast-message {
flex: 1;
@ -141,7 +144,8 @@
z-index: 0;
}
.toast-icon {
.toast-icon,
.toast-button-icon {
font-size: 1.4em;
}

View File

@ -18,6 +18,7 @@ import { mdLeaveAnimation } from './animations/md.leave';
* @part container - The element that wraps all child elements.
* @part header - The header text of the toast.
* @part message - The body text of the toast.
* @part icon - The icon that appears next to the toast content.
*/
@Component({
tag: 'ion-toast',
@ -106,6 +107,12 @@ export class Toast implements ComponentInterface, OverlayInterface {
*/
@Prop() animated = true;
/**
* The name of the icon to display, or the path to a valid SVG file. See `ion-icon`.
* https://ionic.io/ionicons
*/
@Prop() icon?: string;
/**
* Emitted after the toast has presented.
*/
@ -243,7 +250,7 @@ export class Toast implements ComponentInterface, OverlayInterface {
<ion-icon
icon={b.icon}
slot={b.text === undefined ? 'icon-only' : undefined}
class="toast-icon"
class="toast-button-icon"
/>}
{b.text}
</div>
@ -281,6 +288,10 @@ export class Toast implements ComponentInterface, OverlayInterface {
<div class="toast-container" part="container">
{this.renderButtons(startButtons, 'start')}
{this.icon !== undefined &&
<ion-icon class="toast-icon" part="icon" icon={this.icon} lazy={false} aria-hidden="true"></ion-icon>
}
<div class="toast-content">
{this.header !== undefined &&
<div class="toast-header" part="header">{this.header}</div>

View File

@ -23,6 +23,7 @@ export class ToastExample {
const toast = await this.toastController.create({
header: 'Toast header',
message: 'Click to Close',
icon: 'information-circle',
position: 'top',
buttons: [
{
@ -42,7 +43,7 @@ export class ToastExample {
]
});
await toast.present();
const { role } = await toast.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
}

View File

@ -12,6 +12,7 @@ async function presentToastWithOptions() {
const toast = document.createElement('ion-toast');
toast.header = 'Toast header';
toast.message = 'Click to Close';
toast.icon = 'information-circle',
toast.position = 'top';
toast.buttons = [
{
@ -32,7 +33,7 @@ async function presentToastWithOptions() {
document.body.appendChild(toast);
await toast.present();
const { role } = await toast.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
}

View File

@ -43,6 +43,7 @@ const ToastExample: React.FC = () => {
import React, { useState } from 'react';
import { IonToast, IonContent, IonButton } from '@ionic/react';
import { informationCircle } from 'ionicons/icons';
export const ToastExample: React.FC = () => {
const [showToast1, setShowToast1] = useState(false);
@ -63,6 +64,7 @@ export const ToastExample: React.FC = () => {
isOpen={showToast2}
onDidDismiss={() => setShowToast2(false)}
message="Click to Close"
icon={informationCircle}
position="top"
buttons={[
{

View File

@ -20,6 +20,7 @@ export class ToastExample {
const toast = await toastController.create({
header: 'Toast header',
message: 'Click to Close',
icon: 'information-circle',
position: 'top',
buttons: [
{
@ -39,7 +40,7 @@ export class ToastExample {
]
});
await toast.present();
const { role } = await toast.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
}
@ -53,4 +54,4 @@ export class ToastExample {
];
}
}
```
```

View File

@ -10,6 +10,7 @@
<script>
import { IonButton, IonContent, IonPage, toastController } from '@ionic/vue';
import { informationCircle } from 'ionicons/icons';
export default {
components: { IonButton, IonContent, IonPage },
@ -27,6 +28,7 @@ export default {
.create({
header: 'Toast header',
message: 'Click to Close',
icon: informationCircle,
position: 'top',
buttons: [
{
@ -46,7 +48,7 @@ export default {
]
})
await toast.present();
const { role } = await toast.onDidDismiss();
console.log('onDidDismiss resolved with role', role);
},
@ -78,7 +80,7 @@ export default defineComponent({
setup() {
const isOpenRef = ref(false);
const setOpen = (state: boolean) => isOpenRef.value = state;
return { isOpenRef, setOpen }
}
});