Display notifications that appear on the front end to provide feedback or information to the user.

ska-theme includes a template part for rendering Toasts, which can be enabled from ska-theme -> General -> Toasts. The template part is set up to use the skaToast Alpine.js module.

Module specificationTypeScript
// Available configuration when using `x-data="skaToast"` on an element.
interface ToastConfig {
	/** Maximum amount of Toasts visible at once. */
	max?: number
}

// Toast structure.
interface Toast {
	id?: string | number
	content: string
	type?: 'default' | 'info' | 'success' | 'warning' | 'error' | string
}

// Properties available when using `x-data="skaToast"` on an element.
interface ToastModule {
	/** Add and show a toast. */
	add: (toast: Toast | Toast['content']) => void
	/** Show a toast. */
	show: (id: Toast['id']) => void
	/** Hide a toast. */
	hide: (id: Toast['id']) => void
	/** Remove all toasts. */
	clear: () => void
}

Adding a toast

Ensure that rendering of the template part that handles showing toasts is enabled from ska-theme -> General -> Toast.

JavaScript

The global window.ska_theme object includes a function for adding a toast. The function can accept a string with toast content or an object with the content property and additional details about the toast, such as type or id.

Adding a toast with JavaScriptJavaScript
// Using the global function
window.ska_theme.toast('Toast content.')

// With additional details
window.ska_theme.toast({
	content: 'Toast content.',
	type: 'info',
})

// Dispatching the event manually
window.dispatchEvent(new CustomEvent('ska-toast', {
	detail: {
		content: 'Toast content.',
	},
}))

// Toast with details
window.ska_theme.toast({
	id: 'toast-1',
	content: 'Toast content.',
	type: 'info',
})
// Hide toast by ID
window.ska_theme.hideToast('toast-1')
// Hide all toasts
window.ska_theme.clearToasts()

Alpine.js

In the block editor it’s easiest to add toasts by adding HTML attributes to blocks. A toast can be triggered by using the ska_theme.toast function from earlier or by using Alpine’s $dispatch magic.

Adding a toast with Alpine.jsHTML
/** Using the global function */
<button x-data x-on:click="ska_theme.toast('Toast content.')">Show toast</button>

// Add toast
ska_theme.toast({id: 'toast-1',	content: 'Toast content.', type: 'info'})

// Hide toast
ska_theme.hideToast('toast-1')

// Hide all toasts
ska_theme.clearToasts()

/** Using Alpine.js $dispatch */
<button x-data x-on:click="$dispatch('ska-toast', 'Toast content.')">Show toast</button>

// Add toast
$dispatch('ska-toast', {content: 'Toast content.', type: 'success', id: 'toast-id'})

// Hide toast
$dispatch('ska-hide-toast', 'toast-id')

// Hide all toasts
$dispatch('ska-clear-toasts')

PHP

A toast can also be added with PHP to leave users some feedback when something was done server-side.

Adding a toast with PHPPHP
ska_theme()->get('toast')->add('Toast content.');

ska_theme()->get('toast')->add([
	'content' => 'Invalid nonce.', 
	'type' => 'error',
]);
PHP examplePHP
add_action('wp_body_open', function() {

	if(!isset($_POST['email'])) {
		return;
	}

	if(subscribe_to_newsletter(sanitize_email(wp_unslash($_POST['email'])))) {
		ska_theme()->get('toast')->add([
			'content' => esc_html__('You have subscribed to the newsletter!', 'your-textdomain'),
			'type' => 'success',
		]);
	} else {
		ska_theme()->get('toast')->add([
			'content' => sprintf(
				esc_html__('Something went %1$shorribly%2$s wrong.', 'your-textdomain'),
				'<strong>',
				'</strong>'
			),
			'type' => 'error',
		]);
	}
});

Examples

Default toast

Detailed toast

Remote request

A button that attempts to fetch data from a REST endpoint and displays a success toast with the result or an error toast on failure (includes a setTimeout for demo purposes only).

Alpine.js attributes that the button usesHTML
<button 
	x-data="{loading: false}" 
	x-on:fetch="fetch('/docs/wp-json/wp/v2/posts?per_page=1')
		.then(response => response.json())
		.then(post => post[0].title.rendered)
		.then(title => $dispatch('success', title))
		.catch(e => $dispatch('error'))
		.finally(() => loading = false)" 
	x-on:success="$dispatch('ska-toast', {content: `The latest post on this site is titled: <strong>${$event.detail}</strong>`, type: 'success'})" 
	x-on:error="$dispatch('ska-toast', {content: `Failed fetching the latest post.`, type: 'error'})" 
	x-on:click="loading = true; $dispatch('fetch')" 
	:class="{loading}" 
	:disabled="loading"
>
	...
</button>