-
Notifications
You must be signed in to change notification settings - Fork 1.3k
fix: Autocomplete context refactor #8695
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
LFDanLu
wants to merge
18
commits into
baseCollection_filter
Choose a base branch
from
autocomplete_context_refactor
base: baseCollection_filter
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+288
−260
Open
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
c111744
autoimport....
LFDanLu 24dd7cb
replace internal autocomplete context
LFDanLu d8969a7
add FieldInputContext in place of input context and search/textfield …
LFDanLu ae3cc84
fix build
LFDanLu 3a81f31
removing erroneous autoimports
LFDanLu db91b3a
add ability for user to provide independent filter text
LFDanLu 7177106
fix lint
LFDanLu dfb80f3
fix some more tests
LFDanLu ec8066f
bring back controlled input value at autocomplete level
LFDanLu 76107ff
adding prop to disable virtual focus
LFDanLu cde0977
another stab at the types
LFDanLu 82cb364
clear autocomplete contexts so that they dont leak to nested collections
LFDanLu 18d3dbc
add tests for disallowVirtualFocus works with listbox and menu
LFDanLu 7cbf8a1
fix types
LFDanLu 8bfe6d2
refactor CollectionNode to read from static property and properly clo…
LFDanLu 5a72a98
naming from reviews and moving contexts out of autocomplete
LFDanLu 05aca0b
Merge branch 'baseCollection_filter' of github.com:adobe/react-spectr…
LFDanLu 6cfdb09
review comments
LFDanLu File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ | |
* governing permissions and limitations under the License. | ||
*/ | ||
|
||
import {AriaLabelingProps, BaseEvent, DOMProps, Node, RefObject} from '@react-types/shared'; | ||
import {AriaLabelingProps, BaseEvent, DOMProps, FocusableElement, Node, RefObject} from '@react-types/shared'; | ||
import {AriaTextFieldProps} from '@react-aria/textfield'; | ||
import {AutocompleteProps, AutocompleteState} from '@react-stately/autocomplete'; | ||
import {CLEAR_FOCUS_EVENT, FOCUS_EVENT, getActiveElement, getOwnerDocument, isCtrlKeyPressed, mergeProps, mergeRefs, useEffectEvent, useEvent, useLabels, useObjectRef, useSlotId} from '@react-aria/utils'; | ||
|
@@ -28,7 +28,6 @@ export interface CollectionOptions extends DOMProps, AriaLabelingProps { | |
disallowTypeAhead: boolean | ||
} | ||
|
||
// TODO; For now go with Node here, but maybe pare it down to just the essentials? Value, key, and maybe type? | ||
export interface AriaAutocompleteProps<T> extends AutocompleteProps { | ||
/** | ||
* An optional filter function used to determine if a option should be included in the autocomplete list. | ||
|
@@ -37,10 +36,17 @@ export interface AriaAutocompleteProps<T> extends AutocompleteProps { | |
filter?: (textValue: string, inputValue: string, node: Node<T>) => boolean, | ||
|
||
/** | ||
* Whether or not to focus the first item in the collection after a filter is performed. | ||
* Whether or not to focus the first item in the collection after a filter is performed. Note this is only applicable | ||
* if virtual focus behavior is not turned off via `disableVirtualFocus`. | ||
* @default false | ||
*/ | ||
disableAutoFocusFirst?: boolean | ||
disableAutoFocusFirst?: boolean, | ||
|
||
/** | ||
* Whether the autocomplete should disable virtual focus, instead making the wrapped collection directly tabbable. | ||
* @default false | ||
*/ | ||
disableVirtualFocus?: boolean | ||
} | ||
|
||
export interface AriaAutocompleteOptions<T> extends Omit<AriaAutocompleteProps<T>, 'children'> { | ||
|
@@ -52,7 +58,7 @@ export interface AriaAutocompleteOptions<T> extends Omit<AriaAutocompleteProps<T | |
|
||
export interface AutocompleteAria<T> { | ||
/** Props for the autocomplete textfield/searchfield element. These should be passed to the textfield/searchfield aria hooks respectively. */ | ||
textFieldProps: AriaTextFieldProps, | ||
textFieldProps: AriaTextFieldProps<FocusableElement>, | ||
/** Props for the collection, to be passed to collection's respective aria hook (e.g. useMenu). */ | ||
collectionProps: CollectionOptions, | ||
/** Ref to attach to the wrapped collection. */ | ||
|
@@ -72,7 +78,8 @@ export function useAutocomplete<T>(props: AriaAutocompleteOptions<T>, state: Aut | |
inputRef, | ||
collectionRef, | ||
filter, | ||
disableAutoFocusFirst = false | ||
disableAutoFocusFirst = false, | ||
disableVirtualFocus = false | ||
} = props; | ||
|
||
let collectionId = useSlotId(); | ||
|
@@ -83,7 +90,7 @@ export function useAutocomplete<T>(props: AriaAutocompleteOptions<T>, state: Aut | |
|
||
// For mobile screen readers, we don't want virtual focus, instead opting to disable FocusScope's restoreFocus and manually | ||
// moving focus back to the subtriggers | ||
let shouldUseVirtualFocus = getInteractionModality() !== 'virtual'; | ||
let shouldUseVirtualFocus = getInteractionModality() !== 'virtual' && !disableVirtualFocus; | ||
|
||
useEffect(() => { | ||
return () => clearTimeout(timeout.current); | ||
|
@@ -254,15 +261,17 @@ export function useAutocomplete<T>(props: AriaAutocompleteOptions<T>, state: Aut | |
} | ||
|
||
let shouldPerformDefaultAction = true; | ||
if (focusedNodeId == null) { | ||
shouldPerformDefaultAction = collectionRef.current?.dispatchEvent( | ||
new KeyboardEvent(e.nativeEvent.type, e.nativeEvent) | ||
) || false; | ||
} else { | ||
let item = document.getElementById(focusedNodeId); | ||
shouldPerformDefaultAction = item?.dispatchEvent( | ||
new KeyboardEvent(e.nativeEvent.type, e.nativeEvent) | ||
) || false; | ||
if (collectionRef.current !== null) { | ||
if (focusedNodeId == null) { | ||
shouldPerformDefaultAction = collectionRef.current?.dispatchEvent( | ||
new KeyboardEvent(e.nativeEvent.type, e.nativeEvent) | ||
) || false; | ||
} else { | ||
let item = document.getElementById(focusedNodeId); | ||
shouldPerformDefaultAction = item?.dispatchEvent( | ||
new KeyboardEvent(e.nativeEvent.type, e.nativeEvent) | ||
) || false; | ||
} | ||
} | ||
|
||
if (shouldPerformDefaultAction) { | ||
|
@@ -282,6 +291,9 @@ export function useAutocomplete<T>(props: AriaAutocompleteOptions<T>, state: Aut | |
} | ||
break; | ||
} | ||
} else { | ||
// TODO: check if we can do this, want to stop textArea from using its default Enter behavior so items are properly triggered | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. todo? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it seems to work, but I'm realizing with the grid virtual focus work that there are a ton of configurations to test haha |
||
e.preventDefault(); | ||
} | ||
}; | ||
|
||
|
@@ -359,25 +371,28 @@ export function useAutocomplete<T>(props: AriaAutocompleteOptions<T>, state: Aut | |
let textFieldProps = { | ||
value: state.inputValue, | ||
onChange | ||
} as AriaTextFieldProps<HTMLInputElement>; | ||
} as AriaTextFieldProps<FocusableElement>; | ||
|
||
let virtualFocusProps = { | ||
onKeyDown, | ||
'aria-activedescendant': state.focusedNodeId ?? undefined, | ||
onBlur, | ||
onFocus | ||
}; | ||
|
||
if (collectionId) { | ||
textFieldProps = { | ||
...textFieldProps, | ||
onKeyDown, | ||
autoComplete: 'off', | ||
'aria-haspopup': collectionId ? 'listbox' : undefined, | ||
...(shouldUseVirtualFocus && virtualFocusProps), | ||
enterKeyHint: 'go', | ||
'aria-controls': collectionId, | ||
// TODO: readd proper logic for completionMode = complete (aria-autocomplete: both) | ||
'aria-autocomplete': 'list', | ||
'aria-activedescendant': state.focusedNodeId ?? undefined, | ||
// This disable's iOS's autocorrect suggestions, since the autocomplete provides its own suggestions. | ||
autoCorrect: 'off', | ||
// This disable's the macOS Safari spell check auto corrections. | ||
spellCheck: 'false', | ||
enterKeyHint: 'go', | ||
onBlur, | ||
onFocus | ||
autoComplete: 'off' | ||
}; | ||
} | ||
|
||
|
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
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
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
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
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
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
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
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
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe more appropriate to make these types more broad