Announce item name when it's removed from a table - #66
Conversation
be54618 to
5b28a53
Compare
Co-authored-by: plocket <52798256+plocket@users.noreply.github.com>
5b28a53 to
b8ab680
Compare
BryceStevenWilley
left a comment
There was a problem hiding this comment.
After testing this a bit, I think that there are two main things that should change:
- Give a bit more information about what item was removed. It looks like
item_popped = this_thread.current_info['action_dict'].pop(..., and thenstr(item_popped)works well for that (just gives the first column of the row, which IMO is good enough). I think this is needed,Item removedis just a bit too vague. - Change how we display the announcement. As is, I think it too easy for users to either miss the announcement if they go to a different part of the page before the whole heading is read, or for it to be read multiple times / later than we intend. We could either:
- make an empty announcement section right under the header (not in the header itself, that's confusing if folks are iterating over the headings present on the page), have
add_sr_announcement()add the text to the javascript of the page, and then add those messages to the announcement section after the page has loaded (after a set interval). Let's us keeparia-live= polite - use docassemble's builtin
log(..., "info")banner system. This usesrole=alert(which the below link claims doesn't work on macOS, but seems to work for me on Chrome/macOS. Would need more testing, might not work at all in Firefox, but), and lets us punt on this particular issue: we could just uselog(..., "info")for now, and then make sure the banner announcement system is more accessible (#47 specifically means that we'll have to do more testing with banners when we get the chance). We very will might need to take option 1 when fixing banners anyway.
- make an empty announcement section right under the header (not in the header itself, that's confusing if folks are iterating over the headings present on the page), have
Slight leaning towards option 2 here, eventually getting to option 1 when addressing #47.
https://tetralogical.com/blog/2024/05/01/why-are-my-live-regions-not-working/ was the best source I found on aria-live issues
Use the popped item's name in the message instead of a generic "Item removed". Also prime an empty aria-live region once when the page first loads, and writing the message into it on delete. And, added a tiny delay to the heading focus shift so VoiceOver has some time to speak before the focus jumps.
Thank you for this, and for the article. For the display issue, the article was right, Safari and Chrome with VoiceOver only seem to announce things if they're injected into a region that's already sitting there. So, there's now an empty Tested it on macOS with Safari and Chrome. Safari is handling it cleanly but chrome is a little flaky on the initial load but works fine after |
|
Just some testing comments. Testing this when it's macOS
iPhone:
Linux:
It's a solid improvement over the current behavior. |
BryceStevenWilley
left a comment
There was a problem hiding this comment.
I think this is much better! I think the most efficient option is to keep the changes from functions.py, and move the JS changes and the server.py changes to a different PR. That behavior doesn't seem to be currently doing anything, but I think that's the right direction to continue in, and in a different PR you can integrate more tightly with the message log in that aria-live section.
|
Throwing my testing interview in the comments here so I don't lose it: metadata:
title: Default playground interview
short title: Test
comment: This is a learning tool. Feel free to write over it.
---
include:
- docassemble.AssemblyLine:assembly_line.yml
---
mandatory: True
code: |
users.gather()
done
---
event: done
question: idk
---
sections:
- review_screen: Review
---
event: review_screen
question: Review
review:
- Edit: users.revisit
button: |
**Users**
% for item in users:
- ${ item }
% endfor
---
|
BryceStevenWilley
left a comment
There was a problem hiding this comment.
Looks good to me! Will merge this now, and will do another full assistive tech test on #67
When a user deletes a row from a table, screen reader users had no way to know anything happened. I first tried adding an aria-live region but it didn't work with VoiceOver - docassemble replaces the entire #dabody content on every AJAX response, so any aria-live div inside it gets destroyed and recreated each time, and screen readers don't announce text that's already present in a newly created element (i tested manually updating the text of an existing aria-live div did announce correctly, but the AJAX swap broke it).
Instead, I worked with docassemble's existing behavior, after every AJAX response, daInitialize already moves focus to #daMainQuestion, and VoiceOver reads its full text content. So I added a helper function in functions.py that queues a message when a list or dict item is deleted, and in server.py, after the page is loaded, if the page contains a table with edit/delete buttons (btn-darevisit), that message is injected as a visually hidden span inside the heading.
This way the screen reader reads "Item removed." when focus moves to the heading after the deleting an item.