---
description: How to work with the focus system.
title: Focus system
image: images/blockly_banner.png
---

# Focus system

The focus system keeps track of the user's location (focus) in a Blockly editor.
It is used by Blockly and by custom code to determine what component (block,
field, toolbox category, etc.) currently has focus and to move that focus to
another component.

It is important to understand the focus system so you can ensure that your
custom code works correctly with it.

## Architecture

The focus system has three parts:

- The `FocusManager` is a singleton that coordinates focus across all of
  Blockly. It is used by Blockly and by custom code to find out what component
  has Blockly focus, as well as to move Blockly focus to a different
  component. It also listens for DOM focus events, synchronizes Blockly focus
  and DOM focus, and manages the CSS classes that indicate which component has
  focus.

  The focus manager is primarily used by Blockly. It is sometimes used by
  custom code to [interact with the focus system](#use-the-focus-manager).

- An `IFocusableTree` is an independent area of a Blockly editor, such as a
  workspace or toolbox. It is composed of focusable nodes, such as blocks and
  fields. Trees can also have subtrees. For example, a mutator workspace on a
  block in the main workspace is a subtree of the main workspace.

  `IFocusableTree` is primarily used by the focus manager. Unless you write a
  custom toolbox, you probably won't need to [implement it](#custom-classes).

- An `IFocusableNode` is a Blockly component that can have focus, such as a
  block, field, or toolbox category. Focusable nodes have a DOM element that
  displays the node and which has DOM focus when the node has Blockly focus.
  Note that trees are also focusable nodes. For example, you can focus on the
  workspace as a whole.

  The methods in `IFocusableNode` are primarily called by the focus manager.

  `IFocusableNode` itself is used to represent the component that has focus.
  For example, when a user selects an item on a block's context menu, the
  block is passed to the item's callback function as an `IFocusableNode`.

  If you write custom components, you may need to [implement
  `IFocusableNode`](#custom-classes).

## Types of focus

The focus system defines a number of different types of focus.

### Blockly focus and DOM focus

The two main types of focus are Blockly focus and DOM focus.

- **Blockly focus** specifies which Blockly component (block, field, toolbox
  category, etc.) has focus. It is necessary for working at the level of
  Blockly components. For example, the keyboard navigation plugin allows users
  to use arrow keys to move from component to component, such as from a block
  to a field. Similarly, the context menu system builds a menu that is
  appropriate for the current component -- that is, it builds different menus
  for workspaces, blocks, and workspace comments.

- **DOM focus** specifies which DOM element has focus. It is necessary for
  working at the level of DOM elements. For example, [screen
  readers](https://www.afb.org/blindness-and-low-vision/using-technology/assistive-technology-products/screen-readers)
  present information about the element that currently has DOM focus and tabs
  move (change focus) from DOM element to DOM element.

The focus manager keeps Blockly focus and DOM focus in sync, so when a node
(Blockly component) has Blockly focus, its underlying DOM element has DOM focus
and vice versa.

#### Active and passive focus

Blockly focus is further divided into **active focus** and **passive focus**.
Active focus means that a node will receive user input, such as a key press.
Passive focus means that a node previously had active focus, but lost it when
the user moved to a node in another tree (for example, they moved from the
workspace to the toolbox) or away from the Blockly editor altogether. If the
tree regains focus, the passively focused node will regain active focus.

Each tree has a separate focus context. That is, at most one node in the tree
can have focus. Whether that focus is active or passive depends on whether the
tree has focus. There can be at most one node with active focus on the entire
page.

The focus manager uses different highlights (CSS classes) for actively and
passively focused nodes. These allow users to understand where they are and
where they will return to.

### Ephemeral focus

There is another type of focus called **ephemeral focus**. Separate workflows,
such as dialogs or field editors, request ephemeral focus from the focus
manager. When the focus manager grants ephemeral focus, it suspends the focus
system. From a practical standpoint, this means that such workflows can capture
and act on DOM focus events without having to worry that the focus system might
act on them as well.

When the focus manager grants ephemeral focus, it changes the actively focused
node to passive focus. It restores active focus when ephemeral focus is
returned.

## Examples

The following examples illustrate how Blockly uses the focus system. They should
help you understand how your code fits into the focus system and how your code
might use the focus system.

### Move focus with the keyboard

Suppose a block with two fields has Blockly focus, as indicated by a highlight
(CSS class) on the block's DOM element. Now suppose the user presses the right
arrow:

1.  The [keyboard navigation
    plugin](/guides/configure/keyboard-nav):
    - Receives a key press event.
    - Asks the navigation system (a part of core Blockly) to move focus to the
      "next" component.
1.  The navigation system:
    - Asks the focus manager what component has Blockly focus. The focus
      manager returns the block as an `IFocusableNode`.
    - Determines that the `IFocusableNode` is a `BlockSvg` and looks at its
      rules for navigating blocks, which state that it should move Blockly
      focus from the block as a whole to the first field on the block.
    - Tells the focus manager to move Blockly focus to the first field.
1.  The focus manager:
    - Updates its state to set Blockly focus on the first field.
    - Sets DOM focus on the field's DOM element.
    - Moves the highlight class from the block's element to the field's
      element.

### Move focus with the mouse

Now suppose that the user clicks on the second field on the block. The focus
manager:

1.  Receives a DOM `focusout` event on the first field's DOM element and a
    `focusin` event on the second field's DOM element.
1.  Determines that the DOM element that received focus corresponds to the
    second field.
1.  Updates its state to set Blockly focus on the second field. (The focus
    manager doesn't need to set DOM focus because the browser already did this.)
1.  Moves the highlight class from the first field's element to the second
    field's element.

### Other examples

Here are some other examples:

- When a user drags a block from the toolbox to the workspace, the mouse event
  handler creates a new block and calls the focus manager to set Blockly focus
  on that block.

- When a block is deleted, its `dispose` method calls the focus manager to
  move focus to the block's parent.

- [Keyboard shortcuts](/guides/configure/keyboard-shortcuts) use
  `IFocusableNode` to identify the Blockly component to which the shortcut
  applies.

- [Context menus](/guides/configure/context-menus) use
  `IFocusableNode` to identify the Blockly component on which the menu was
  invoked.

## Customizations and the focus system

When you customize Blockly, you need to make sure that your code works correctly
with the focus system. You may also use the focus system to identify and set the
currently focused node.

### Custom blocks and toolbox contents

The most common way to customize Blockly is to define custom blocks and
customize the contents of the toolbox. Neither of these actions has any affect
on the focus system.

### Custom classes

Custom classes may need to implement one or both focus interfaces
(`IFocusableTree` and `IFocusableNode`). It is not always obvious when this is
the case.

Some classes clearly need to implement focus interfaces. These include:

- A class that implements a custom toolbox. This class needs to implement
  `IFocusableTree` and `IFocusableNode`.

- Classes that create a visible component (such as a field or icon) that users
  can navigate to. These classes need to implement `IFocusableNode`.

Some classes need to implement `IFocusableNode` even though they do not create a
visible component or they create a visible component that users cannot navigate
to. These include:

- Classes that implement an interface that extends `IFocusableNode`.

  For example, the move icon in the keyboard navigation plugin displays a
  four-way arrow that indicates that the block can be moved with the arrow
  keys. The icon itself is not visible (the four-way arrow is a bubble) and
  users cannot navigate to it. However, the icon must implement
  `IFocusableNode` because icons implement`IIcon` and `IIcon` extends
  `IFocusableNode`.

- Classes used in an API that requires an `IFocusableNode`.

  For example, the `FlyoutSeparator` class creates a gap between two items in
  a flyout. It does not create any DOM elements, so it doesn't have a visible
  component and users can't navigate to it. However, it must implement
  `IFocusableNode` because it is stored in a `FlyoutItem` and the `FlyoutItem`
  constructor requires an `IFocusableNode`.

- Classes that extend a class that implements `IFocusableNode`.

  For example, `ToolboxSeparator` extends `ToolboxItem`, which implements
  `IFocusableNode`. Although toolbox separators have a visible component,
  users cannot navigate to them because they cannot be acted on and have no
  useful content.

Other classes create visible components that the user can navigate to, but do
not need to implement `IFocusableNode`. These include:

- Classes that create a visible component that manages its own focus, such as
  a field editor or a dialog. (Note that such classes do need to [take
  ephemeral focus](#ephemeral-focus) when they start and return it when they
  end. Using `WidgetDiv` or `DropDownDiv` will handle this for you.)

Finally, some classes do not interact with the focus system and do not need to
implement `IFocusableTree` or `IFocusableNode`. These include:

- Classes that create a visible component that users cannot navigate to or act
  on and which contains no information that a screen reader might use. For
  example, a purely decorative background in a game.

- Classes entirely unrelated to the focus system, such as classes that
  implement `IMetricsManager` or `IVariableMap`.

If you are uncertain whether your class will interact with the focus system,
test it with the keyboard navigation plugin. If this fails, you might need to
implement `IFocusableTree` or `IFocusableNode`. If it succeeds but you are still
unsure, read the code that uses your class to see if either interface is
required or if there are any other interactions.

#### Implement focus interfaces

The easiest way to implement `IFocusableTree` or `IFocusableNode`is to extend a
class that implements these interfaces. For example, if you're creating a custom
toolbox, extend `Toolbox`, which implements `IFocusableTree` and
`IFocusableNode`. If you're creating a custom field, extend `Field`, which
implements `IFocusableNode`. Be sure to check that your code doesn't interfere
with the focus interface code in the base class.

If you do extend a class that implements a focus interface, you generally won't
need to override any methods. The most common exception is
`IFocusableNode.canBeFocused`, which you need to override if you don't want
users to navigate to your component.

Less common is the need to override the focus callback methods (`onTreeFocus`
and `onTreeBlur` in `IFocusableTree` and `onNodeFocus` and `onNodeBlur` in
`IFocusableNode`). Note that attempting to change focus (call
`FocusManager.focusNode` or `FocusManager.focusTree`) from these methods results
in an exception.

If you write a custom component from scratch, you'll need to implement the focus
interfaces yourself. See the reference documentation for
[`IFocusableTree`](/reference/blockly.ifocusabletree) and
[`IFocusableNode`](/reference/blockly.ifocusablenode) more
information.

After you have implemented your class, test it against the keyboard navigation
plugin to verify that you can (or cannot) navigate to your component.

#### Use the focus manager

Some custom classes use the focus manager. The most common reasons to do this
are to get the currently focused node and to focus on a different node. To get
the focus manager, call `Blockly.getFocusManager`:

```js
const focusManager = Blockly.getFocusManager();
```

To get the currently focused node, call `getFocusedNode`:

```js
const focusedNode = focusManager.getFocusedNode();
// Do something with the focused node.
```

To move focus to a different node, call `focusNode`:

```js
// Move focus to a different block.
focusManager.focusNode(myOtherBlock);
```

To move focus to a tree, call `focusTree`. This also sets node focus on the
tree's root node.

```js
// Move focus to the main workspace.
focusManager.focusTree(myMainWorkspace);
```

The other common reason to use the focus manager is to take and return ephemeral
focus. The `takeEphemeralFocus` function returns a lambda that you must call to
return ephemeral focus.

```js
const returnEphemeralFocus = focusManager.takeEphemeralFocus();
// Do something.
returnEphemeralFocus();
```

If you use
[`WidgetDiv`](/guides/create-custom-blocks/fields/customizing-fields/creating#widgetdiv-sample-code)
or
[`DropDownDiv`](/guides/create-custom-blocks/fields/customizing-fields/creating#dropdowndiv-sample-code),
they will handle ephemeral focus for you.

### Tab stops

The focus system sets a tab stop (`tabindex` of `0`) on the root element of all
trees (the main workspace, the toolbox, and flyout workspaces). This allows
users to use the tab key to navigate around the main regions of a Blockly editor
and then (using the keyboard navigation plugin) use arrow keys to navigate
within those regions. Do not change these tab stops, as this will interfere with
the focus manager's ability to manage them.

You should generally avoid setting tab stops on other DOM elements used by
Blockly, as this interferes with Blockly's model of using the tab key to
navigate between areas of the editor and arrow keys within those areas. In
addition, such tab stops might not work as intended. This is because each
focusable node declares a DOM element as its focusable element. If you set a tab
stop on a descendant of the focusable element and the user tabs to that element,
the focus manager will move DOM focus to the declared focusable element.

It is safe to set tab stops on elements in your application that are outside the
Blockly editor. When the user tabs from the editor to such an element, the focus
manager changes the Blockly focus from active to passive. For accessibility, you
should set the `tabindex` property to `0` or `-1`, as recommended by the warning
in MDN's description of the [`tabindex`
attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/tabindex).

### DOM focus

For accessibility reasons, applications should avoid calling the `focus` method
on DOM elements. This is disorienting to users of screen readers, as they are
suddenly moved to an unknown location in the application.

An additional problem is that the focus manager reacts to focus events by
setting DOM focus on the nearest ancestor-or-self of the focused element that is
a declared focusable element. This may be different from the element on which
`focus` was called. (If there is no nearest focusable ancestor-or-self, such as
when `focus` is called on an element outside the Blockly editor, the focus
manager just changes the actively focused node to passive focus.)

### Positionables

Positionables are components that are positioned on top of the workspace and
implement
[`IPositionable`](/reference/blockly.ipositionable).
Examples are the trashcan and the backpack in the [backpack
plugin](https://www.npmjs.com/package/@blockly/workspace-backpack).
Built-in positionables are integrated with the focus system, but if you create
your own you should ensure that they work well with it. The built-in ones follow
this pattern:

* Implement `IFocusableNode`
* Ensure that the focusable DOM element (the one returned from
  `getFocusableElement()`) has `tabindex="0"`

Depending on the purpose of your positionable, you should also consider
registering a keyboard shortcut to perform its action (e.g. zoom in) or to
directly focus it (e.g. a workspace search field).
