ElementFocus

Reactive tracking of focus state on an element. Detects when an element gains or loses focus, and allows programmatically setting focus.

Loading demo...

Usage

angular-ts
import { Component, viewChild, ElementRef } from '@angular/core';
import { elementFocus } from '@signality/core';

@Component({
  template: `
    <input #input [class.focused]="focused()" />
    <p>{{ focused() ? 'Input is focused' : 'Input is not focused' }}</p>
  `,
})
export class FocusDemo {
  readonly input = viewChild<ElementRef>('input');
  readonly focused = elementFocus(this.input); 
}

Parameters

ParameterTypeDescription
targetMaybeElementSignal<HTMLElement>Target element to track
optionsElementFocusOptionsOptional configuration (see Options below)

Options

The ElementFocusOptions extends CreateSignalOptions<boolean> and WithInjector:

OptionTypeDefaultDescription
equalValueEqualityFn<boolean>-Custom equality function (see more)
debugNamestring-Debug name for the signal (development only)
focusVisiblebooleanfalseTrack focus using the :focus-visible pseudo-class. The browser uses heuristics to determine when focus should be visually indicated (e.g., keyboard navigation, programmatic focus). See MDN: :focus-visible for details.
preventScrollbooleanfalsePrevent scrolling to the element when it is focused
injectorInjector-Optional injector for DI context

Return Value

Returns a WritableSignal<boolean> containing true when the element has focus, false otherwise. You can use .set(true) to programmatically focus the element and .set(false) to blur it.

Examples

Focus ring

angular-ts
import { Component, viewChild, ElementRef } from '@angular/core';
import { elementFocus } from '@signality/core';

@Component({
  template: `
    <button #btn [class.focus-ring]="focused()">
      Click or Tab to me
    </button>
  `,
})
export class FocusRing {
  readonly btn = viewChild<ElementRef>('btn');
  readonly focused = elementFocus(this.btn, { focusVisible: true });
}

Programmatic focus setting

angular-ts
import { Component, viewChild, ElementRef, signal } from '@angular/core';
import { elementFocus } from '@signality/core';

@Component({
  template: `
    <div class="input-wrapper">
      <input #input [(ngModel)]="query" />
      @if (query()) {
        <button (click)="clear()">×</button>
      }
    </div>
  `,
})
export class SearchInput {
  readonly inputEl = viewChild('input', { read: ElementRef });
  readonly inputFocused = elementFocus(this.inputEl);
  readonly query = signal('');

  clear() {
    this.query.set('');
    this.inputFocused.set(true); // Return focus after clearing
  }
}

SSR Compatibility

On the server, the signal initializes with false.

Type Definitions

typescript
interface ElementFocusOptions extends CreateSignalOptions<boolean>, WithInjector {
  readonly focusVisible?: boolean;
  readonly preventScroll?: boolean;
}

function elementFocus(
  target: MaybeElementSignal<HTMLElement>,
  options?: ElementFocusOptions
): WritableSignal<boolean>;
Edit this page on GitHub Last updated: Mar 28, 2026, 23:36:01