Dropdown: reveal the current value on open + proper listbox/menu item roles#396
Open
acusti wants to merge 4 commits into
Open
Dropdown: reveal the current value on open + proper listbox/menu item roles#396acusti wants to merge 4 commits into
acusti wants to merge 4 commits into
Conversation
32457be to
c303417
Compare
a59b8d3 to
60ef117
Compare
027bd7a to
a58042b
Compare
A controlled dropdown opened at the top of its list regardless of the current value. On open, mark the item whose data-ukt-value matches props.value aria-selected, make it the active item so keyboard navigation starts there, and scroll it into view — so a long list opens showing, and scrolled to, the current selection. setActiveItem's event becomes optional (it only builds the onActiveItem payload, which is skipped when there's no event) so an item can be activated programmatically on open. Adds a themeable --uktdd-body-bg-color-selected tint for the persistent selection marker. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The dropdown set the container role (listbox/menu/dialog) but left its items as plain <li>s, so a searchable listbox exposed no options and a menu no menuitems. On open, fill in the roles the consumer hasn't set: option for a listbox, menuitem for a menu (and for any submenu, itself a menu), with the <ul>/<ol> wrappers marked role="presentation" so the container owns its items directly rather than through an intervening list. Skip items that carry their own semantics — a natively interactive item (button, link, input) or one with a consumer-set role keeps it. aria-selected on the current option is already set by the reveal-on-open behavior. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The open-time annotation marks the item matching props.value, but with keepOpenOnSubmit the body outlives the submit, so selecting another item left the tint (and aria-selected) on the previous selection until the next open. Move it to the submitted option in handleSubmitItem; a closing body unmounts, so reopening re-derives it from props.value as before. Also document that the open-time annotations (roles, aria-selected, reveal) run once per open, so items rendered into an already-open body aren't annotated until the next open. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HcJxNoQKN6Yx5hmYpwJHMJ
The ARIA attributes section covered the trigger, body, submenu, and menubar annotations but not the item-level ones added alongside them: option/menuitem role fill-in, the presentation role on list wrappers, aria-selected on the current listbox option, and the reveal-on-open behavior with its --uktdd-body-bg-color-selected custom property. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HcJxNoQKN6Yx5hmYpwJHMJ
a58042b to
c48606a
Compare
Comment on lines
+7
to
+12
| A controlled dropdown now opens with the item whose `data-ukt-value` | ||
| matches `props.value` marked `aria-selected`, made the active item (so | ||
| keyboard navigation starts from it), and scrolled into view — so a long | ||
| list opens showing, and scrolled to, the current selection instead of the | ||
| top. The persistent selection tint is themeable via the new | ||
| `--uktdd-body-bg-color-selected` custom property. |
Comment on lines
+1241
to
+1244
| if (valueIdentity != null && dropdownElement) { | ||
| const selectedItem = getItemElements(dropdownElement)?.find( | ||
| (item) => item.dataset.uktValue === valueIdentity, | ||
| ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #394 (base
dropdown-value-label-pair).Summary
Two related improvements for controlled dropdowns.
Reveal the current value on open
On open, the item whose
data-ukt-valuematchesprops.valueis made the active item (so keyboard navigation starts from the current selection) and scrolled into view — a long list opens at the current value instead of the top. In a listbox it's also markedaria-selected="true"(with a themeable--uktdd-body-bg-color-selectedtint).Proper listbox / menu item roles
The dropdown set the container role (
listbox/menu/dialog) but left its items as plain<li>s. On open it now fills in the roles the consumer hasn't set:role="option"for a searchable (listbox) dropdown,role="menuitem"for a menu — and alwaysmenuiteminside a submenu (itself a menu).<ul>/<ol>wrappers getrole="presentation"so the listbox/menu owns its items directly rather than through an intervening list.aria-selected.Details
annotateParentItems(which already gives submenusrole="menu").setActiveItem'seventbecomes optional — it's only used to build theonActiveItempayload, which is skipped without an event — so an item can be activated programmatically on open without a synthetic event or a spurious callback.aria-selectedis listbox-only (it isn't valid on amenuitem); menus get the visual active highlight but noaria-selected.Testing
minorchangesets.OpensToCurrentValueStorybook story — a long list with the value far down, so opening scrolls straight to it.build/test/tsc/lint/formatall green.Follow-up (not here)
aria-activedescendanton the searchable input (announcing the active option as you arrow through it) is the natural next a11y step for the combobox interaction — left out to keep this focused on roles + reveal.🤖 Generated with Claude Code