<div class="message--error " role="alert">
<div class="message__container">
<div class="message__icon-container">
<span class="visually-hidden">Error message</span>
<ul class="message__list">
<li class="message__list-item">E-mail <a href="#">field</a> is required.</li>
<li class="message__list-item">Message field is required.<br>New line</li>
</ul>
<span class="message__close-button" tabindex="0" role="button">
<span class="visually-hidden">Close</span>
</span>
</div>
</div>
</div>
{{#ifCond _self.name "===" "error"}}
<div class="message--error {{#if isHidden}}is-hidden{{/if}}" role="alert">
<div class="message__container">
<div class="message__icon-container">
<span class="visually-hidden">Error message</span>
{{#if message}}
{{{message}}}
{{else}}
<ul class="message__list">
<li class="message__list-item">E-mail <a href="#">field</a> is required.</li>
<li class="message__list-item">Message field is required.<br>New line</li>
</ul>
{{/if}}
<span class="message__close-button" tabindex="{{#if isHidden}}-1{{else}}0{{/if}}" role="button">
<span class="visually-hidden">Close</span>
</span>
</div>
</div>
</div>
{{/ifCond}}
{{#ifCond _self.name "===" "warning"}}
<div class="message--warning {{#if isHidden}}is-hidden{{/if}}" role="alert">
<div class="message__container">
<div class="message__icon-container">
<span class="visually-hidden">Warning message</span>
{{#if message}}
{{{message}}}
{{else}}
<p class="message__text">Please <a href="#">mind</a> the gap.<br>There might be a problem.</p>
{{/if}}
<span class="message__close-button" tabindex="{{#if isHidden}}-1{{else}}0{{/if}}" role="button">
<span class="visually-hidden">Close</span>
</span>
</div>
</div>
</div>
{{/ifCond}}
{{#ifCond _self.name "===" "status"}}
<div class="message--status {{#if isHidden}}is-hidden{{/if}}" role="alert">
<div class="message__container">
<div class="message__icon-container">
<span class="visually-hidden">Status message</span>
{{#if message}}
{{{message}}}
{{else}}
<p class="message__text">Yip. That <a href="#">action</a> worked! Updated Page <em>Test Title</em> successfully</p>
{{/if}}
<span class="message__close-button" tabindex="{{#if isHidden}}-1{{else}}0{{/if}}" role="button">
<span class="visually-hidden">Close</span>
</span>
</div>
</div>
</div>
{{/ifCond}}
{
"isHidden": false,
"message": ""
}
import './message-material-like.scss';
export * from './message-material-like';
import MoveTo from 'moveto';
export class Message {
constructor(context, options) {
this.options = Object.assign({}, {
focusOnStart: true,
debug: true
}, options);
this.message = context;
this.messages = [...document.querySelectorAll(selector)];
this.closeButton = context.querySelector('.message__close-button');
this.determineInlineMessage();
this.initCloseButton();
this.focusFirstMessage();
if (this.options.debug) {
console.debug('Message initialized');
}
}
determineInlineMessage() {
// check if the parent element of the message (or the parents parent in case
// one div is wrapped our) is matching the <main> tag. Otherwise we can
// assume it's an inline message
const parent = this.message.parentElement;
if (parent) {
if (parent.nodeName !== 'MAIN' && parent.nodeName !== 'BODY') {
const parentParent = parent.parentElement;
if (parentParent && parentParent.nodeName !== 'MAIN') {
if (parentParent.nodeName !== 'BODY') {
this.message.classList.add('is-inline');
}
}
}
}
}
initCloseButton() {
if (this.closeButton) {
// set role button if not available already
if (!this.closeButton.hasAttribute('role')) {
this.closeButton.setAttribute('role', 'button');
}
this.closeButton.addEventListener('click', () => this.hide());
this.closeButton.addEventListener('keydown', event => {
if (event.keyCode === 13) {
event.preventDefault(); // in case message is located in a <form>
this.hide();
}
});
if (this.message.classList.contains('is-hidden')) {
this.hide(); // make sure tabindex is correctly
}
}
}
focusFirstMessage() {
if (this.messages[0] === this.message && this.options.focusOnStart) {
if (!this.message.classList.contains('is-hidden')) {
// the browser focuses the document on init by default. Wait for it
// with setTimeout and focus the message instead. Also, remove and add
// the class otherwise the browser won't focus the message since it's
// not focusable by default (has no tabindex)
this.message.classList.add('is-hidden');
setTimeout(() => {
this.message.classList.remove('is-hidden');
this.message.focus();
new MoveTo({
duration: 400,
tolerance: 10
}).move(this.message);
}, 100);
}
}
}
hide() {
this.message.classList.add('is-hidden');
this.closeButton.setAttribute('tabindex', '-1');
// in case it was focused and there's a custom focus library like flying
// focus that still highlights the now hidden button
this.closeButton.blur();
}
}
export const selector = '[class^="message--"]';
@import "~shared/base";
$fontFamily: inherit;
$fontSize: 1.125rem;
$lineHeight: 1.33;
$iconSize: 20px;
$closeButtonIconSize: 13px;
$statusBackgroundColor: #e0ede5;
$statusColor: #257340;
$statusLinkHoverColor: $statusColor;
$warningBackgroundColor: #fffbd4;
$warningColor: #bd8300;
$warningLinkHoverColor: $warningColor;
$errorBackgroundColor: #fdd9d9;
$errorColor: #920005;
$errorLinkHoverColor: $errorColor;
$closeButtonIconColor: #4a4a4a;
/*******************************************************************************
* General
******************************************************************************/
.message {
&--error,
&--warning,
&--status {
padding: 15px 0;
font-family: $fontFamily;
font-size: $fontSize;
line-height: $lineHeight;
// in high contrast mode, no background color is displayed, therefore
// use border as an alternative design pattern
@media screen and (-ms-high-contrast: white-on-black) {
border: 1px solid $a11yNonTextColorWhiteOnBlack;
}
@media screen and (-ms-high-contrast: black-on-white) {
border: 1px solid $a11yNonTextColorBlackOnWhite;
}
&.is-inline {
margin: 10px 0;
}
&.is-hidden {
display: none;
}
em {
// em is used to indicate a title quote
font-style: normal;
&:before {
content: "\00BB";
}
&:after {
content: "\00AB";
}
}
span.visually-hidden {
@include visually-hidden;
}
}
&--error {
background: $errorBackgroundColor;
color: $errorColor;
a {
@include link-underline-small($errorColor, $errorLinkHoverColor);
}
}
&--warning {
background: $warningBackgroundColor;
color: $warningColor;
a {
@include link-underline-small($warningColor, $warningLinkHoverColor);
}
}
&--status {
background: $statusBackgroundColor;
color: $statusColor;
a {
@include link-underline-small($statusColor, $statusLinkHoverColor);
}
}
&__container {
@include container;
position: relative;
}
/*****************************************************************************
* Icon
****************************************************************************/
&__icon-container {
position: relative;
padding: 0 #{$closeButtonIconSize + 15} 0 #{$iconSize + 15};
&:before {
position: absolute;
top: 3px; // optical alignment
left: 0;
font-size: $iconSize;
line-height: $iconSize;
color: inherit;
}
}
&--error &__icon-container {
@include form-components-icons-before("error");
}
&--warning &__icon-container {
@include form-components-icons-before("warning");
}
&--status &__icon-container {
@include form-components-icons-before("status");
}
/*****************************************************************************
* List
****************************************************************************/
&__list {
margin: 0;
padding: 0;
list-style-type: none;
&-item {
position: relative;
margin: 0;
padding: 0 0 0 20px;
&:before {
position: absolute;
top: 0;
left: 0;
content: "–";
}
}
}
/*****************************************************************************
* Text
****************************************************************************/
&__text {
margin: 0;
padding: 0;
}
/*****************************************************************************
* Close Button
****************************************************************************/
&__close-button {
position: absolute;
top: -4px; // optical alignment with icon on the left side
right: 0;
cursor: pointer;
border: 0;
outline: 0;
@include form-components-icons-after("close");
// hide dotted outline in Firefox
&:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 $closeButtonIconColor;
}
&:after {
color: $closeButtonIconColor;
font-size: $closeButtonIconSize;
line-height: $closeButtonIconSize;
}
}
}
No notes defined.