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

[AriaNotify] How should the interrupt property work? #2331

Open
alisonmaher opened this issue Sep 17, 2024 · 2 comments
Open

[AriaNotify] How should the interrupt property work? #2331

alisonmaher opened this issue Sep 17, 2024 · 2 comments

Comments

@alisonmaher
Copy link

alisonmaher commented Sep 17, 2024

The current design of AriaNotify, as outlined in the spec PR and the explainer, includes a property that allows authors more control over the verbosity of their notifications, called interrupt.

We have received feedback that interrupt is confusing with respect to how flushing works, and that it doesn't quite cover all use cases.

To help in outlining how interrupt works with its various value types (none, all, and pending) @douggeoffray put together a demo showcasing how each behaves in the case of a progress bar. The code for this demo can be found at https://codepen.io/douggeoffray/pen/WNqVQjO.

As demonstrated, this property will allow authors more customization of how noisy their notifications will be.

Currently, interrupt only flushes notifications of the same originating node and priority, if applicable. However, we received feedback that this doesn't cover all use cases desired by web authors, as outlined by the following example provided by @smhigley:

In an AI chat scenario, after sending a response we send a series of notifications as follows:

  • Loading updates every 5 seconds (priority: none)
  • Potentially a generating announcement once content streaming starts (and further updates every 5 seconds) (priority: none)
  • When finished successfully, a notification including the full text content of the response (priority: important)
  • When failed, an error message (priority: important)

This is currently in copilot chat controls, but the same pattern could be used elsewhere, anywhere content is loaded for a potentially long time, and can succeed or error.

Here is a code sample of the above use case: https://copilot-study.netlify.app/chatMay2024

As noted by this example, there is a desire to flush all notifications of the same node, regardless of priority, which isn't possible today with the current definition of interrupt.

As a result, I am proposing to update to the flushing behavior of interrupt as follows, with the change from the current proposal bolded:

  1. Only flush items from the same node (as is specified today)
  2. If priority is set to important, and interrupt is all, flush all notifications for that node, no matter the priority.
  3. If priority is set to none, and interrupt is all, flush only the notifications with the same node and priority of none. This way, low priority items won't flush high priority items.
  4. Points 2 and 3 would be the same for an interrupt value of pending, but only flush notifications that are pending as opposed to also those that are currently being spoken.
@alisonmaher
Copy link
Author

This was discussed at TPAC at several points. I've tried to pull out the points in which this was discussed below:

aardrian: priority and interrupt, to set the stage, I've worked with devs over the past years that are painful to recount. They don't understand the difference between polite and assertive. Priority and interrupt are two axes. Doug provided a matrix that's helpful, but my gut tells me that I won't be able to explain it to devs

aardrian: from the matrix, priority important won't override priority none, I want to check that I'm not misreading that

alisonmaher: yup, and there's an open issue

alisonmaher: I'm happy to go through the proposal, the update is for high pri items to flush out both high pri and low pri notifications of the same node. And then any low pri would still just only flush other low pri. So that's my proposal for update, to make that much better for what authors want to be using for, I think

Matt_King: since the API is imperative, what if flushing was just a separate method. Like, you just, if the author just said "I want to flush stuff out" rather than buliding it into those props

jamesn: because they wouldn't

Matt_King: if the option to do it is there, but you were arguing they might not set priority and interrupt correctly. What's the difference between not setting interrupt and having a separate call to flush it?

Jamie, you wanted to flag AT implementability concerns about interrupt and priority taking the source node into account

Doug: are you flushing it because you want to stop speech, or because you want to speak the new string. And if you want to speak the new string, it makes sense to do it all in one

Jamie: I have real concerns about the, right now interrupt takes the node into account. Every node effectively ahs to be considered separately. I don't know what it is for JAWS, but for NVDA it's going to be extremely hard to implement. I mean like a ridiculous refactor

Jamie: and I'm looking at the mac API, and it has priority but not [?]. I'm worried about implementability for this

Doug: I talked to folks on this, and he said it was possible, but there might be performance issues for this

Jamie: I'm not saying it's impossible, but I'm talking about difficulty, and it might take 5 years to implement. I'm wondering if it should be part of the initial spec if it'll take forever to implement

Matt_King: could someone explain the node part?

