From d6f21c6d313888cdb7bd7777533bc3f004748eb4 Mon Sep 17 00:00:00 2001 From: Dmitry Krupenya Date: Fri, 29 May 2020 18:15:40 +0300 Subject: [PATCH] feat: set focus on first form element CB-124 --- .../AuthProviderForm/AuthProviderForm.tsx | 36 ++++++++++--------- webapp/packages/core/src/blocks/InFocus.tsx | 31 ++++++++++++++++ webapp/packages/core/src/blocks/index.ts | 1 + 3 files changed, 51 insertions(+), 17 deletions(-) create mode 100644 webapp/packages/core/src/blocks/InFocus.tsx diff --git a/webapp/packages/authentication/src/Dialog/AuthProviderForm/AuthProviderForm.tsx b/webapp/packages/authentication/src/Dialog/AuthProviderForm/AuthProviderForm.tsx index c67d609472..e9ecc83e03 100644 --- a/webapp/packages/authentication/src/Dialog/AuthProviderForm/AuthProviderForm.tsx +++ b/webapp/packages/authentication/src/Dialog/AuthProviderForm/AuthProviderForm.tsx @@ -10,7 +10,7 @@ import { observer } from 'mobx-react'; import { useCallback } from 'react'; import styled from 'reshadow'; -import { InputField } from '@dbeaver/core/blocks'; +import { InputField, InFocus } from '@dbeaver/core/blocks'; import { useStyles } from '@dbeaver/core/theming'; import { AuthProvider } from '../../AuthProviderService'; @@ -32,21 +32,23 @@ export const AuthProviderForm = observer(function AuthProviderForm({ }, [credentials]); return styled(useStyles(formStyles))( - - {provider.credentialParameters.map(parameter => parameter.user && ( - - handleChange(parameter.id, value)} - disabled={authenticate} - mod='surface' - > - {parameter.displayName} - - - ))} - + + + {provider.credentialParameters.map(parameter => parameter.user && ( + + handleChange(parameter.id, value)} + disabled={authenticate} + mod='surface' + > + {parameter.displayName} + + + ))} + + ); }); diff --git a/webapp/packages/core/src/blocks/InFocus.tsx b/webapp/packages/core/src/blocks/InFocus.tsx new file mode 100644 index 0000000000..6fc4b358ed --- /dev/null +++ b/webapp/packages/core/src/blocks/InFocus.tsx @@ -0,0 +1,31 @@ +import React, { + useEffect, useRef, ReactElement, MutableRefObject +} from 'react'; + +type InFocusProps = { + children: ReactElement; +} + +export function InFocus({ children }: InFocusProps) { + const isFirstRender: MutableRefObject = useRef(true); + const childRef: MutableRefObject = useRef(null); + + useEffect(() => { + if (isFirstRender.current) { + isFirstRender.current = false; + if (childRef.current !== null) { + const firstFocusable: HTMLElement | null = childRef.current + .querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'); + if (firstFocusable) { + firstFocusable.focus(); + } + + } + } + }); + const childElement = React.Children.only(children); + return React.cloneElement( + childElement, + { ref: (el: HTMLElement) => childRef.current = el } + ); +} diff --git a/webapp/packages/core/src/blocks/index.ts b/webapp/packages/core/src/blocks/index.ts index 004e30dead..868d2f8f7a 100644 --- a/webapp/packages/core/src/blocks/index.ts +++ b/webapp/packages/core/src/blocks/index.ts @@ -21,4 +21,5 @@ export * from './ShadowInput'; export * from './StaticImage'; export * from './SubmittingForm'; export * from './TextPlaceholder'; +export * from './InFocus'; export * from './useClipboard';