Commit b8a1c6e9 authored by Lyza Danger Gardner's avatar Lyza Danger Gardner Committed by Lyza Gardner

Add support for visually-hidden ToastMessages

parent 0e34ece6
......@@ -16,7 +16,9 @@ import { withServices } from '../service-context';
/**
* An individual toast message: a brief and transient success or error message.
* The message may be dismissed by clicking on it.
* The message may be dismissed by clicking on it. `visuallyHidden` toast
* messages will not be visible but are still available to screen readers.
*
* Otherwise, the `toastMessenger` service handles removing messages after a
* certain amount of time.
*
......@@ -42,6 +44,7 @@ function ToastMessage({ message, onDismiss }) {
/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions */
<Card
classes={classnames('p-0 flex border', {
'sr-only': message.visuallyHidden,
'border-red-error': message.type === 'error',
'border-yellow-notice': message.type === 'notice',
'border-green-success': message.type === 'success',
......
......@@ -90,6 +90,17 @@ describe('ToastMessages', () => {
assert.calledOnce(fakeToastMessenger.dismiss);
});
it('should set a screen-reader-only class on `visuallyHidden` messages', () => {
const message = fakeSuccessMessage();
message.visuallyHidden = true;
fakeStore.getToastMessages.returns([message]);
const wrapper = createComponent();
const messageContainer = wrapper.find('ToastMessage').getDOMNode();
assert.include(messageContainer.className, 'sr-only');
});
it('should not dismiss the message if a "More info" link is clicked', () => {
fakeStore.getToastMessages.returns([fakeNoticeMessage()]);
......
......@@ -39,11 +39,15 @@ describe('ToastMessengerService', () => {
it('adds a new success toast message to the store', () => {
fakeStore.hasToastMessage.returns(false);
service.success('hooray');
service.success('hooray', { visuallyHidden: true });
assert.calledWith(
fakeStore.addToastMessage,
sinon.match({ type: 'success', message: 'hooray' })
sinon.match({
type: 'success',
message: 'hooray',
visuallyHidden: true,
})
);
});
......
......@@ -11,6 +11,8 @@ const MESSAGE_DISMISS_DELAY = 500;
* @typedef MessageOptions
* @prop {boolean} [autoDismiss=true] - Whether the toast message automatically disappears.
* @prop {string} [moreInfoURL=''] - Optional URL for users to visit for "more info"
* @prop {boolean} [visuallyHidden=false] - When `true`, message will be visually
* hidden but still available to screen readers.
*/
/**
......@@ -58,7 +60,7 @@ export class ToastMessengerService {
_addMessage(
type,
messageText,
{ autoDismiss = true, moreInfoURL = '' } = {}
{ autoDismiss = true, moreInfoURL = '', visuallyHidden = false } = {}
) {
// Do not add duplicate messages (messages with the same type and text)
if (this._store.hasToastMessage(type, messageText)) {
......@@ -66,7 +68,13 @@ export class ToastMessengerService {
}
const id = generateHexString(10);
const message = { type, id, message: messageText, moreInfoURL };
const message = {
type,
id,
message: messageText,
moreInfoURL,
visuallyHidden,
};
this._store.addToastMessage({
isDismissed: false,
......
......@@ -11,6 +11,7 @@ describe('store/modules/toast-messages', () => {
id: 'myToast',
type: 'anyType',
message: 'This is a message',
visuallyHidden: false,
};
});
......@@ -27,6 +28,7 @@ describe('store/modules/toast-messages', () => {
assert.equal(messages[0].id, 'myToast');
assert.equal(messages[0].type, 'anyType');
assert.equal(messages[0].message, 'This is a message');
assert.isFalse(messages[0].visuallyHidden);
});
it('adds duplicate messages to the array of messages in state', () => {
......
......@@ -7,6 +7,7 @@ import { createStoreModule, makeAction } from '../create-store';
* @prop {string} message
* @prop {string} moreInfoURL
* @prop {boolean} isDismissed
* @prop {boolean} visuallyHidden
*/
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment