Auto focus input box when opening popup (#139161)

* Focusing on input box on render

* Use generated ID instead of ref

* fix import

Co-authored-by: Jonathan Buttner <jonathan.buttner@elastic.co>
This commit is contained in:
Thom Heymann 2022-08-24 11:55:49 +01:00 committed by GitHub
parent e3181e65f3
commit 410ededfd5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 4 deletions

View file

@ -79,6 +79,7 @@ describe('UserProfilesPopover', () => {
closePopover={[MockFunction]}
display="inline-block"
hasArrow={true}
initialFocus="#searchInput_generated-id"
isOpen={false}
ownFocus={true}
panelPaddingSize="none"
@ -102,6 +103,7 @@ describe('UserProfilesPopover', () => {
},
]
}
searchInputId="searchInput_generated-id"
selectedOptions={
Array [
Object {
@ -121,4 +123,25 @@ describe('UserProfilesPopover', () => {
</EuiPopover>
`);
});
it('should set `initialFocus` and `searchInputId` props correctly', async () => {
const [firstOption, secondOption] = userProfiles;
const wrapper = shallow(
<UserProfilesPopover
title="Title"
button={<button>Toggle</button>}
closePopover={jest.fn()}
selectableProps={{
selectedOptions: [firstOption],
defaultOptions: [secondOption],
}}
isOpen
/>
);
expect(wrapper.find('EuiPopover').prop('initialFocus')).toBe('#searchInput_generated-id');
expect(wrapper.find('UserProfilesSelectable').prop('searchInputId')).toBe(
'searchInput_generated-id'
);
});
});

View file

@ -9,7 +9,7 @@
import type { EuiPopoverProps, EuiContextMenuPanelProps } from '@elastic/eui';
import type { FunctionComponent } from 'react';
import React from 'react';
import { EuiPopover, EuiContextMenuPanel } from '@elastic/eui';
import { EuiPopover, EuiContextMenuPanel, useGeneratedHtmlId } from '@elastic/eui';
import { UserProfilesSelectable, UserProfilesSelectableProps } from './user_profiles_selectable';
@ -38,10 +38,15 @@ export const UserProfilesPopover: FunctionComponent<UserProfilesPopoverProps> =
selectableProps,
...popoverProps
}) => {
const searchInputId = useGeneratedHtmlId({
prefix: 'searchInput',
conditionalId: selectableProps.searchInputId,
});
return (
<EuiPopover panelPaddingSize="none" {...popoverProps}>
<EuiPopover panelPaddingSize="none" initialFocus={`#${searchInputId}`} {...popoverProps}>
<EuiContextMenuPanel title={title}>
<UserProfilesSelectable {...selectableProps} />
<UserProfilesSelectable {...selectableProps} searchInputId={searchInputId} />
</EuiContextMenuPanel>
</EuiPopover>
);

View file

@ -200,4 +200,9 @@ describe('UserProfilesSelectable', () => {
wrapper.find('input[type="search"]').simulate('change', { target: { value: 'search' } });
expect(onSearchChange).toHaveBeenCalledWith('search', []);
});
it('should set `id` prop of search input correctly', () => {
const wrapper = mount(<UserProfilesSelectable searchInputId="testSearchField" />);
expect(wrapper.find('input[type="search"]').prop('id')).toBe('testSearchField');
});
});

View file

@ -74,10 +74,15 @@ export interface UserProfilesSelectableProps
isLoading?: boolean;
/**
* Placeholder text for search box.
* Placeholder text of search field.
*/
searchPlaceholder?: string;
/**
* Identifier of search field.
*/
searchInputId?: string;
/**
* Returns text for selected status.
* @param selectedCount Number of selected users
@ -107,6 +112,7 @@ export const UserProfilesSelectable: FunctionComponent<UserProfilesSelectablePro
emptyMessage,
errorMessage,
searchPlaceholder,
searchInputId,
selectedStatusMessage,
clearButtonLabel,
}) => {
@ -243,6 +249,7 @@ export const UserProfilesSelectable: FunctionComponent<UserProfilesSelectablePro
onChange: onSearchChange,
isLoading,
isClearable: !isLoading,
id: searchInputId,
}}
isPreFiltered
listProps={{ onFocusBadge: false }}