react-spectrum icon indicating copy to clipboard operation
react-spectrum copied to clipboard

(WIP) Autocomplete with menu

Open LFDanLu opened this issue 1 year ago โ€ข 2 comments

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

LFDanLu avatar Oct 11 '24 21:10 LFDanLu

Is there maybe some document explaining the motivation for this new component and what it's going to be?

romansndlr avatar Oct 29 '24 17:10 romansndlr

@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.

LFDanLu avatar Oct 29 '24 17:10 LFDanLu

@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 avatar Nov 17 '24 11:11 cheema-corellian

@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.

LFDanLu avatar Nov 18 '24 17:11 LFDanLu

@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.

cheema-corellian avatar Nov 21 '24 01:11 cheema-corellian

## 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
+}

rspbot avatar Dec 04 '24 20:12 rspbot