Major Changes
-
#3061
45f7c63Thanks
@github-actions! - Moverole="listbox"and related ARIA semantics from the
contentpart to thelistpart. Thecontentpart now acts as a presentational wrapper (orrole="dialog"when
popupType="dialog"), allowing consumers to render headers, footers, search inputs, tabs, and other widgets inside
the popup without polluting the listbox's accessibility tree.Breaking change — markup must wrap items in
<div {...api.getListProps()}>inside
<div {...api.getContentProps()}>:// Before <div {...api.getPositionerProps()}> <ul {...api.getContentProps()}> {items.map(item => <li {...api.getItemProps({ item })}>...</li>)} </ul> </div> // After <div {...api.getPositionerProps()}> <div {...api.getContentProps()}> <div {...api.getListProps()}> {items.map(item => <div {...api.getItemProps({ item })}>...</div>)} </div> </div> </div>
Other changes:
aria-controlson the trigger now points to the list id, not the content id.- The list element is the keyboard focus target.
scrollIntoView, scroll arrows,scrollToIndexFn, and the
activedescendant observer all anchor on the list. - New
initialFocusEl: () => HTMLElement | nullprop redirects initial focus on open (e.g., to a search input
rendered inside content). - Content's keymap now skips
Home,End, andSpacewhen the event target is an editable element, so a search
input inside content can type freely while arrow keys still navigate the listbox. - Stale
highlightedValueis reconciled insyncCollectionwhen the value is no longer in the collection (e.g.,
after filtering). - Live region announcements (mirrors combobox) — assertive announcement of the highlighted option label, gated on
Apple platforms when the list is focused and always when focus is elsewhere (search input, composed widgets). - Scroll arrows now render inside content (siblings of list) instead of the positioner, matching base-ui's pattern.
- Replaced
compositewithpopupType: "listbox" | "dialog"(default"listbox").popupType="dialog"makes
contentcarryrole="dialog"andaria-haspopup="dialog"on the trigger; thelistalways carries
role="listbox"regardless. Migratecomposite: false→popupType: "dialog".
Patch Changes
- Updated dependencies [
5820feb]:- @zag-js/anatomy@2.0.0-next.0
- @zag-js/types@2.0.0-next.0
- @zag-js/dom-query@2.0.0-next.0
- @zag-js/core@2.0.0-next.0
- @zag-js/dismissable@2.0.0-next.0
- @zag-js/focus-visible@2.0.0-next.0
- @zag-js/popper@2.0.0-next.0
- @zag-js/collection@2.0.0-next.0
- @zag-js/utils@2.0.0-next.0
- @zag-js/live-region@2.0.0-next.0