Skip to content
Permalink
Browse files

feat(toast): add header and additional custom toast buttons (#17147)

Adds a `header` and `buttons` property to toast. This allows for a toast header to be passed and multiple buttons including action buttons and icon only buttons which matches the Material Design spec. Adds hover states to the button to match the spec. Updates usage section to recommend the new way of passing a close button using the buttons array and `cancel` role. If a button is passed using the cancel role default the color to match the spec. Buttons will default to the `end` side but have the option of being placed on the `start` side.

Co-authored-by: Simon HΓ€nisch <simonhaenisch@users.noreply.github.com>
Co-authored-by: Brandy Carney <brandy@ionic.io>

closes #16791 closes #16237 closes #17611
  • Loading branch information...
zakton5 authored and brandyscarney committed Apr 11, 2019
1 parent 52e5a8d commit 6e1a8f1df2f49c1e03b5af5995210304d3018e84
@@ -1135,11 +1135,13 @@ ion-toast-controller,method,getTop,getTop() => Promise<HTMLIonToastElement | und

ion-toast,shadow
ion-toast,prop,animated,boolean,true,false,false
ion-toast,prop,buttons,(string | ToastButton)[] | undefined,undefined,false,false
ion-toast,prop,closeButtonText,string | undefined,undefined,false,false
ion-toast,prop,color,string | undefined,undefined,false,false
ion-toast,prop,cssClass,string | string[] | undefined,undefined,false,false
ion-toast,prop,duration,number,0,false,false
ion-toast,prop,enterAnimation,((Animation: Animation, baseEl: any, opts?: any) => Promise<Animation>) | undefined,undefined,false,false
ion-toast,prop,header,string | undefined,undefined,false,false
ion-toast,prop,keyboardClose,boolean,false,false,false
ion-toast,prop,leaveAnimation,((Animation: Animation, baseEl: any, opts?: any) => Promise<Animation>) | undefined,undefined,false,false
ion-toast,prop,message,string | undefined,undefined,false,false
@@ -68,6 +68,7 @@ import {
TabButtonLayout,
TextareaChangeEventDetail,
TextFieldTypes,
ToastButton,
ToastOptions,
ToggleChangeEventDetail,
TransitionDoneFn,
@@ -4757,6 +4758,10 @@ export namespace Components {
*/
'animated': boolean;
/**
* An array of buttons for the toast.
*/
'buttons'?: (ToastButton | string)[];
/**
* Text to display in the close button.
*/
'closeButtonText'?: string;
@@ -4781,6 +4786,10 @@ export namespace Components {
*/
'enterAnimation'?: AnimationBuilder;
/**
* Header to be shown in the toast.
*/
'header'?: string;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
'keyboardClose': boolean;
@@ -4828,6 +4837,10 @@ export namespace Components {
*/
'animated'?: boolean;
/**
* An array of buttons for the toast.
*/
'buttons'?: (ToastButton | string)[];
/**
* Text to display in the close button.
*/
'closeButtonText'?: string;
@@ -4848,6 +4861,10 @@ export namespace Components {
*/
'enterAnimation'?: AnimationBuilder;
/**
* Header to be shown in the toast.
*/
'header'?: string;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
'keyboardClose'?: boolean;
@@ -45,10 +45,25 @@ export class ToastExample {
async presentToastWithOptions() {
const toast = await this.toastController.create({
header: 'Toast header',
message: 'Click to Close',
showCloseButton: true,
position: 'top',
closeButtonText: 'Done'
buttons: [
{
side: 'start',
icon: 'star',
text: 'Favorite',
handler: () => {
console.log('Favorite clicked');
}
}, {
text: 'Done',
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
}
}
]
});
toast.present();
}
@@ -76,11 +91,27 @@ async function presentToastWithOptions() {
await toastController.componentOnReady();
const toast = await toastController.create({
header: 'Toast header',
message: 'Click to Close',
showCloseButton: true,
position: 'top',
closeButtonText: 'Done'
buttons: [
{
side: 'start',
icon: 'star',
text: 'Favorite',
handler: () => {
console.log('Favorite clicked');
}
}, {
text: 'Done',
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
}
}
]
});
return await toast.present();
}
```
@@ -122,9 +153,21 @@ export class Toast extends Component<Props, State> {
isOpen={this.state.showToast2}
onDidDismiss={() => this.setState(() => ({ showToast2: false }))}
message='Click to Close'
showCloseButton={true}
position='top'
closeButtonText='Done'
buttons={[{
side: 'start',
icon: 'star',
text: 'Favorite',
handler: () => {
console.log('Favorite clicked');
}
}, {
text: 'Done',
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
}
}]}
>
</IonToast>
);
@@ -140,11 +183,13 @@ export class Toast extends Component<Props, State> {
| Property | Attribute | Description | Type | Default |
| ----------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ----------- |
| `animated` | `animated` | If `true`, the toast will animate. | `boolean` | `true` |
| `buttons` | -- | An array of buttons for the toast. | `(string \| ToastButton)[] \| undefined` | `undefined` |
| `closeButtonText` | `close-button-text` | Text to display in the close button. | `string \| undefined` | `undefined` |
| `color` | `color` | The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics). | `string \| undefined` | `undefined` |
| `cssClass` | `css-class` | Additional classes to apply for custom CSS. If multiple classes are provided they should be separated by spaces. | `string \| string[] \| undefined` | `undefined` |
| `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. | `((Animation: Animation, baseEl: any, opts?: any) => Promise<Animation>) \| undefined` | `undefined` |
| `header` | `header` | Header to be shown in the toast. | `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. | `((Animation: Animation, baseEl: any, opts?: any) => Promise<Animation>) \| undefined` | `undefined` |
| `message` | `message` | Message to be shown in the toast. | `string \| undefined` | `undefined` |
@@ -26,6 +26,10 @@ test('toast: custom close text', async () => {
await testToast(DIRECTORY, '#custom-close-text-toast');
});

test('toast: custom buttons', async () => {
await testToast(DIRECTORY, '#custom-action-buttons-toast');
});

test('toast: translucent', async () => {
await testToast(DIRECTORY, '#translucent-toast');
});
@@ -66,6 +70,10 @@ test('toast:rtl: custom close text', async () => {
await testToast(DIRECTORY, '#custom-close-text-toast', true);
});

test('toast:rtl: custom buttons', async () => {
await testToast(DIRECTORY, '#custom-action-buttons-toast');
});

test('toast:rtl: translucent', async () => {
await testToast(DIRECTORY, '#translucent-toast', true);
});
@@ -13,54 +13,92 @@

<body>
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>Toast - Basic</ion-title>
</ion-toolbar>
</ion-header>

<ion-content id="content" padding>
<ion-button expand="block" id="show-bottom-toast" onclick="presentToast('bottom')">Show Toast Bottom</ion-button>
<ion-button expand="block" id="show-top-toast" onclick="presentToast('top')">Show Toast Top</ion-button>
<ion-button expand="block" id="show-middle-toast" onclick="presentToast('middle')">Show Toast Middle</ion-button>
<ion-button expand="block" id="two-line-toast" onclick="presentToastWithOptions({message: 'Two-line message\nwith action.', showCloseButton: true, closeButtonText: 'Action'})">Show Toast with long message</ion-button>
<ion-button expand="block" id="close-button-toast" onclick="presentToastWithOptions({message: 'click to close', showCloseButton: true})">Show Toast with Close Button</ion-button>
<ion-button expand="block" id="custom-close-text-toast" onclick="presentToastWithOptions({message: 'click to close', showCloseButton: true, closeButtonText: 'closing time'})">Show Toast with Custom Close Button Text</ion-button>
<ion-button expand="block" id="translucent-toast" onclick="presentToastWithOptions({message: 'click to close', showCloseButton: true, translucent: true})">Show Translucent Toast</ion-button>
<ion-button expand="block" id="color-toast" onclick="presentToastWithOptions({message: 'click to close', showCloseButton: true, color: 'danger'})">Show Color Toast</ion-button>
<ion-button expand="block" id="custom-class-toast" onclick="presentToastWithOptions({message: 'click to close', showCloseButton: true, cssClass: 'my-custom-class'})">Show Toast with Custom Class</ion-button>

<ion-toast-controller></ion-toast-controller>

<ion-grid>
<ion-row>
<ion-col size="6">
<f class="red"></f>
</ion-col>
<ion-col size="6">
<f class="green"></f>
</ion-col>
<ion-col size="6">
<f class="blue"></f>
</ion-col>
<ion-col size="6">
<f class="yellow"></f>
</ion-col>
<ion-col size="6">
<f class="pink"></f>
</ion-col>
<ion-col size="6">
<f class="purple"></f>
</ion-col>
<ion-col size="6">
<f class="black"></f>
</ion-col>
<ion-col size="6">
<f class="orange"></f>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>
<ion-header>
<ion-toolbar>
<ion-title>Toast - Basic</ion-title>
</ion-toolbar>
</ion-header>

<ion-content id="content" padding>
<ion-button expand="block" id="show-bottom-toast" onclick="presentToast('bottom')">
Position Bottom
</ion-button>

<ion-button expand="block" id="show-top-toast" onclick="presentToast('top')">
Position Top
</ion-button>

<ion-button expand="block" id="show-middle-toast" onclick="presentToast('middle')">
Position Middle
</ion-button>

<ion-button expand="block" onclick="presentToastWithOptions({header: 'Toast header', message: 'Toast message'})">
Header Toast
</ion-button>

<ion-button expand="block" onclick="presentToastWithOptions({header: 'Toast header', message: 'Really long message that should go all of the way to the button', showCloseButton: true, closeButtonText: 'Action'})">
Header + Action Toast
</ion-button>

<ion-button expand="block" id="two-line-toast" onclick="presentToastWithOptions({message: 'Two-line message\nwith action.', showCloseButton: true, closeButtonText: 'Action'})">
Long Message
</ion-button>

<ion-button expand="block" id="close-button-toast" onclick="presentToastWithOptions({message: 'click to close', showCloseButton: true})">
Close Button
</ion-button>

<ion-button expand="block" id="custom-close-text-toast" onclick="presentToastWithOptions({message: 'click to close', showCloseButton: true, closeButtonText: 'closing time'})">
Custom Close Button
</ion-button>

<ion-button expand="block" onclick="presentToastWithButtonOptions()">
Custom Buttons
</ion-button>

<ion-button expand="block" id="translucent-toast" onclick="presentToastWithOptions({message: 'click to close', showCloseButton: true, translucent: true})">
Translucent Toast
</ion-button>

<ion-button expand="block" id="color-toast" onclick="presentToastWithOptions({message: 'click to close', showCloseButton: true, color: 'danger'})">
Color Toast
</ion-button>

<ion-button expand="block" id="custom-class-toast" onclick="presentToastWithOptions({message: 'click to close', showCloseButton: true, cssClass: 'my-custom-class'})">
Custom Class
</ion-button>

<ion-toast-controller></ion-toast-controller>

<ion-grid>
<ion-row>
<ion-col size="6">
<f class="red"></f>
</ion-col>
<ion-col size="6">
<f class="green"></f>
</ion-col>
<ion-col size="6">
<f class="blue"></f>
</ion-col>
<ion-col size="6">
<f class="yellow"></f>
</ion-col>
<ion-col size="6">
<f class="pink"></f>
</ion-col>
<ion-col size="6">
<f class="purple"></f>
</ion-col>
<ion-col size="6">
<f class="black"></f>
</ion-col>
<ion-col size="6">
<f class="orange"></f>
</ion-col>
</ion-row>
</ion-grid>
</ion-content>

</ion-app>
<script>
@@ -84,6 +122,34 @@
const toastElement = await toastController.create(opts);
return await toastElement.present();
}
async function presentToastWithButtonOptions() {
const opts = {
message: 'click to close',
buttons: [
{
side: 'start',
icon: 'star',
handler: () => {
console.log('favorite button clicked!')
return false;
}
},
{
text: 'Close',
side: 'end',
role: 'cancel',
handler: () => {
console.log('close button clicked!');
}
}
]
};
const toastController = document.querySelector('ion-toast-controller');
await toastController.componentOnReady();
const toastElement = await toastController.create(opts);
return await toastElement.present();
}
</script>

<style>
@@ -144,8 +210,7 @@
.orange {
background-color: #f69234;
}
</style>
</body>

</html>
</html>

0 comments on commit 6e1a8f1

Please sign in to comment.
You can’t perform that action at this time.