Problem/Motivation
During the review of #2982853: Menu settings and path alias details should be closed even with values I got reminded to an oddity I've noticed in the aural interface a while ago in the context of the advanced sidebar on node edit forms. There the announcement of the expanded and collapsed state of detail elements was sort of off in voiceover - the announcement was even differing in between browsers (check aural_interface-safari.mp4 and aural_interface-firefox.mp4)
When checking the DOM I've finally realized what the actual problem is (check dom-safari.mp4 and dom-firefox.mp4). Turns out once the aria-expanded attribute is set to true it remains true no matter if the expansion state is changed another time. And the reason why the aural interface behaves different between safari and firefox, safari doesnt announce the same state a second time, while firefox announces the state change even though the state remains the same .
Steps to reproduce
- Go to for example
node/add/article - expand and collapse some of the detail elements in the advanced sidebar and observe the DOM and AOM while the detail element changes in between the expanded and collapsed state.
Proposed resolution
Make sure that the aria-expanded state is updated properly in a consistent manner.
P.s. one detail i am uncertain about, if you check the open attribute on the associated details element in safari you have open while in firefox you get open="". not sure if that would require additional action
Remaining tasks
User interface changes
Introduced terminology
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #14 | devtools.mp4 | 2.06 MB | rkoller |
| #14 | off.mp4 | 850.38 KB | rkoller |
| #11 | voiceover.mp4 | 1.06 MB | rkoller |
| #8 | video.jpg | 363.43 KB | rkoller |
| #7 | aria-expanded attribute safari.mp4 | 616.7 KB | debdeep.mukhopadhyay |
Issue fork drupal-3571628
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
debdeep.mukhopadhyay commentedI am working on this
Comment #4
debdeep.mukhopadhyay commentedHi @rkoller,
I tested this on Drupal 11 (DDEV) and applied a small fix in core/misc/details-aria.js.
Now aria-expanded correctly toggles when opening and closing the summary.
I’ve also attached a short screen recording showing it working on my local setup.
Thank you very much for reviewing when you have time.
Comment #5
rkollerthank you for picking up and working on the issue @innoraftDebdeep! I've checked out MR14647 and first just manually tested it. for me the problem persists in safari, firefox, and edge . I am not a developer, so i am not entirely sure, but in the diff only the ternary operator for the open attribute on the detail element was changed, the code for the aria-expanded on the summary element hasnt had a change.
on a side note, about my P.S in the proposed resolution section in the issue summary. I've noticed and reliazed while testing your MR, when i do a reload clearing the caches in firefox and safari (by clicking the reload button with pressed alt button) the attribute is
open="open". After collapsing and expanding the detail element again it becomes the already describedopenin safari andopen=""in firefox.Comment #6
smustgrave commented@debdeep.mukhopadhyay thank you for taking an interest, looking at the MR the comment kind of concerned me as it appears it came from AI so wanted to share this https://www.drupal.org/docs/develop/issues/issue-procedures-and-etiquett....
Comment #7
debdeep.mukhopadhyay commentedHi @rkoller and @smustgrave,
thank you very much for taking the time to review and for the helpful feedback.
@rkoller —
Thank you for testing the MR and for the detailed notes.
I tested the patch again locally on Firefox, Safari and Edge, and for me the issue is resolved in all three browsers.
I have also added a screen recording to show the behavior after applying the patch.
One small note: after applying the patch, a full cache clear is required.
If the browser cache (and Drupal cache) is not cleared, the old behavior can still appear.
It is possible that the issue you are seeing is caused by cached assets.
Regarding the observation about open="open" after a hard reload and then changing after toggling — I was also able to reproduce that behavior before applying the patch, but after clearing caches and retesting with the patch, the behavior is consistent for me.
@smustgrave —
Thank you for pointing out the issue etiquette documentation. I really appreciate the reminder.
I would like to clarify that I am actively working on and testing this issue myself.
While I sometimes use tooling to help with wording, the investigation, implementation and testing of the fix were done by me, and I fully understand the responsibility of contributing accurate and reviewable work.
If you notice anything specific in the MR that should be improved (especially around tests, since the issue is now tagged with Needs tests), I would be very happy to address it.
Thanks again to both of you for the review and guidance.
Comment #8
rkolleri am still unable to confirm that the MR is working as expected on my end and i always clear caches after checking out a MR.
and looking at the video you provided the aria-expanded state != to the actual state in the ui. so also on your end the behavior is buggy:
Comment #9
rkolleri also copy over a few comments from the discussion https://drupal.slack.com/archives/C2ANFUGGG/p1770308283488189 on the drupal slack in the accessibility channel by @cwilcox808 potentially relevant for the solution:
*the
aria-pressedcomment he is referring to in the following was in comment to my previous note in the discussion about the following comment in thedetails-aria.jsfile "Handles `aria-expanded` and `aria-pressed` attributes on details elements."Comment #10
debdeep.mukhopadhyay commentedHi @rkoller,
Thank you very much for your detailed review and for sharing the discussion from the accessibility channel.
Sorry for the confusion and for my earlier approach — I initially handled the state on the summary click event, which indeed reads the state before the element is actually toggled. That was my mistake.
Based on your feedback, I have updated the implementation to listen to the element’s toggle event instead, so the real open/closed state is reflected when updating aria-expanded. This should avoid the mismatch between the visual state and the accessibility state that you pointed out in the video.
Thank you again for your patience and for the very helpful guidance.
Comment #11
rkollerthanks for updating the MR @debdeep.mukhopadhyay! i've tested in the latest versions of safari, safari technology preview, firefox, and edge in macos 26.2 and in each of them the state is announced correctly now, great! check the recording voiceover.mp4, was done in safari 26.2 with voiceover. from a manual testing perspective this looks good. from a technical perspective i am not qualified to assess if it is the right approach, i am not a developer. i defer to either @smustgrave or @cwilcox808 who i will ping in the drupal slack, they can better judge the approach than me. and after there is a consensus about the taken approach for the solution the MR still needs tests.
Comment #12
cwilcox808 commentedI don't have the means to test the code but I can comment on what I read.
Reading the code, there are a number of improvements; using the 'toggle' event, using the details.open property, removal of jQuery dependency.
This:
should be changed to this:
If the summary element isn't a direct descendant of the details element, it's not valid and won't be functional (it will effectively be a div).
I think this can be simplified:
To:
The boolean value of
.openis cast to the strings 'true' or 'false'.Something I see in production is
<summary role="button" aria-controls="edit-menu" aria-expanded="false" …>exists without JavaScript running. Because aria-expanded can only be altered by JavaScript, the attribute should not be present unless JavaScript is running. Otherwise, the details element will always be announced as "collapsed." I didn't realize this script was being used on a summary with role="button", effectively changing the details / summary into a generic "disclosure widget." If JavaScript doesn't run and the summary hasrole="button", it will break the details / summary, even without the presence of aria-expanded.I can't tell which details / summary elements this script is meant to act on, for the moment I'm going to assume it's only used on ones like those in the page authoring sidebar (Menu settings, URL alias, etc.) that are turned into generic disclosure widgets. How it should work is the summary elements have no ARIA attributes (including role) so that if JavaScript doesn't run, the element's inherent role and state can still work. When the JavaScript runs, it adds the role="button" and the aria-expanded with the state that matches whether the details element is open or not. It should probably only add the role attribute if the element doesn't already have one. Don't add aria-controls, it's pointless in this case (and in most cases).
Comment #13
debdeep.mukhopadhyay commentedHi @cwilcox808,
Thank you very much for the detailed feedback and for taking the time to review and test this.
Sorry for the earlier confusion and for my previous implementation — that was my mistake.
I have now updated the code based on the comments, so that:
the state is handled on the element’s toggle event,
only a direct child is targeted,
the real details.open state is used,
and existing widgets (summaries that already have a role) are respected, while still keeping aria-expanded in sync.
According to my latest testing, the visual state and the announced state now stay in sync.
Thank you again for your patience and for the very helpful guidance.
Comment #14
rkollerthanks for updating the MR incorporating the suggestions by @cwilcox808... i've tested the changes manually with keyboard and mouse in combination with voiceover. in safari and chrome things look good. i was only able to get to an off state where the ui showed one state and the aural interface the opposite. but i am unable to reproduce that consistently neither have any idea how i've managed to trigger that. BUT in firefox i am able to to trigger it more consistently, i only dont know what pattern is behind it yet. "maybe" it depends on the speed the details element is clicked by mouse at first? as i said not entirely sure about the root cause the state gets off track. i did another test and included the devtools in the video in firefox. i did the same steps as the previous video but as you can see this time luckily only the comments details element is off url alias remains correct. luckily because the summary element for the comment details element is selected in the devtools and there even voiceover announces expanded button group for the comments the aria-expanded state is false. not sure how that is possible at all? i am using the latest firefox developer edition.
Comment #15
debdeep.mukhopadhyay commentedHi @rkoller,
Thank you very much for the additional testing and for sharing the recordings.
From my side, I can also observe that in Firefox the visual state of the element and the announced state can occasionally become out of sync, while the behavior in Safari and Chrome appears to be consistent. This seems to be a rare interaction or timing-related edge case.
If you agree, I would like to propose adding a very small and limited fallback that simply re-synchronizes the aria-expanded state on interaction with the element itself, while still keeping the toggle event as the primary and authoritative source of truth.
I would greatly appreciate your guidance on whether this approach would be acceptable.
Comment #16
rkoller@debdeep.mukhopadhyay i dont know if your suggested approach would be the right choice, as i've mentioned before i am not a developer and therefore unfortunately unable to provide any feedback about that kind of implementation details. :( i guess @cwilcox808 or @smustgrave are able to assess your suggestion in #15 better than me.
Comment #17
jojo_martin commentedI had just run into this issue and was happy to find that it's already logged! In my case, it came up for displays using the 'Details' field group and then I went looking at admin pages and noticed it in details elements there too.
I can confirm that the changes in the MR ensures the accuracy of the aria-expanded attribute within details elements, at least in firefox and chrome.
Comment #18
rkollerthank you for testing @jojo_martin! out of curiosity after you wrote the MR is fixing the issue for you in firefox and chrome, are you unable to reproduce the problem outlined in #14?
Comment #19
jojo_martin commented@rkoller I just checked with VoiceOver and firefox, and was able to reproduce the inconsistent issue described in #14, which seems to be more likely an issue with VoiceOver based on a similar issue I found with a quick search for VoiceOver not correctly announcing changes to the aria-expanded attribute: https://bugs.webkit.org/show_bug.cgi?id=284804
I also found that the VoiceOver issue seemed to happen more if I used my mouse to interact with the expandable element, and it was more reliable if I just used keyboard navigation. Either way, it doesn't seem like an issue on the drupal side of things from what I can tell. So, it likely doesn't need to be a blocker for this issue?
Comment #20
debdeep.mukhopadhyay commentedHi @jojo_martin,@rkoller
Thank you very much for testing again and for sharing your findings.
If this appears to be a VoiceOver/browser-level issue rather than something caused by the Drupal implementation, that makes sense based on the current behavior we are seeing.
From my side, the visual state and the aria-expanded attribute remain in sync, and I’m not seeing evidence of a Drupal-side mismatch.
I’m happy to follow the maintainers’ guidance on whether this can move forward as-is or if any further adjustments are needed.
Comment #21
debdeep.mukhopadhyay commentedHi @jojo_martin,@rkoller,
I hope you are doing well.
I would like to gently follow up on this issue. I had worked on this earlier and shared my contribution/merge request after spending considerable time on analysis, implementation, and testing to ensure the proposed solution behaves as expected.
Since there has been no update or feedback for quite some time, could you please take a moment to review the contribution when convenient? If any further changes or improvements are required, I would be very happy to address them.
If everything looks good, I would sincerely appreciate if the issue could be moved to the next appropriate status. I would also be grateful to be credited for my contribution.
Thank you very much for your time and support.
Comment #22
kentr commented@debdeep.mukhopadhyay Thank you for working on this!
I understanding that the wait can be frustrating. Sometimes issues just take a while. We
generallyoften use the priority and age of issues to determine next tasks [edit: and issue queue order].I will note that the status is currently "Needs work" as of comment #8, which means that no one will be moving to review it.
The issue also has the tag "Needs tests", and the last pipeline failed. It can't be set to "Needs review" until those are resolved.
If you have added tests, please remove the "Needs tests" tag.
Comment #23
kentr commentedI also want to note that new tests should be FunctionalJavascript, and probably should use one of the existing routes in the
form_testmodule that displaysdetailselements.Comment #24
mgiffordJust adding some identifiers:
Bug ID: DRU-9da94f27 (instance) / DRU-e1099604 (pattern)
Primary route: /node/add/article (details behaviors also exercised on /form-test/group-details)
WCAG SC: 4.1.2 (A)
Rule: aria-expanded-sync
Comment #25
kentr commentedNote: There's a discussion on whether or not we really do want to use a modified details / summary element in #3573865: Details preprocess incorrectly adds role to summary.
details-aria.jswas added in #2472177: Collapsible fieldset have duplicated and wrong aria-expanded. It looks like it was just to add dynamic behavior foraria-expandedin the transition to a native details.But does the native expanded state work correctly in Safari now? Safari + VoiceOver doesn't announce the state change for me on a plain
details/summarysuch as on this a11ysupport.io test page. This is Safari 26.5.2, MacOS 14.8.Does effectively changing the
details/summaryinto a generic "disclosure widget" by fixingaria-expandedand moving thearia-roleto JavaScript per #12 satisfy this recommendation for "creating your own" disclosure widget by Scott O'Hara?:I'm planning to rebase this MR and look into the failing test.
Comment #26
kentr commentedRebased, and pipeline is passing.
Also, this code runs on all
detailselements as far as I can tell.In Claro, the details on the node edit form are called “accordion“ style. I don’t know of a live example of a “standard”
detailselement in core.Maybe there’s one in the views UI or field UI somewhere. There is one in the
form_testmodule at/form_test/details-contains-required-fields.Some questions
details/summarylike the current MR here does (versus using other HTML elements)?We have disclosure widget code elsewhere which we could centralize into a helper function so that it’s DRY and standardized. If we're effectively turning
details/summaryinto a generic disclosure widget, could we use that code here instead of something new fordetails/summary?Comment #27
cwilcox808 commentedI don't have all the context but here are my thoughts about your questions:
details/summarycan still expand/collapse when JavaScript fails for some reason. If the elements are used in an interface that's useless without JavaScript working, this isn't an advantage.summaryis activated, the 'toggle' event should be triggered regardless of how thedetailselement is expanded or collapsed. Thedetailselement contents now implicitly have thehidden=until-foundproperty so they can expand if a user uses the browser's find in page feature to search for text that's within the element (this CSS prevents that:details:not([open])::details-content { display: none; }).The only reason I'm aware of to add JavaScript is intermittent Safari+VoiceOver (macOS and iOS/iPadOS) bugs. Sometimes they're fine but there have been regressions more than once over the past 5+ years. Issues happen more often with macOS than Apple's mobile OSes. The typical issue is failing to announce when the state changes ("expanded," "collapsed").
Comment #28
kentr commentedThanks @cwilcox808
Makes sense to me.
Since we can't predict where it will be used, we probably need to plan for cases where this is a problem. I'm in the camp that there are many reasons
this can happenthat JavaScript can be unavailable. The Scott O'Hara article says that this also applies to "reader mode".Sounds like we need to fix that, also.
Safari may be in retrograde currently. @rkoller and I have both experienced that recently. It's helpful to know that it's happened more than once.
You made a good point about adding a comment regarding the purpose for the JavaScript.
Comment #29
kentr commentedEven a node edit form isn't useless without JavaScript. The rich text editor won't work, but standard fields will.
Comment #30
mgiffordThis sounds quite like we're moving in the right direction.
Having a consistent pattern that helps us control inconsistent browser application would be good.
We can then bring this over to replace efforts here https://www.drupal.org/project/drupal/issues/3573865#comment-16692222
Comment #31
kentr commentedClosed #3573865: Details preprocess incorrectly adds role to summary as a duplicate and transferred credit. It's more like a subset than a duplicate...
Per #12, we should remove
role="button"from the initial markup. This change can be taken from https://git.drupalcode.org/project/drupal/-/merge_requests/14777 for #3573865: Details preprocess incorrectly adds role to summaryComment #32
kentr commentedActually, probably MR 16325 https://git.drupalcode.org/project/drupal/-/merge_requests/16325 is the right one for removing the
role="button"from the initial markup.