Overview
The addon is designed to display flash notifications within Ember.js applications.
It utilizes Popover API which works well in Chrome-based browsers but is not fully supported in Firefox, at this moment @starting-style rule has not been implemented yet.
Installation
ember install ember-flash-notifications
Usage
Minimal implementation
<FlashNotifications as |notification|>
<FlashNotification @notification={{notification}}>
<div class="error">{{notification.message}}</div>
</FlashNotification>
</FlashNotifications>
import { action } from '@ember/object';
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
export default class FlashComponent extends Component {
@service notifications;
@action
addNotification() {
this.notifications.error('Something is going wrong!');
}
}
[popover] {
@apply my-0 mr-0;
}
.flash {
@apply w-80 transition-opacity block opacity-0;
}
.flash:popover-open {
@apply opacity-100;
}
.flash .error {
@apply bg-rose-500 text-white p-2 rounded-sm;
}
@starting-style {
.flash:popover-open {
@apply opacity-0;
}
}
Different notification types
<FlashNotifications as |notification|>
<FlashNotification @notification={{notification}}>
<div class={{notification.type}}>{{notification.message}}</div>
</FlashNotification>
</FlashNotifications>
import { action } from '@ember/object';
import Component from '@glimmer/component';
import { htmlSafe } from '@ember/template';
import { inject as service } from '@ember/service';
export default class FlashComponent extends Component {
@service notifications;
@action
errorNotification() {
this.notifications.error('Something is going wrong!');
}
@action
warningNotification() {
this.notifications.warning('Doubtful but OK');
}
@action
successNotification() {
this.notifications.success('Working as expected');
}
@action
infoNotification() {
this.notifications.info(htmlSafe('Some useful info splitted<br>to multiple lines'));
}
}
[popover] {
@apply my-0 mr-0;
}
.flash {
@apply w-80 transition-opacity block opacity-0;
}
.flash:popover-open {
@apply opacity-100;
}
.flash div {
@apply text-white p-2 rounded-sm;
}
.flash div.error {
@apply bg-rose-500;
}
.flash div.warning {
@apply bg-orange-500;
}
.flash div.success {
@apply bg-lime-500;
}
.flash div.info {
@apply bg-sky-500;
}
@starting-style {
.flash:popover-open {
@apply opacity-0;
}
}
Custom notifications
ember g instance-initializer notifications
export function initialize(owner) {
let notifications = owner.lookup('service:notifications');
notifications.registerShorthand('custom');
}
export default {
initialize,
};
<FlashNotifications as |notification|>
<FlashNotification class={{notification.type}} @notification={{notification}}>
<div class="p-1 bg-transparent">
<div class="flash-content">
{{#if notification.isCustom}}
<div class="text-sm font-bold text-slate-500 mr-4">{{notification.options.title}}</div>
{{/if}}
<div class="flex gap-4">
<div class="flash-type">
<img class="w-16 h-16" src="biohazard.svg" alt="Notification type icon" />
</div>
<div>
<div class="flex flex-col grow">
<span class="text-xs">{{notification.message}}</span>
<code class="text-xs text-slate-400">{{notification.options.error}}</code>
</div>
</div>
</div>
<div class="absolute top-1 right-1 flex-shrink-0 flex">
<div role="button" name="close" class="flash-close text-gray-400">
<span class="sr-only">Close</span>
<Icons::FasTimes role="presentation" class="h-4 w-4" />
</div>
</div>
</div>
</div>
</FlashNotification>
</FlashNotifications>
import { action } from '@ember/object';
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
export default class FlashCustomComponent extends Component {
@service notifications;
@action
addNotification() {
this.notifications.custom('Error in DNA sequence:', {
duration: 10_000,
title: 'Custom notification message',
error:
'MDSKGSSQKGSRLLLLLVVSNLLLCQGVVSTPVCPNGPGNCQVSLRDLFDRAVMVSHYIHDLSS
EMFNEFDKRYAQGKGFITMALNSCHTSSLPTPEDKEQAQQTHHEVLMSLILGLLRSWNDPLYHL
VTEVRGMKGAPDAILSRAIEIEEENKRLLEGMEMIFGQVIPGAKETEPYPVWSGLPSLQTKDED
ARYSAFYNLLHCLRRDSSKIDTYLKLLNCRIIYNNNC*',
});
}
}
Custom duration
By default, the time of notification disappearing is 5s. Setting the duration to 0 makes the notification persistent.
This value can be overridden using initializer:
ember g instance-initializer notifications
export function initialize(owner) {
let notifications = owner.lookup('service:notifications');
notifications.setOptions({
duration: 3_000,
});
}
export default {
initialize,
};
You can also specify the duration for a particular notification.
import { action } from '@ember/object';
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
export default class FlashComponent extends Component {
@service notifications;
@action
errorNotification() {
this.notifications.error('This notification will be visible until you close it', { duration: 0 });
}
@action
warningNotification() {
this.notifications.warning('Disappeared in 10 seconds', { duration: 10_000 });
}
}
Manual closing a notification
You'll need to define an element with name="close"
attribute:
<FlashNotifications as |notification|>
<FlashNotification @notification={{notification}}>
<div class="relative info">
{{notification.message}}
<div class="absolute top-1 right-1 flex-shrink-0 flex">
<div role="button" name="close" class="flash-close">
<span class="sr-only">Close</span>
<Icons::FasTimes role="presentation" class="h-4 w-4" />
</div>
</div>
</div>
</FlashNotification>
</FlashNotifications>
Clear all notifications
Note: when fired, no any transitions and no onClose
calls will be applied.
import { action } from '@ember/object';
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
export default class FlashComponent extends Component {
@service notifications;
@action
clearNotifications() {
this.notifications.clear();
}
}
Custom onClose handler
Fired on CSS transition ends
<FlashNotifications as |notification|>
<FlashNotification @notification={{notification}} @onClose={{this.onClose}}>
<div class="relative info">
{{notification.message}}
<div class="absolute top-1 right-1 flex-shrink-0 flex">
<div role="button" name="close" class="flash-close">
<span class="sr-only">Close</span>
<Icons::FasTimes role="presentation" class="h-4 w-4" />
</div>
</div>
</div>
</FlashNotification>
</FlashNotifications>
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
export default class FlashCloseComponent extends Component {
@service notifications;
onClose(notification) {
window.alert('Notification was closed');
}
}
API Reference
Notifications service
setOptions(options)
Sets the default options for notifications by merging with existing defaults.
options (Object)
: Custom options to be merged with the default options.
registerShorthand(type)
Registers a shorthand method for creating notifications of a specific type and adds a getter property (is<Type>) to the Notification prototype.
type (String)
: The type of notification to register.
error(message, options)
warning(message, options)
success(message, options)
info(message, options)
Adds a error (warning, success, of info notification appropriately) notification to the queue.
message (String)
: The message to be displayed.options (Object)
: Instance-specific options for the notification.
remove(notification)
Removes a specific notification from the queue.
notification (Object)
: The notification object to be removed.
clear()
Clears all notifications from the queue.
Components
FlashNotifications
FlashNotifications component is a container that manages and displays a list of notification messages. It yields each notification to be rendered within FlashNotification component.
FlashNotification
The FlashNotification component is responsible for rendering individual notification messages.
Arguments:
notification (Object)
: Notification object to be displayed.onClose (function)
: A callback function to be invoked when the notification is closed.
<FlashNotifications as |notification|>
<FlashNotification @notification={{notification}} @onClose={{this.onClose}}>
<div class="relative info">
{{notification.message}}
<div class="absolute top-1 right-1 flex-shrink-0 flex">
<div role="button" name="close" class="flash-close">
<span class="sr-only">Close</span>
<Icons::FasTimes role="presentation" class="h-4 w-4" />
</div>
</div>
</div>
</FlashNotification>
</FlashNotifications>
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
export default class FlashCloseComponent extends Component {
@service notifications;
onClose(notification) {
window.alert('Notification was closed');
}
}