Jamie: [explains it]

Jamie: right now, NVDA cannot reorder based on the source node, and that would be a significant factor. I know narrator can do this, but it might be the only one
.....
Jamie: [something i missed]

Jamie: if I queue a hi pri message from node A, a low pri message from node B, and a high pri from Node C, how do those get ordered

Jamie: right now NVDA can't do queues per node. It's not impossible, but not implemented

smockle: I don't think node-specific priority is part of this. Clearing is, but there is a global priority, at least that's how the polyfill works

Jamie: is node-specific interrupt a thing?

smockle: yes

Jamie: so that's the same thing
...
smockle: so renaming notificaitonId to type, have high-pri interrupt low-pri, those are things we have consensus on. Jamie, you suggested dropping interrupt

smockle: are there thigns we can do to interrupt besides dropping it to get it out, could we have it not tied to a specific node?

Jamie: yes

Jamie: everyone acknowledges that this is important, and I want to raise this so this doesn't become a thing that prevents it from being implemented. So I want to remove as many of these blockers as possible

Jamie: that is one proposal, I think we should talk about it more

Doug: I think we're still talking about an assertive queue and a polite queue, I think. And today, if an assertive comes in, it will interrupt everything. I don't think it'll interrupt another assertive, but it'll interrupt everything else

Doug: also if a keypress comes in, it'll flush everything. So I think we can make this better by giving better guidance to SRs to not interrupt assertive on keypress, so we're not interrupting anything, we're just setting the prioirty of those strings to come in front of

Doug: using Narrator as an example, if an assertive comes in, it goes to the front of the queue but doesn't interrupt anything. Techniques like that will help the biggest complaint users have, where they were missing information. I think this will help get less of that experience. I still like the idea of speech history, but I think this will help
...
jcraig: we are open to changing APIs, if there's compelling need. There is some support for interrupt, but I don't know if every aspect of interrupt is supported

keithamus: the isssues are how does the interrupt prop work, I don't know if we've settled that

jamesn: we've settled it needs to change

Doug: I wonder if you get rid of interrupt, and go with priority, is that enough?

Doug: I think all platforms support a priority approach, I jsut hate to see this whole thing bogged down with this at this point. Is it important enough to bog it down or not

alisonmaher: I guess the question is would authors find enoguh value in this over live regions?

keithamus: there's certainly still value. I think interrupt is a nice feature, but the other features inherent in the design are more valuable

smockle: one of the problems we came in with was coordination between multiple components on the page all sending live regions. And we started having longer and longer delays. I think our issue is less a single component needing to interrupt itself, and more lots of components needing to not interrupt eachother

keithamus: maybe another API method that could effectively just cancel whatever is currently being announced. Maybe moving that option out of the API

smockle: or maybe cancelling for a given node or a specific type, is more flexible

Based on this, we did all seem to agree to resolve on updating the following: If priority is set to important, and interrupt is all or pending, flush all or pending notifications for that node, no matter the priority.

One of the main outstanding points that @jcsteh brought up was AT implementability of interrupt being node-based. I have been giving it some more thought and have come up with a potential algorithm I am planning to discuss with AT vendors in the next couple of weeks to help determine if this will be implementable in a performant way https://docs.google.com/document/d/1ukbM0SMQqYFWD65kZFW9MNURv8vriRvx8W0Y24E0Lbs/edit?usp=sharing.

If we prove it won't be possible, we can look to update the functionality to either not be node based, or potentially drop it as @douggeoffray had noted in the discussion.

So next steps for me are to follow up with ATs on proving out implementability, and we can plan to revisit once I have more data.

@alisonmaher
Copy link
Author

@douggeoffray and I chatted with NVDA and JAWS in the last couple of weeks, to determine the implementability of the above. JAWS was supportive of keeping interrupt in the first version of the release of ariaNotify(). JAWS is planning to look more into the algorithm proposed in https://docs.google.com/document/d/1ukbM0SMQqYFWD65kZFW9MNURv8vriRvx8W0Y24E0Lbs/edit?usp=sharing, since they will need to update their notification handling in general.

NVDA was also supportive of interrupt, and they didn't have concerns with this not being implementable with it being per-node. However, they will need to re-architect their notification backend, in general.

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

No branches or pull requests

1 participant