CreateImageWizard: Make steps autofocus on first input upon render

The default behavior of Data Driven Forms when moving to the previous or
next step is to maintain focus on the previous or next button,
respectively.

This commit makes the UI more friendly to keyboard users by focusing
on the first input element of a given step when it is rendered.

Whenever possible, autofocus is achieved by passing components the
autoFocus prop. When this is not possible, then useRef and useEffect hooks
are used to set focus.

At the moment, it is not possible to autofocus the image output step's
release selector or the file system configuration step's toggle using the
above methods. This is because these PatternFly components do not
currently pass props to the appropriate child component and do not
support ref forwarding. The best option for autofocus in these cases is
currently being investigated.
This commit is contained in:
lucasgarfield 2022-03-10 18:29:19 +01:00 committed by jkozol
parent f6142bc4cb
commit c28e0d15b6
7 changed files with 103 additions and 3 deletions

View file

@ -213,6 +213,12 @@ const Packages = ({ defaultArch, ...props }) => {
}
};
const firstInputElement = useRef(null);
useEffect(() => {
firstInputElement.current?.focus();
}, []);
return (
<DualListSelector>
<DualListSelectorPane
@ -221,6 +227,7 @@ const Packages = ({ defaultArch, ...props }) => {
placeholder="Search for a package"
data-testid="search-available-pkgs-input"
value={ packagesSearchName.current }
ref={ firstInputElement }
onFocus={ () => setFocus('available') }
onBlur={ () => setFocus('') }
onChange={ (val) => {

View file

@ -112,7 +112,7 @@ const ReviewStep = () => {
</DescriptionListGroup>
</DescriptionList>
<Tabs isFilled activeKey={ activeTabKey } onSelect={ handleTabClick } className="pf-u-w-75">
<Tab eventKey={ 0 } title={ <TabTitleText>Target environment</TabTitleText> } data-testid='tab-target'>
<Tab eventKey={ 0 } title={ <TabTitleText>Target environment</TabTitleText> } data-testid='tab-target' autoFocus>
<List isPlain iconSize="large">
{getState()?.values?.['target-environment']?.aws &&
<ListItem icon={ <img className='provider-icon' src='/apps/frontend-assets/partners-icons/aws.svg' /> }>

View file

@ -22,6 +22,7 @@ export default {
name: 'image-name',
type: 'text',
label: 'Image name',
autoFocus: true,
validate: [
{
type: validatorTypes.PATTERN,

View file

@ -77,14 +77,15 @@ export default {
{
component: 'radio-popover',
label: 'Type',
isRequired: true,
Popover: PopoverInfo,
name: 'google-account-type',
initialValue: 'googleAccount',
options: Object.entries(googleAccType).map(([ value, label ]) => ({
label: value === 'domain' ? 'Google Workspace domain or Cloud Identity domain' : label,
value
value,
autoFocus: value === 'googleAccount' ? true : false
})),
isRequired: true,
validate: [
{
type: validatorTypes.REQUIRED,

View file

@ -45,6 +45,7 @@ export default {
label: 'Tenant ID',
required: true,
isRequired: true,
autoFocus: true,
validate: [
{
type: validatorTypes.REQUIRED,

View file

@ -43,6 +43,7 @@ export default {
description: 'Includes Subscriptions and Red Hat Insights',
value: 'register-now-insights',
'data-testid': 'radio-register-now-insights',
autoFocus: true,
},
{
label: 'Register image instances only',