-
Notifications
You must be signed in to change notification settings - Fork 86
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
Notification: Property innerAriaLive
has no effect
#2091
Comments
this bugfix should be available as of beta.139 |
Issue is not fixed with 3.0.0-beta.139. The attribute |
hi @georgwittberger-telekom-mms I just tested this again on a little custom site. I used the voiceover utility on macOS and the narrator on win11 - and the notification content was output correctly. I also checked on the deployed storybook page and got the correct screenreader output. |
Hi @felix-ico , thanks for investigating and testing. The expected behavior is that screen readers announce the notification text content as soon as the component appears in the DOM. It's not about having the content read when focusing the element. This announcement on appearance did not work for me because the body part of the notification does not have the attribute |
Hi @felix-ico , I have news on this one. The problem of notifications not being announced when they appear/change in the document was raised again in our recent accessibility audit. I have looked a little bit into it. It seems like the inner attribute I worked around this behavior in our React project as follows: const MessageBox = ({
id,
heading,
variant,
dismissible,
children,
onClose,
...props
}) => {
const [opened, setOpened] = useState(false);
const onMessageClose = (event) => {
event.stopPropagation();
setOpened(false);
onClose?.(event);
};
useEffect(() => {
// Workaround: Open notification after initial render to make aria-live work!
setOpened(true);
}, []);
return (
<ScaleNotification
id={id}
heading={heading}
innerAriaLive={variant === "danger" ? "assertive" : "polite"}
variant={variant}
opened={opened}
{...(dismissible && {
dismissible: true,
closeButtonLabel: "Close dialog",
closeButtonTitle: "Close dialog"
})}
// Workaround: Prevent events from triggering behavior in parent components (e.g. scale-modal)!
onScale-open={event => event.stopPropagation()}
onScale-close={onMessageClose}
{...props}>
{children && <div slot="text">{children}</div>}
</ScaleNotification>
);
}; So, you may want to take a look why setting |
hi @georgwittberger-telekom-mms thanks a lot for the update and the tip. That's interesting because I remember testing on the storybook canvas (that has edit: read your last post again and realized that this should have nothing to do with the react context - testing now |
Hi @georgwittberger-telekom-mms I just tested this again, and could nor reproduce your described bug. I made sure to have a notification with the opened attribute already set to true on the initial page load. I did find some inconsistent behavior though: Tested on Win11 Outside of react context (vanilla HTML): Edge + JAWS: Notification headline and text gets read on first page load, and on subsequent page reloads ✅ In react context: Edge + JAWS: Notification headline and text gets read on first page load, and on subsequent page reloads ✅ I also tested the storybook sample: on chrome & edge + NVDA and JAWS and found that all contents are output correctly (and there is no special logic there to set opened="true" after page load there) ✅ - could you test that link on your side? I think that the innerAriaLive property should be removed in any case. As far as I understand elements with role="alert" have an implicit "assertive" aria-live value, so setting it to polite should not have any effect anyway. @acstll do you have any thoughts on this? |
Hi @felix-ico , thanks for this extensive testing. When I open that link the notification component does not render any role attribute or aria-live attributes. But the test page seems to be set up without using Generelly, it would be nice to have external control whether the notification needs to be announced as an alert or it is just a status. Maybe you can provide a prop like |
That should be due to this code, that is executed on initial render:
when the notification is initially set to open, it will not receive any role attribute, therefore not receiving and I guess the issue is that the |
OK, I see why this could make sense. There might be cases where notifications should not be announced when they are rendered on initial page load, but only once the are displayed by setting I suppose this is the expected usage of the component: It is intended to be rendered always even if the message should not be visible yet. So it should be rendered with However, there are cases where we cannot always render the notification component. For example, if you have a tab panel which renders its content only when the tab is selected. In this case, a notification could be inserted into the DOM with PropsalAdd new prop Behavior without
|
Hi @georgwittberger-telekom-mms, thanks a lot for the detailed suggestion. I've been trying to implement similar to how you described, but came across some issues with aria-live="polite"/role="status" - the notification text doesn't get read at all. After some reading i found that apparently an element with role="status"/aria-live="polite" will be announced only when the inner html changes, not when the role is set (different to role="alert", which gets announced when the role is set) - this is an issue here because the notification is already present in the dom and the text doesn't change. My PR for reference #2171 possibly related issue nvaccess/nvda#14591 I am still trying to find a solution for this, will also ask colleagues internally for help. |
quick update: I may have found a workaround for that issue, by setting a small delay and "updating" (with the original text) the innerHTML, so that the screen readers announce the contents of role="status"- this seems to work in all scenarios in my tests. I had to make one change, that seemed to make sense in general to me: "heading" is not a prop anymore but another slot (this was because otherwise the text slot would be read before the heading, due to light-dom having precedence over shadow dom) I'm hoping to make a release for this tomorrow, so that you may test it too. |
Thank you so much, @felix-ico . I appreciate your hard work on this niche issue. 👍 Sad to hear that Regarding the heading change for the Scale Notification component: Will it continue to support |
I'm about to push some more changes to the bugfix-branch and will keep your comment in mind |
so actually i removed the whole "workaround" as it wasn't doing anything #2171 I realized that I have been testing wrong due to me misunderstanding aria-live property from my test "when the user is idle" means when the screen reader has stopped reading, and an element with role=status appears, it will be announced. However, if the screen reader is announcing some content, and the role=status element appears in the meantime, it will NOT be announced. I tested this by setting different timeouts and got consistent behavior, even without the custom element but just with some simple divs, so I am not sure at the moment if the spec is broken or the screen readers/browser have implemented it wrong. In any case, from my tests the component should now be announced when it is mounted to the page and is already opened (the original issue). There may be inconsistent behavior when the |
about backwards compatibility, the heading prop should also still work, there may be issues with how screen readers deal with the order of those elements so I'd recommend using the slot |
Scale Version
3.0.0-beta.137
Framework and version
React 18.2.0 with @telekom/scale-components-react
Current Behavior
Notification is not announced by screen readers when it appears in the document even though attribute
inner-aria-live
is set on custom element. The attribute value does not seem to be rendered anywhere inside the shadow DOM.Expected Behavior
Notification should be announced by screen readers when its attribute
inner-aria-live
is set to eitherpolite
orassertive
. The inner element<div part="body">
should have the attributearia-live
with the given value.Code Reproduction
Try it by setting prop
innerAriaLive
on this demo page: https://telekom.github.io/scale/?path=/docs/components-notification--standardThe text was updated successfully, but these errors were encountered: