Focus on first suitable child in sign in flow

When switching steps in the sign in flow we're essentially showing a new dialog (or at least it should behave as such) which means we'll need to reset the focus, if we don't then keyboard focus will just flow to the body whenever we change the dialog contents.
This commit is contained in:
Markus Olsson 2023-02-13 11:48:21 +01:00
parent b0c4b63ea6
commit 5c7f4a788f
2 changed files with 17 additions and 1 deletions

View file

@ -383,7 +383,7 @@ export class Dialog extends React.Component<IDialogProps, IDialogState> {
* 4. Any remaining button
*
*/
private focusFirstSuitableChild() {
public focusFirstSuitableChild() {
const dialog = this.dialogElement
if (dialog === null) {

View file

@ -41,6 +41,8 @@ const SignInWithBrowserTitle = __DARWIN__
const DefaultTitle = 'Sign in'
export class SignIn extends React.Component<ISignInProps, ISignInState> {
private readonly dialogRef = React.createRef<Dialog>()
public constructor(props: ISignInProps) {
super(props)
@ -52,6 +54,18 @@ export class SignIn extends React.Component<ISignInProps, ISignInState> {
}
}
public componentDidUpdate(prevProps: ISignInProps) {
// Whenever the sign in step changes we replace the dialog contents which
// means we need to re-focus the first suitable child element as it's
// essentially a "new" dialog we're showing only the dialog component itself
// doesn't know that.
if (prevProps.signInState !== null && this.props.signInState !== null) {
if (prevProps.signInState.kind !== this.props.signInState.kind) {
this.dialogRef.current?.focusFirstSuitableChild()
}
}
}
public componentWillReceiveProps(nextProps: ISignInProps) {
if (nextProps.signInState !== this.props.signInState) {
if (
@ -161,6 +175,7 @@ export class SignIn extends React.Component<ISignInProps, ISignInState> {
<OkCancelButtonGroup
okButtonText={primaryButtonText}
okButtonDisabled={disableSubmit}
onCancelButtonClick={this.onDismissed}
/>
</DialogFooter>
)
@ -324,6 +339,7 @@ export class SignIn extends React.Component<ISignInProps, ISignInState> {
onDismissed={this.onDismissed}
onSubmit={this.onSubmit}
loading={state.loading}
ref={this.dialogRef}
>
{errors}
{this.renderStep()}