Focus track

Motivation

In a web application, there is often a requirement to determine whether an element or any of its descendants currently has focus, typically for accessibility purposes. Developers commonly devise their own methods to track this information. In AgnosUI, we provide a utility in core services that AgnosUI components leverage for this purpose. Utilize the globally readable signal activeElement$ to monitor the current focused item. If your focus is solely on your DOM element and its descendants, you have the option to generate a custom signal using the HasFocus factory.

Service Overview

This service exports functionality related to managing focus within a web application. It includes a readable signal, activeElement$, representing the currently active HTML element, and a factory function, createHasFocus(), that creates an object implementing the HasFocus interface.

To install the core part, open your project's terminal and run the following command:

npm i @agnos-ui/core

`activeElement$` Readable Signal

activeElement$ is a readable signal that provides information about the currently focused HTML element. When at least a consumer starts listening its value, it sets the active element to the current document.activeElement. The active element is updated each time a focusin/ focusout event is triggered on the document.documentElement. The event listeners are removed when the number of listeners fall to 0.

`createHasFocus` Factory

createHasFocus is a factory function that creates an object conforming to the HasFocus interface. It provides:

  • directive that can be apply to elements to track if the focus is on one of the elements or on one of their descendent.
  • hasFocus$ signal (that internally uses the activeElement$ signal) that say if the focus is actually among the elements (or their descendent) targeted by the directive.

Usage

Whenever you want to check which element of the DOM has the focus, you can simply import the signal activeElement$ and subscribe to it.

In action

Loading...

Example Usage `activeElement$`

import {activeElement$} from '@agnos-ui/core';}

const unsubscribe = activeElement$.subscribe((activeElement) => {
    console.log(`Tag name: ${activeElement?.tagName.toLowerCase()}, id: ${activeElement?.id}`);
})

Example Usage `HasFocus`

If you are only interested to your element and descendent, then you have to use the createHasFocus factory, apply the directive to the element, and then subscribe to the hasFocus$ signal.

import {createHasFocus} from '@agnos-ui/core';

const {directive, hasFocus$} = createHasFocus();

// Apply the directive to specific elements
// (We provide utilities to apply this in the different framework context too)
var elementWhereToTrack = document.getElementById('id');
const instance = directive(elementWhereToTrack);

// Subscribe to the hasFocus$ signal
const unsubscribe = hasFocus$.subscribe((hasFocus) => {
    console.log(`Focused: ${hasFocus}`);
});

// Cleanup
unsubscribe();
instance?.destroy();

Notes

  • The code ensures proper cleanup by removing event listeners when no longer needed.