(WIP) Autocomplete with menu
Closes
โ Pull Request Checklist:
- [ ] Included link to corresponding React Spectrum GitHub Issue.
- [ ] Added/updated unit tests and storybook for this change (for new code or code which already has tests).
- [ ] Filled out test instructions.
- [ ] Updated documentation (if it already exists for this component).
- [ ] Looked at the Accessibility Practices for this feature - Aria Practices
๐ Test Instructions:
๐งข Your Project:
RSP
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Is there maybe some document explaining the motivation for this new component and what it's going to be?
@romansndlr nothing that I can quite share at the moment, but essentially this will support the ability to filter a menu in the same fashion that a combobox does (virtual focus so the user remains in the input), but without needing the menu to be within a separate popover (like Spotlight search on macOS). Still early stages for it but we hope that the wrapping Autocomplete will eventually be able to take any kind of collection component (e.g. gridlist, table, etc) rather than just a menu.
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
@LFDanLu Is it correct to assume that since this component appears to use combobox as the base, much of the combobox functionality will be retained? Of particular interest is the ability to categorize the search results as described in this discussion topic: https://github.com/adobe/react-spectrum/discussions/7308
Also, is there a very rough estimate on when this feature might make it into a release? And is it targeting S1, S2 or both?
@cheema-corellian The search/filtering capabilities of combobox along with the same kind of "virtual" focus interactions will be part of autocomplete, yes. The experience in https://github.com/adobe/react-spectrum/discussions/7308 should be possible with this component I imagine, barring the additional "Add new employee" item at the bottom which will need some additional handling. I hope to have this feature out within the next month, at least in an alpha form in React Aria Components but additional work needs to be done for submenu support and supporting any generic collection rather than just menu. We will for sure target S2 once it stabilizes in React Aria Components, but not sure about S1 to be honest.
Build successful! ๐
Build successful! ๐
@cheema-corellian The search/filtering capabilities of combobox along with the same kind of "virtual" focus interactions will be part of autocomplete, yes. The experience in #7308 should be possible with this component I imagine, barring the additional "Add new employee" item at the bottom which will need some additional handling. I hope to have this feature out within the next month, at least in an alpha form in React Aria Components but additional work needs to be done for submenu support and supporting any generic collection rather than just menu. We will for sure target S2 once it stabilizes in React Aria Components, but not sure about S1 to be honest.
@LFDanLu Thanks for providing this update. It is very helpful. I look forward to trying this component in S2 when it becomes available.
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
Build successful! ๐
## API Changes
react-aria-components
/react-aria-components:Autocomplete
+Autocomplete {
+ children: ReactNode
+ defaultFilter?: (string, string) => boolean = contains
+ defaultInputValue?: string
+ inputValue?: string
+ onInputChange?: (string) => void
+ slot?: string | null
+}
/react-aria-components:AutocompleteContext
+AutocompleteContext {
+ UNTYPED
+}
/react-aria-components:AutocompleteStateContext
+AutocompleteStateContext {
+ UNTYPED
+}
/react-aria-components:InternalAutocompleteContext
+InternalAutocompleteContext {
+ UNTYPED
+}
@react-aria/autocomplete
/@react-aria/autocomplete:useAutocomplete
+useAutocomplete {
+ props: AriaAutocompleteOptions
+ state: AutocompleteState
+ returnVal: undefined
+}
/@react-aria/autocomplete:AriaAutocompleteProps
+AriaAutocompleteProps {
+ children: ReactNode
+ defaultFilter?: (string, string) => boolean = contains
+ defaultInputValue?: string
+ inputValue?: string
+ onInputChange?: (string) => void
+}
/@react-aria/autocomplete:AriaAutocompleteOptions
+AriaAutocompleteOptions {
+ collectionRef: RefObject<HTMLElement | null>
+ defaultFilter?: (string, string) => boolean = contains
+ defaultInputValue?: string
+ inputRef: RefObject<HTMLInputElement | null>
+ inputValue?: string
+ onInputChange?: (string) => void
+}
/@react-aria/autocomplete:AutocompleteAria
+AutocompleteAria {
+ collectionProps: CollectionOptions
+ collectionRef: RefObject<HTMLElement | null>
+ filterFn: (string) => boolean
+ inputProps: InputHTMLAttributes<HTMLInputElement>
+}
/@react-aria/autocomplete:CollectionOptions
+CollectionOptions {
+ aria-describedby?: string
+ aria-details?: string
+ aria-label?: string
+ aria-labelledby?: string
+ disallowTypeAhead: boolean
+ id?: string
+ shouldUseVirtualFocus: boolean
+}
@react-aria/collections
/@react-aria/collections:BaseCollection
BaseCollection <T> {
addNode: (CollectionNode<T>) => void
at: () => Node<T>
clone: () => this
commit: (Key | null, Key | null, any) => void
+ filter: ((string) => boolean) => BaseCollection<T>
getChildren: (Key) => Iterable<Node<T>>
getFirstKey: () => void
getItem: (Key) => Node<T> | null
getKeyAfter: (Key) => void
getKeys: () => void
getLastKey: () => void
removeNode: (Key) => void
size: any
undefined: () => void
}
@react-aria/menu
/@react-aria/menu:AriaMenuOptions
AriaMenuOptions <T> {
aria-describedby?: string
aria-details?: string
aria-label?: string
aria-labelledby?: string
autoFocus?: boolean | FocusStrategy
defaultSelectedKeys?: 'all' | Iterable<Key>
disabledKeys?: Iterable<Key>
disallowEmptySelection?: boolean
id?: string
isVirtualized?: boolean
items?: Iterable<T>
keyboardDelegate?: KeyboardDelegate
onAction?: (Key) => void
onClose?: () => void
onKeyDown?: (KeyboardEvent) => void
onKeyUp?: (KeyboardEvent) => void
onSelectionChange?: (Selection) => void
selectedKeys?: 'all' | Iterable<Key>
selectionMode?: SelectionMode
shouldFocusWrap?: boolean
+ shouldUseVirtualFocus?: boolean
}
@react-aria/selection
/@react-aria/selection:SelectableItemOptions
SelectableItemOptions {
allowsDifferentPressOrigin?: boolean
focus?: () => void
+ id?: string
isDisabled?: boolean
isVirtualized?: boolean
key: Key
linkBehavior?: 'action' | 'selection' | 'override' | 'none' = 'action'
ref: RefObject<FocusableElement | null>
selectionManager: MultipleSelectionManager
shouldSelectOnPressUp?: boolean
shouldUseVirtualFocus?: boolean
}
@react-aria/utils
/@react-aria/utils:CLEAR_FOCUS_EVENT
+CLEAR_FOCUS_EVENT {
+ UNTYPED
+}
/@react-aria/utils:FOCUS_EVENT
+FOCUS_EVENT {
+ UNTYPED
+}
/@react-aria/utils:UPDATE_ACTIVEDESCENDANT
+UPDATE_ACTIVEDESCENDANT {
+ UNTYPED
+}
@react-stately/autocomplete
/@react-stately/autocomplete:useAutocompleteState
+useAutocompleteState {
+ props: AutocompleteStateOptions
+ returnVal: undefined
+}
/@react-stately/autocomplete:AutocompleteProps
+AutocompleteProps {
+ children: ReactNode
+ defaultInputValue?: string
+ inputValue?: string
+ onInputChange?: (string) => void
+}
/@react-stately/autocomplete:AutocompleteStateOptions
+AutocompleteStateOptions {
+ defaultInputValue?: string
+ inputValue?: string
+ onInputChange?: (string) => void
+}
/@react-stately/autocomplete:AutocompleteState
+AutocompleteState {
+ focusedNodeId: string | null
+ inputValue: string
+ setFocusedNodeId: (string | null) => void
+ setInputValue: (string) => void
+}