Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(invisibleMessage): introduce invisibleMessage util #3192

Merged
merged 6 commits into from
May 18, 2021

Conversation

ivoplashkov
Copy link
Member

Introduce InvisibleMessage util to allow custom announcements by screen readers.

The aria-live region provide a way to programmatically expose dynamic content changes in a way that can be announced by assistive technologies. Thanks to that we are able to inform the users of assistive technologies for a change that has happened to the UI.

How to use:

  1. Import the util with => import announce from "@ui5/webcomponents-base/dist/util/InvisibleMessage.js";
  2. The "announce" method expects two arguments, first one is the string to be announced and the second one is the InvisibleMessageMode enum, which is either "Polite" or "Assertive", depending on the priority we wish to apply.

@ivoplashkov ivoplashkov requested a review from d3xter666 May 10, 2021 07:28
politeSpan.style.cssText = styles;
assertiveSpan.style.cssText = styles;

if (!politeSpan.parentElement) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this be always true?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check if you have pushed the changes.

const span = mode === InvisibleMessageMode.Assertive ? assertiveSpan : politeSpan;

// Set textContent to empty string in order to trigger screen reader's announcement.
span.textContent = "";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why you'd need to make it empty and then assign the message?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If someone wants to announce the same message over and over again on some interaction, the screen reader won't be triggered if we don't empty the value.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure that way, it'd be read out?

checkBox.click();
button.click();

assert.ok(politeSpan.getHTML().indexOf("announcement") > -1, "value has been announced");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not true "value has been announced"
It is true that it has been rendered

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check if you have pushed the changes.

politeSpan.style.cssText = styles;
assertiveSpan.style.cssText = styles;

if (!politeSpan.parentElement) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check if you have pushed the changes.

checkBox.click();
button.click();

assert.ok(politeSpan.getHTML().indexOf("announcement") > -1, "value has been announced");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check if you have pushed the changes.

@ivoplashkov ivoplashkov requested a review from MapTo0 May 18, 2021 07:33
Copy link
Member

@MapTo0 MapTo0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Copy link
Contributor

@d3xter666 d3xter666 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚢 🇮🇹

@ivoplashkov ivoplashkov merged commit 0a33c40 into SAP:master May 18, 2021
@vladitasev
Copy link
Contributor

Please add me as a reviewer for all significant changes to the base package in the future.

@@ -0,0 +1,30 @@
import DataType from "./DataType.js";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file should be called AnnouncementMode IMO

import InvisibleMessageMode from "../types/InvisibleMessageMode.js";
import getSingletonElementInstance from "./getSingletonElementInstance.js";

const styles = `position: absolute;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole code is not CSP compliant. We cannot set CSS like this (innerText, cssText, etc...). Use the imperative APIs instead.

top: -1000px;
pointer-events: none;`;

const politeSpan = document.createElement("span");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code must be synchronized with the lifecycle of the framework. You can achieve this in one of two ways:

  • Make the creation of these spans lazy (during the call of the announce function - an only create the span that is announced - polite or assertive)
  • Export another function from this file, and call it in boot.js to create the spans safely after the HTML is loaded..

I prefer the first.

const span = mode === InvisibleMessageMode.Assertive ? assertiveSpan : politeSpan;

// Set textContent to empty string in order to trigger screen reader's announcement.
span.textContent = "";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could would then become:
getSpan(mode).textContent = message;
where getSpan is a local function for this module that returns the span, if created, or creates and then returns it.

@@ -103,6 +103,7 @@ import applyDirection from "@ui5/webcomponents-base/dist/locale/applyDirection.j
import { attachDirectionChange } from "@ui5/webcomponents-base/dist/locale/directionChange.js";
import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js";
import * as defaultTexts from "./dist/generated/i18n/i18n-defaults.js";
import announce from "@ui5/webcomponents-base/dist/util/InvisibleMessage.js";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an antipattern - if a module has an export default, it should coincide with the name of the module.

@@ -0,0 +1,48 @@
import InvisibleMessageMode from "../types/InvisibleMessageMode.js";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file does not belong to util in its current form. This is a module with side effects (creates DOM) and not a utility such as camelToKebabCase.

ilhan007 pushed a commit that referenced this pull request Sep 20, 2021
* feat(invisibleMessage): introduce invisibleMessage util

* apply comments

* fix typo

* apply comments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants