Skip to content

Commit

Permalink
Autocomplete: only show UI on user input (#45904)
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix authored Nov 30, 2022
1 parent 74a71e2 commit ae560c8
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 12 deletions.
55 changes: 43 additions & 12 deletions packages/components/src/autocomplete/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -415,26 +415,57 @@ function useAutocomplete( {
}

export function useAutocompleteProps( options ) {
const [ isVisible, setIsVisible ] = useState( false );
const ref = useRef();
const recordAfterInput = useRef();
const onKeyDownRef = useRef();
const { popover, listBoxId, activeId, onKeyDown } = useAutocomplete( {
...options,
contentRef: ref,
} );
onKeyDownRef.current = onKeyDown;

useEffect( () => {
if ( isVisible ) {
if ( ! recordAfterInput.current ) {
recordAfterInput.current = options.record;
} else if (
recordAfterInput.current.start !== options.record.start ||
recordAfterInput.current.end !== options.record.end
) {
setIsVisible( false );
recordAfterInput.current = null;
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ options.record ] );

const mergedRefs = useMergeRefs( [
ref,
useRefEffect( ( element ) => {
function _onKeyDown( event ) {
onKeyDownRef.current( event );
}
function _onInput() {
// Only show auto complete UI if the user is inputting text.
setIsVisible( true );
recordAfterInput.current = null;
}
element.addEventListener( 'keydown', _onKeyDown );
element.addEventListener( 'input', _onInput );
return () => {
element.removeEventListener( 'keydown', _onKeyDown );
element.removeEventListener( 'input', _onInput );
};
}, [] ),
] );

if ( ! isVisible ) {
return { ref: mergedRefs };
}

return {
ref: useMergeRefs( [
ref,
useRefEffect( ( element ) => {
function _onKeyDown( event ) {
onKeyDownRef.current( event );
}
element.addEventListener( 'keydown', _onKeyDown );
return () => {
element.removeEventListener( 'keydown', _onKeyDown );
};
}, [] ),
] ),
ref: mergedRefs,
children: popover,
'aria-autocomplete': listBoxId ? 'list' : undefined,
'aria-owns': listBoxId,
Expand Down
28 changes: 28 additions & 0 deletions test/e2e/specs/editor/various/autocomplete-and-mentions.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -409,4 +409,32 @@ test.describe( 'Autocomplete', () => {
<p>@ringbearer +thebetterhobbit</p>
<!-- /wp:paragraph -->` );
} );

test( 'should hide UI when selection changes (by keyboard)', async ( {
page,
} ) => {
await page.click( 'role=button[name="Add default block"i]' );
await page.keyboard.type( '@fr' );
await expect(
page.locator( 'role=option', { hasText: 'Frodo Baggins' } )
).toBeVisible();
await page.keyboard.press( 'ArrowLeft' );
await expect(
page.locator( 'role=option', { hasText: 'Frodo Baggins' } )
).not.toBeVisible();
} );

test( 'should hide UI when selection changes (by mouse)', async ( {
page,
} ) => {
await page.click( 'role=button[name="Add default block"i]' );
await page.keyboard.type( '@fr' );
await expect(
page.locator( 'role=option', { hasText: 'Frodo Baggins' } )
).toBeVisible();
await page.click( '[data-type="core/paragraph"]' );
await expect(
page.locator( 'role=option', { hasText: 'Frodo Baggins' } )
).not.toBeVisible();
} );
} );

0 comments on commit ae560c8

Please sign in to comment.