Skip to content

Commit

Permalink
feat(toast): image variant, a11y support, title html, click support
Browse files Browse the repository at this point in the history
This PR

- adds accessibility support using aria labels to toasts just like we did for modals in #2036
- adds a ui image toast variant to show images without any padding
- fixes missing html support in titles
- fixes wrong placement of vertical actions when the message was too short
- supports the onClick handler in any case now even if closeOnClick is set to false
  - onClick can now also return false to prevent closing the toast
  - the close icon gets a dedicated event now independent of the onClick event
  • Loading branch information
lubber-de authored Oct 3, 2021
1 parent 2f5aacb commit 3426127
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 23 deletions.
72 changes: 49 additions & 23 deletions src/definitions/modules/toast.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,14 @@ $.fn.toast = function(parameters) {
element = this,
instance = isToastComponent ? $module.data(moduleNamespace) : undefined,

id,
module
;
module = {

initialize: function() {
module.verbose('Initializing element');
module.create.id();
if (!module.has.container()) {
module.create.container();
}
Expand Down Expand Up @@ -124,17 +126,22 @@ $.fn.toast = function(parameters) {
},

show: function(callback) {
callback = callback || function(){};
module.debug('Showing toast');
if(settings.onShow.call($toastBox, element) === false) {
module.debug('onShow callback returned false, cancelling toast animation');
return;
}
callback = callback || function(){};
module.debug('Showing toast');
module.animate.show(callback);
},

close: function(callback) {
if(settings.onHide.call($toastBox, element) === false) {
module.debug('onHide callback returned false, cancelling toast animation');
return;
}
callback = callback || function(){};
module.debug('Closing toast');
module.remove.visible();
module.unbind.events();
module.animate.close(callback);
Expand All @@ -146,12 +153,16 @@ $.fn.toast = function(parameters) {
module.verbose('Creating container');
$context.append($('<div/>',{class: settings.position + ' ' + className.container + ' ' +(settings.horizontal ? className.horizontal : '')}));
},
id: function() {
id = (Math.random().toString(16) + '000000000').substr(2, 8);
module.verbose('Creating unique id for element', id);
},
toast: function() {
$toastBox = $('<div/>', {class: className.box});
var iconClass = module.get.iconClass();
if (!isToastComponent) {
module.verbose('Creating toast');
$toast = $('<div/>');
$toast = $('<div/>', {role: 'alert'});
var $content = $('<div/>', {class: className.content});
if (iconClass !== '') {
$toast.append($('<i/>', {class: iconClass + ' ' + className.icon}));
Expand All @@ -164,21 +175,29 @@ $.fn.toast = function(parameters) {
}));
}
if (settings.title !== '') {
var titleId = '_' + module.get.id() + 'title';
$toast.attr('aria-labelledby', titleId);
$content.append($('<div/>', {
class: className.title,
text: settings.title
id: titleId,
html: module.helpers.escape(settings.title, settings.preserveHTML)
}));
}

$content.append($('<div/>', {class: className.message, html: module.helpers.escape(settings.message, settings.preserveHTML)}));
var descId = '_' + module.get.id() + 'desc';
$toast.attr('aria-describedby', descId);
$content.append($('<div/>', {
class: className.message,
id: descId,
html: module.helpers.escape(settings.message, settings.preserveHTML)
}));

$toast
.addClass(settings.class + ' ' + className.toast)
.append($content)
;
$toast.css('opacity', settings.opacity);
if (settings.closeIcon) {
$close = $('<i/>', {class: className.close + ' ' + (typeof settings.closeIcon === 'string' ? settings.closeIcon : '')});
$close = $('<i/>', {class: className.close + ' ' + (typeof settings.closeIcon === 'string' ? settings.closeIcon : ''), role: 'button', tabindex: 0, 'aria-label': settings.text.close});
if($close.hasClass(className.left)) {
$toast.prepend($close);
} else {
Expand Down Expand Up @@ -221,12 +240,13 @@ $.fn.toast = function(parameters) {
}
}
settings.actions.forEach(function (el) {
var icon = el[fields.icon] ? '<i class="' + module.helpers.deQuote(el[fields.icon]) + ' icon"></i>' : '',
var icon = el[fields.icon] ? '<i '+(el[fields.text] ? 'aria-hidden="true"' : '')+' class="' + module.helpers.deQuote(el[fields.icon]) + ' icon"></i>' : '',
text = module.helpers.escape(el[fields.text] || '', settings.preserveHTML),
cls = module.helpers.deQuote(el[fields.class] || ''),
click = el[fields.click] && $.isFunction(el[fields.click]) ? el[fields.click] : function () {};
$actions.append($('<button/>', {
html: icon + text,
'aria-label': $('<div>'+(el[fields.text] || el[fields.icon] || '')+'</div>').text(),
class: className.button + ' ' + cls,
click: function () {
var button = $(this);
Expand Down Expand Up @@ -330,13 +350,12 @@ $.fn.toast = function(parameters) {
bind: {
events: function() {
module.debug('Binding events to toast');
if(settings.closeOnClick || settings.closeIcon) {
(settings.closeIcon ? $close : $toast)
.on('click' + eventNamespace, module.event.click)
;
if(settings.closeIcon) {
$close.on('click' + eventNamespace, module.event.close);
}
$toast.on('click' + eventNamespace, module.event.click);
if($animationObject) {
$animationObject.on('animationend' + eventNamespace, module.close);
$animationObject.on('animationend' + eventNamespace, module.event.close);
}
$toastBox
.on('click' + eventNamespace, selector.approve, module.event.approve)
Expand All @@ -348,11 +367,10 @@ $.fn.toast = function(parameters) {
unbind: {
events: function() {
module.debug('Unbinding events to toast');
if(settings.closeOnClick || settings.closeIcon) {
(settings.closeIcon ? $close : $toast)
.off('click' + eventNamespace)
;
if(settings.closeIcon) {
$close.off('click' + eventNamespace);
}
$toast.off('click' + eventNamespace);
if($animationObject) {
$animationObject.off('animationend' + eventNamespace);
}
Expand Down Expand Up @@ -384,11 +402,6 @@ $.fn.toast = function(parameters) {
},
close: function(callback) {
callback = $.isFunction(callback) ? callback : function(){};
module.debug('Closing toast');
if(settings.onHide.call($toastBox, element) === false) {
module.debug('onHide callback returned false, cancelling toast animation');
return;
}
if(settings.transition && $.fn.transition !== undefined && $module.transition('is supported')) {
$toastBox
.transition({
Expand Down Expand Up @@ -458,6 +471,9 @@ $.fn.toast = function(parameters) {
},

get: {
id: function() {
return id;
},
container: function() {
return ($context.find(module.helpers.toClass(settings.position) + selector.container + (settings.horizontal ? module.helpers.toClass(className.horizontal) : ':not('+module.helpers.toClass(className.horizontal)+')'))[0]);
},
Expand Down Expand Up @@ -491,9 +507,15 @@ $.fn.toast = function(parameters) {
},

event: {
close: function(){
module.close();
},
click: function(event) {
if($(event.target).closest('a').length === 0) {
settings.onClick.call($toastBox, element);
if(settings.onClick.call($toastBox, element) === false || !settings.closeOnClick) {
module.verbose('Click callback returned false or close denied by setting cancelling close');
return;
}
module.close();
}
},
Expand Down Expand Up @@ -834,6 +856,10 @@ $.fn.toast.settings = {
unclickable : 'unclickable'
},

text: {
close : 'Close'
},

icons : {
info : 'info',
success : 'checkmark',
Expand Down
29 changes: 29 additions & 0 deletions src/definitions/modules/toast.less
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,12 @@
}
}
&.vertical when (@variationToastVertical) {
& > .content {
flex-grow: 1;
}
&.attached when (@variationToastAttached){
flex-grow: 1;
}
& > .close.icon + .content when (@variationToastClose){
padding-left: @toastCloseDistanceVertical;
}
Expand Down Expand Up @@ -554,6 +560,29 @@
border-bottom-right-radius: 0;
}
}

&.ui.ui.ui.image when (@variationToastImage) {
padding: 0;
& > .content {
padding-top: @inputVerticalPadding;
padding-bottom: @inputVerticalPadding;
padding-right: @inputHorizontalPadding;
}
& > .actions when (@variationToastActions) {
margin: 0;
}
& > .ui.image {
border-top-left-radius: @defaultBorderRadius;
border-bottom-left-radius: @defaultBorderRadius;
&.mini {
min-width: @toastImageMiniImageAdjustment;
& + .content {
min-height: @toastImageMiniImageAdjustment;
padding-left: @toastImageMiniImagePadding;
}
}
}
}
}


Expand Down
3 changes: 3 additions & 0 deletions src/themes/default/modules/toast.variables
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@
@toastIconCenteredAdjustment: 1.2em;
@toastImageCenteredAdjustment: 2em;

@toastImageMiniImageAdjustment: e(%("calc(%d + %d)", @inputVerticalPadding, @toastMiniImageHeight));
@toastImageMiniImagePadding: 4.4em;

/* Progressbar Colors */
@toastInfoProgressColor: darken(@toastInfoColor,15);
@toastWarningProgressColor: darken(@toastWarningColor,15);
Expand Down

0 comments on commit 3426127

Please sign in to comment.