Skip to content
Sensors

useFocus

Reactive utility that tracks whether a DOM element has focus, with two-way binding — read the current focus state and programmatically focus or blur the element.

Focus Tracking
Blurred

Click the input or use the buttons to control focus programmatically.

import {
const useRef$: {
<T = any>(initialValue: null): Ref$<T | null>;
<T = any>(initialValue: T): Ref$<T>;
<T = any>(): Ref$<T | null>;
}
useRef$
} from "@usels/core";
import {
const useFocus: (target: MaybeEventTarget, options?: DeepMaybeObservable<UseFocusOptions>) => UseFocusReturn
useFocus
} from "@usels/web";
function
function Component(): JSX.Element
Component
() {
const
const input$: Ref$<HTMLInputElement | null>
input$
=
useRef$<HTMLInputElement>(): Ref$<HTMLInputElement | null> (+2 overloads)

Core (framework-agnostic) version of useRef$. Creates an observable element ref with opaque wrapping.

  • non-null value → Ref$<T>: current, get(), peek() return T
  • null / no arg → Ref$<T | null>: current, get(), peek() return T | null

Nullability is expressed via the type parameter, mirroring T | null at the call site.

useRef$
<
interface HTMLInputElement
HTMLInputElement
>();
const {
const focused$: any

Current focus state (read/write) — set(true)→focus(), set(false)→blur()

focused$
} =
function useFocus(target: MaybeEventTarget, options?: DeepMaybeObservable<UseFocusOptions>): UseFocusReturn

Framework-agnostic reactive focus tracking for a target element with optional two-way binding.

Exposes focused$ as a read/write Observable:

  • Setting focused$.set(true) calls el.focus()
  • Setting focused$.set(false) calls el.blur()
  • DOM focus/blur events update focused$ automatically.

useFocus
(
const input$: Ref$<HTMLInputElement | null>
input$
);
return (
<
JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div
>
<
JSX.IntrinsicElements.input: DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>
input
RefAttributes<HTMLInputElement>.ref?: Ref<HTMLInputElement> | undefined

Allows getting a ref to the component instance. Once the component unmounts, React will set ref.current to null (or call the ref with null if you passed a callback ref).

ref
={
const input$: Ref$<HTMLInputElement | null>
input$
}
InputHTMLAttributes<HTMLInputElement>.placeholder?: string | undefined
placeholder
="Click to focus" />
<
JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>Focused: {
const focused$: any

Current focus state (read/write) — set(true)→focus(), set(false)→blur()

focused$
.
any
get
() ? "Yes" : "No"}</
JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>
<
JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button
DOMAttributes<HTMLButtonElement>.onClick?: MouseEventHandler<HTMLButtonElement> | undefined
onClick
={() =>
const focused$: any

Current focus state (read/write) — set(true)→focus(), set(false)→blur()

focused$
.
any
set
(true)}>Focus</
JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button
>
<
JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button
DOMAttributes<HTMLButtonElement>.onClick?: MouseEventHandler<HTMLButtonElement> | undefined
onClick
={() =>
const focused$: any

Current focus state (read/write) — set(true)→focus(), set(false)→blur()

focused$
.
any
set
(false)}>Blur</
JSX.IntrinsicElements.button: DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>
button
>
</
JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div
>
);
}

Set initialValue: true to automatically focus the element when the component mounts.

// @noErrors
import { useRef$ } from "@usels/core";
import { useFocus } from "@usels/web";
function AutoFocusInput() {
const input$ = useRef$<HTMLInputElement>();
const { focused$ } = useFocus(input$, { initialValue: true });
return <input ref={input$} />;
}

When focusVisible: true, only tracks focus that would show a visible focus indicator (matching the CSS :focus-visible pseudo-class). Mouse clicks won’t trigger focused$, but keyboard navigation (Tab) will.

// @noErrors
import { useRef$ } from "@usels/core";
import { useFocus } from "@usels/web";
function FocusVisibleButton() {
const btn$ = useRef$<HTMLButtonElement>();
const { focused$ } = useFocus(btn$, { focusVisible: true });
return <button ref={btn$}>Tab to me</button>;
}

Pass preventScroll: true to prevent the browser from scrolling to the element when programmatically focused.

const { focused$ } = useFocus(el$, { preventScroll: true });
focused$.set(true); // focuses without scrolling
ParameterTypeDescription
targetMaybeEventTarget-
optionsUseFocusOptions (optional)-
OptionTypeDefaultDescription
initialValueboolean-Auto-focus the element on mount. Default: false
focusVisibleboolean-Replicate :focus-visible behavior. Default: false
preventScrollboolean-Prevent scroll when focusing. Default: false
windowWindowSource--

UseFocusReturn

NameTypeDescription
focused$ObservableBoolean<boolean>Current focus state (read/write) — set(true)→focus(), set(false)→blur()

View on GitHub