diff --git a/packages/frontend/component/src/hooks/focus-and-select.ts b/packages/frontend/component/src/hooks/focus-and-select.ts new file mode 100644 index 0000000000..edd92c5eaa --- /dev/null +++ b/packages/frontend/component/src/hooks/focus-and-select.ts @@ -0,0 +1,33 @@ +import { useLayoutEffect, useRef } from 'react'; + +export const useAutoFocus = ( + autoFocus?: boolean +) => { + const ref = useRef(null); + + useLayoutEffect(() => { + if (ref.current && autoFocus) { + // to avoid clicking on something focusable(e.g MenuItem), + // then the input will not be focused + setTimeout(() => { + ref.current?.focus(); + }, 0); + } + }, [autoFocus]); + + return ref; +}; + +export const useAutoSelect = ( + autoSelect?: boolean +) => { + const ref = useAutoFocus(autoSelect); + + useLayoutEffect(() => { + if (ref.current && autoSelect) { + ref.current?.select(); + } + }, [autoSelect, ref]); + + return ref; +}; diff --git a/packages/frontend/component/src/hooks/index.ts b/packages/frontend/component/src/hooks/index.ts new file mode 100644 index 0000000000..2c69d81da9 --- /dev/null +++ b/packages/frontend/component/src/hooks/index.ts @@ -0,0 +1 @@ +export { useAutoFocus, useAutoSelect } from './focus-and-select'; diff --git a/packages/frontend/component/src/ui/button/button.tsx b/packages/frontend/component/src/ui/button/button.tsx index df7a55d53d..ed25560e3e 100644 --- a/packages/frontend/component/src/ui/button/button.tsx +++ b/packages/frontend/component/src/ui/button/button.tsx @@ -7,6 +7,7 @@ import type { } from 'react'; import { cloneElement, forwardRef, useCallback } from 'react'; +import { useAutoFocus } from '../../hooks'; import { Loading } from '../loading'; import { Tooltip, type TooltipProps } from '../tooltip'; import * as styles from './button.css'; @@ -120,12 +121,15 @@ export const Button = forwardRef( tooltip, tooltipShortcut, tooltipOptions, + autoFocus, onClick, ...otherProps }, - ref + upstreamRef ) => { + const ref = useAutoFocus(autoFocus); + const handleClick = useCallback( (e: MouseEvent) => { if (loading || disabled) return; @@ -134,11 +138,22 @@ export const Button = forwardRef( [disabled, loading, onClick] ); + const buttonRef = (el: HTMLButtonElement | null) => { + ref.current = el; + if (upstreamRef) { + if (typeof upstreamRef === 'function') { + upstreamRef(el); + } else { + upstreamRef.current = el; + } + } + }; + return (