Skip to content

Manage focus boundaries and keyboard shortcuts contexts with focus scopes.

Overview

Focus scopes allow you to create isolated focus boundaries within your Handsontable instance, enabling seamless focus switching between the grid and your custom UI elements. They automatically manage keyboard shortcuts contexts and provide fine-grained control over which elements can receive focus and which shortcuts are active.

  1. Access the FocusScopeManager API:

    hot.getFocusScopeManager();
  2. Register a focus scope with a container element:

    const focusScopeManager = hot.getFocusScopeManager();
    focusScopeManager.registerScope('customScope', containerElement, {
    shortcutsContextName: 'plugin:customScope',
    onActivate: (focusSource) => {
    // Focus the first focusable element in your plugin's UI
    // container
    },
    });

Focus scope types

Focus scopes come in two types, each with different behavior:

TypeDescription
inline (default)The scope is inline and allows the rest of the component to receive focus in the order of the rendered elements in the DOM.
modalThe scope is modal and blocks the rest of the component from receiving focus. Only elements within the scope can be focused.

Inline scopes

Inline scopes allow natural tab navigation through the DOM. Users can navigate to other parts of the grid using the Tab or Shift+Tab keys.

const focusScopeManager = hot.getFocusScopeManager();
focusScopeManager.registerScope('pagination', paginationContainer, {
type: 'inline',
shortcutsContextName: 'plugin:pagination',
});

The example below demonstrates how the inline focus scope works using the pagination plugin as an example. Let’s focus on the top text input and press the Tab key through the grid to see how the focus moves to the bottom text input and how the internal state changes.

JavaScript
import { HotTable, HotColumn } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
import { useState, useEffect, useRef, useCallback, memo } from 'react';
// register Handsontable's modules
registerAllModules();
const data = [
{ model: 'Trail Helmet', price: 1298.14, sellDate: '2025-08-31', sellTime: '14:12', inStock: true },
{ model: 'Windbreaker Jacket', price: 178.9, sellDate: '2025-05-10', sellTime: '22:26', inStock: false },
{ model: 'Cycling Cap', price: 288.1, sellDate: '2025-09-15', sellTime: '09:37', inStock: true },
{ model: 'HL Mountain Frame', price: 94.49, sellDate: '2025-01-17', sellTime: '14:19', inStock: false },
{ model: 'Racing Socks', price: 430.38, sellDate: '2025-05-10', sellTime: '13:42', inStock: true },
{ model: 'Racing Socks', price: 138.85, sellDate: '2025-09-20', sellTime: '14:48', inStock: true },
{ model: 'HL Mountain Frame', price: 1909.63, sellDate: '2025-09-05', sellTime: '09:35', inStock: false },
{ model: 'Carbon Handlebar', price: 1080.7, sellDate: '2025-10-24', sellTime: '22:58', inStock: false },
{ model: 'Aero Bottle', price: 1571.13, sellDate: '2025-05-24', sellTime: '00:24', inStock: true },
{ model: 'Windbreaker Jacket', price: 919.09, sellDate: '2025-07-16', sellTime: '19:11', inStock: true },
{ model: 'HL Road Tire', price: 886.22, sellDate: '2025-09-09', sellTime: '00:42', inStock: false },
{ model: 'Speed Gloves', price: 635.13, sellDate: '2025-11-17', sellTime: '12:45', inStock: true },
{ model: 'Trail Helmet', price: 1440.64, sellDate: '2025-01-03', sellTime: '20:16', inStock: false },
{ model: 'Aero Bottle', price: 944.63, sellDate: '2025-11-15', sellTime: '16:14', inStock: false },
{ model: 'Windbreaker Jacket', price: 1161.43, sellDate: '2025-06-24', sellTime: '13:19', inStock: false },
{ model: 'LED Bike Light', price: 1012.5, sellDate: '2025-05-01', sellTime: '17:30', inStock: false },
{ model: 'Windbreaker Jacket', price: 635.37, sellDate: '2025-05-14', sellTime: '09:05', inStock: true },
{ model: 'Road Tire Tube', price: 1421.27, sellDate: '2025-01-31', sellTime: '13:33', inStock: true },
{ model: 'Action Camera', price: 1019.05, sellDate: '2025-12-07', sellTime: '01:26', inStock: false },
{ model: 'Carbon Handlebar', price: 603.96, sellDate: '2025-09-13', sellTime: '04:10', inStock: false },
{ model: 'Aero Bottle', price: 1334.03, sellDate: '2025-01-24', sellTime: '03:29', inStock: false },
{ model: 'Road Tire Tube', price: 1841.17, sellDate: '2025-05-22', sellTime: '01:45', inStock: false },
{ model: 'Aero Bottle', price: 1622.05, sellDate: '2025-01-13', sellTime: '08:30', inStock: true },
{ model: 'Comfort Saddle', price: 1456.24, sellDate: '2025-07-20', sellTime: '03:39', inStock: false },
{ model: 'Windbreaker Jacket', price: 1736.96, sellDate: '2025-09-25', sellTime: '00:43', inStock: true },
{ model: 'Fitness Watch', price: 1075.31, sellDate: '2025-11-07', sellTime: '17:47', inStock: true },
{ model: 'Cycling Cap', price: 726.01, sellDate: '2025-10-28', sellTime: '12:44', inStock: true },
{ model: 'Road Tire Tube', price: 601.99, sellDate: '2025-09-22', sellTime: '00:26', inStock: true },
{ model: 'Speed Gloves', price: 1758.26, sellDate: '2025-10-04', sellTime: '04:59', inStock: true },
{ model: 'Speed Gloves', price: 564.35, sellDate: '2025-07-10', sellTime: '18:21', inStock: true },
{ model: 'Hydration Pack', price: 954.84, sellDate: '2025-11-02', sellTime: '00:59', inStock: false },
{ model: 'Cycling Cap', price: 1511.5, sellDate: '2025-02-11', sellTime: '02:38', inStock: false },
{ model: 'HL Road Tire', price: 269.6, sellDate: '2025-06-18', sellTime: '04:58', inStock: false },
{ model: 'Road Tire Tube', price: 435.07, sellDate: '2025-07-22', sellTime: '23:12', inStock: false },
{ model: 'Fitness Watch', price: 1187.8, sellDate: '2025-08-13', sellTime: '10:19', inStock: true },
{ model: 'Racing Socks', price: 770.19, sellDate: '2025-02-02', sellTime: '20:37', inStock: true },
{ model: 'Carbon Handlebar', price: 60.41, sellDate: '2025-12-27', sellTime: '20:30', inStock: true },
{ model: 'Racing Socks', price: 944.21, sellDate: '2025-05-23', sellTime: '18:43', inStock: false },
{ model: 'Racing Socks', price: 621.96, sellDate: '2025-12-12', sellTime: '04:59', inStock: false },
{ model: 'HL Road Tire', price: 774.91, sellDate: '2025-06-02', sellTime: '03:48', inStock: true },
{ model: 'LED Bike Light', price: 1205.29, sellDate: '2025-04-15', sellTime: '22:08', inStock: false },
{ model: 'Racing Socks', price: 388.19, sellDate: '2025-05-24', sellTime: '08:36', inStock: true },
{ model: 'Windbreaker Jacket', price: 267.88, sellDate: '2025-05-25', sellTime: '15:00', inStock: true },
{ model: 'LED Bike Light', price: 283.72, sellDate: '2025-09-26', sellTime: '02:16', inStock: true },
{ model: 'Comfort Saddle', price: 1782.91, sellDate: '2025-03-07', sellTime: '09:43', inStock: false },
{ model: 'Trail Helmet', price: 1943.46, sellDate: '2025-06-05', sellTime: '01:49', inStock: true },
{ model: 'Speed Gloves', price: 1737.8, sellDate: '2025-09-18', sellTime: '14:21', inStock: true },
{ model: 'Road Tire Tube', price: 354.89, sellDate: '2025-08-11', sellTime: '02:03', inStock: true },
{ model: 'Hydration Pack', price: 1490.45, sellDate: '2025-12-04', sellTime: '02:23', inStock: true },
{ model: 'LED Bike Light', price: 844.48, sellDate: '2025-09-22', sellTime: '02:29', inStock: true },
{ model: 'Road Tire Tube', price: 1965.77, sellDate: '2025-02-10', sellTime: '23:52', inStock: false },
{ model: 'Action Camera', price: 522.33, sellDate: '2025-11-11', sellTime: '16:50', inStock: false },
{ model: 'Comfort Saddle', price: 109.4, sellDate: '2025-05-13', sellTime: '11:41', inStock: true },
{ model: 'Hydration Pack', price: 1067.76, sellDate: '2025-08-07', sellTime: '05:04', inStock: false },
{ model: 'Speed Gloves', price: 1738.77, sellDate: '2025-01-28', sellTime: '08:38', inStock: false },
{ model: 'Aero Bottle', price: 1600.35, sellDate: '2025-01-29', sellTime: '00:36', inStock: false },
{ model: 'Speed Gloves', price: 524.91, sellDate: '2025-12-15', sellTime: '12:56', inStock: true },
{ model: 'Windbreaker Jacket', price: 1780.51, sellDate: '2025-09-23', sellTime: '05:02', inStock: false },
{ model: 'Comfort Saddle', price: 1955.0, sellDate: '2025-09-29', sellTime: '13:03', inStock: false },
{ model: 'Speed Gloves', price: 957.4, sellDate: '2025-08-06', sellTime: '03:19', inStock: true },
{ model: 'Fitness Watch', price: 193.72, sellDate: '2025-04-01', sellTime: '19:49', inStock: false },
{ model: 'Speed Gloves', price: 677.94, sellDate: '2025-10-11', sellTime: '22:25', inStock: false },
{ model: 'LED Bike Light', price: 1155.9, sellDate: '2025-03-02', sellTime: '11:36', inStock: false },
{ model: 'LED Bike Light', price: 586.82, sellDate: '2025-11-22', sellTime: '20:29', inStock: false },
{ model: 'Action Camera', price: 406.41, sellDate: '2025-10-25', sellTime: '11:10', inStock: false },
{ model: 'Road Tire Tube', price: 595.55, sellDate: '2025-05-24', sellTime: '01:30', inStock: false },
{ model: 'Racing Socks', price: 1078.63, sellDate: '2025-04-28', sellTime: '02:57', inStock: true },
{ model: 'Cycling Cap', price: 1781.04, sellDate: '2025-10-07', sellTime: '06:58', inStock: false },
{ model: 'Trail Helmet', price: 181.8, sellDate: '2025-10-02', sellTime: '20:04', inStock: false },
{ model: 'HL Mountain Frame', price: 489.39, sellDate: '2025-07-20', sellTime: '10:51', inStock: true },
{ model: 'HL Road Tire', price: 1964.04, sellDate: '2025-07-10', sellTime: '15:01', inStock: true },
{ model: 'Action Camera', price: 1321.19, sellDate: '2025-02-02', sellTime: '13:39', inStock: true },
{ model: 'Trail Helmet', price: 1311.09, sellDate: '2025-12-27', sellTime: '14:45', inStock: false },
{ model: 'Windbreaker Jacket', price: 1573.57, sellDate: '2025-09-20', sellTime: '20:31', inStock: false },
{ model: 'Speed Gloves', price: 338.01, sellDate: '2025-10-22', sellTime: '18:56', inStock: false },
{ model: 'Carbon Handlebar', price: 309.18, sellDate: '2025-11-10', sellTime: '15:20', inStock: true },
{ model: 'LED Bike Light', price: 1289.0, sellDate: '2025-08-22', sellTime: '15:34', inStock: true },
{ model: 'Action Camera', price: 1655.66, sellDate: '2025-06-12', sellTime: '15:38', inStock: false },
{ model: 'Hydration Pack', price: 1126.33, sellDate: '2025-09-15', sellTime: '06:29', inStock: false },
{ model: 'Racing Socks', price: 157.45, sellDate: '2025-01-26', sellTime: '19:25', inStock: true },
{ model: 'Aero Bottle', price: 1707.67, sellDate: '2025-02-02', sellTime: '17:34', inStock: true },
{ model: 'Road Tire Tube', price: 601.95, sellDate: '2025-04-14', sellTime: '08:02', inStock: true },
{ model: 'HL Road Tire', price: 118.42, sellDate: '2025-02-08', sellTime: '06:08', inStock: false },
{ model: 'Racing Socks', price: 1721.99, sellDate: '2025-10-13', sellTime: '09:01', inStock: true },
{ model: 'Action Camera', price: 1620.39, sellDate: '2025-07-18', sellTime: '05:53', inStock: false },
{ model: 'Trail Helmet', price: 1051.16, sellDate: '2025-01-21', sellTime: '09:44', inStock: true },
{ model: 'Fitness Watch', price: 1534.64, sellDate: '2025-02-27', sellTime: '09:19', inStock: true },
{ model: 'Comfort Saddle', price: 984.12, sellDate: '2025-03-16', sellTime: '07:24', inStock: false },
{ model: 'Comfort Saddle', price: 1316.13, sellDate: '2025-02-11', sellTime: '11:01', inStock: true },
{ model: 'Carbon Handlebar', price: 774.69, sellDate: '2025-10-17', sellTime: '11:38', inStock: false },
{ model: 'Road Tire Tube', price: 1887.19, sellDate: '2025-10-19', sellTime: '06:02', inStock: true },
{ model: 'Cycling Cap', price: 519.44, sellDate: '2025-10-21', sellTime: '03:54', inStock: true },
{ model: 'Trail Helmet', price: 1149.2, sellDate: '2025-04-24', sellTime: '04:40', inStock: false },
{ model: 'Carbon Handlebar', price: 915.24, sellDate: '2025-07-10', sellTime: '05:22', inStock: true },
{ model: 'Comfort Saddle', price: 1625.63, sellDate: '2025-03-31', sellTime: '23:55', inStock: true },
{ model: 'Racing Socks', price: 143.76, sellDate: '2025-12-02', sellTime: '07:25', inStock: true },
{ model: 'Cycling Cap', price: 981.24, sellDate: '2025-08-09', sellTime: '19:52', inStock: false },
{ model: 'Comfort Saddle', price: 779.4, sellDate: '2025-06-12', sellTime: '17:08', inStock: true },
{ model: 'Carbon Handlebar', price: 1512.24, sellDate: '2025-07-27', sellTime: '07:02', inStock: true },
{ model: 'Cycling Cap', price: 444.79, sellDate: '2025-09-11', sellTime: '10:05', inStock: false },
];
const Table = memo(({ hotTableRef, data }) => {
return (
<HotTable
ref={hotTableRef}
pagination={true}
autoRowSize={true}
tabNavigation={false}
data={data}
width="100%"
height={250}
stretchH="all"
contextMenu={true}
rowHeaders={true}
colHeaders={true}
autoWrapRow={true}
autoWrapCol={true}
licenseKey="non-commercial-and-evaluation"
>
<HotColumn title="Model" type="text" data="model" width={150} headerClassName="htLeft" />
<HotColumn
title="Price"
type="numeric"
data="price"
width={80}
locale="en-US"
numericFormat={{ style: 'currency', currency: 'USD', minimumFractionDigits: 2 }}
className="htRight"
headerClassName="htRight"
/>
<HotColumn
title="Date"
type="intl-date"
data="sellDate"
width={131}
locale="en-US"
dateFormat={{ month: 'short', day: 'numeric', year: 'numeric' }}
className="htRight"
headerClassName="htRight"
/>
<HotColumn
title="Time"
type="intl-time"
data="sellTime"
width={81}
timeFormat={{ hour: '2-digit', minute: '2-digit', hour12: true }}
className="htRight"
headerClassName="htRight"
/>
<HotColumn title="In stock" type="checkbox" data="inStock" className="htCenter" headerClassName="htCenter" />
</HotTable>
);
});
const DebugInfo = memo(({ debugInfo }) => (
<>
<strong>Debug information:</strong>
<table className="debug-table">
<colgroup>
<col />
<col style={{ width: '200px' }} />
</colgroup>
<tbody>
<tr>
<td>
<code>isListening()</code>
</td>
<td>
<code className="isListening">{String(debugInfo.isListening)}</code>
</td>
</tr>
<tr>
<td>
<code>getFocusScopeManager().getActiveScopeId()</code>
</td>
<td>
<code className="focusScope">{String(debugInfo.focusScope)}</code>
</td>
</tr>
<tr>
<td>
<code>getShortcutManager().getActiveContextName()</code>
</td>
<td>
<code className="shortcutsContext">{String(debugInfo.shortcutsContext)}</code>
</td>
</tr>
</tbody>
</table>
</>
));
const ExampleComponent = () => {
const [debugInfo, setDebugInfo] = useState({
isListening: false,
focusScope: null,
shortcutsContext: null,
});
const hotRef = useRef(null);
const updateDebugInfo = useCallback(() => {
const hotInstance = hotRef.current?.hotInstance;
if (hotInstance) {
setDebugInfo({
isListening: hotInstance.isListening(),
focusScope: hotInstance.getFocusScopeManager().getActiveScopeId(),
shortcutsContext: hotInstance.getShortcutManager().getActiveContextName(),
});
}
}, []);
useEffect(() => {
const interval = setInterval(updateDebugInfo, 200);
return () => clearInterval(interval);
}, [updateDebugInfo]);
return (
<div className="example-container">
<input
className="placeholder-input"
type="text"
name="focusable-text-input"
placeholder="Focusable top text input"
/>
<Table hotTableRef={hotRef} data={data} />
<input
className="placeholder-input"
type="text"
name="focusable-text-input"
placeholder="Focusable bottom text input"
/>
<DebugInfo debugInfo={debugInfo} />
</div>
);
};
export default ExampleComponent;
TypeScript
import { HotTable, HotColumn } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
import { useState, useEffect, useRef, useCallback, memo } from 'react';
// register Handsontable's modules
registerAllModules();
const data = [
{ model: 'Trail Helmet', price: 1298.14, sellDate: '2025-08-31', sellTime: '14:12', inStock: true },
{ model: 'Windbreaker Jacket', price: 178.9, sellDate: '2025-05-10', sellTime: '22:26', inStock: false },
{ model: 'Cycling Cap', price: 288.1, sellDate: '2025-09-15', sellTime: '09:37', inStock: true },
{ model: 'HL Mountain Frame', price: 94.49, sellDate: '2025-01-17', sellTime: '14:19', inStock: false },
{ model: 'Racing Socks', price: 430.38, sellDate: '2025-05-10', sellTime: '13:42', inStock: true },
{ model: 'Racing Socks', price: 138.85, sellDate: '2025-09-20', sellTime: '14:48', inStock: true },
{ model: 'HL Mountain Frame', price: 1909.63, sellDate: '2025-09-05', sellTime: '09:35', inStock: false },
{ model: 'Carbon Handlebar', price: 1080.7, sellDate: '2025-10-24', sellTime: '22:58', inStock: false },
{ model: 'Aero Bottle', price: 1571.13, sellDate: '2025-05-24', sellTime: '00:24', inStock: true },
{ model: 'Windbreaker Jacket', price: 919.09, sellDate: '2025-07-16', sellTime: '19:11', inStock: true },
{ model: 'HL Road Tire', price: 886.22, sellDate: '2025-09-09', sellTime: '00:42', inStock: false },
{ model: 'Speed Gloves', price: 635.13, sellDate: '2025-11-17', sellTime: '12:45', inStock: true },
{ model: 'Trail Helmet', price: 1440.64, sellDate: '2025-01-03', sellTime: '20:16', inStock: false },
{ model: 'Aero Bottle', price: 944.63, sellDate: '2025-11-15', sellTime: '16:14', inStock: false },
{ model: 'Windbreaker Jacket', price: 1161.43, sellDate: '2025-06-24', sellTime: '13:19', inStock: false },
{ model: 'LED Bike Light', price: 1012.5, sellDate: '2025-05-01', sellTime: '17:30', inStock: false },
{ model: 'Windbreaker Jacket', price: 635.37, sellDate: '2025-05-14', sellTime: '09:05', inStock: true },
{ model: 'Road Tire Tube', price: 1421.27, sellDate: '2025-01-31', sellTime: '13:33', inStock: true },
{ model: 'Action Camera', price: 1019.05, sellDate: '2025-12-07', sellTime: '01:26', inStock: false },
{ model: 'Carbon Handlebar', price: 603.96, sellDate: '2025-09-13', sellTime: '04:10', inStock: false },
{ model: 'Aero Bottle', price: 1334.03, sellDate: '2025-01-24', sellTime: '03:29', inStock: false },
{ model: 'Road Tire Tube', price: 1841.17, sellDate: '2025-05-22', sellTime: '01:45', inStock: false },
{ model: 'Aero Bottle', price: 1622.05, sellDate: '2025-01-13', sellTime: '08:30', inStock: true },
{ model: 'Comfort Saddle', price: 1456.24, sellDate: '2025-07-20', sellTime: '03:39', inStock: false },
{ model: 'Windbreaker Jacket', price: 1736.96, sellDate: '2025-09-25', sellTime: '00:43', inStock: true },
{ model: 'Fitness Watch', price: 1075.31, sellDate: '2025-11-07', sellTime: '17:47', inStock: true },
{ model: 'Cycling Cap', price: 726.01, sellDate: '2025-10-28', sellTime: '12:44', inStock: true },
{ model: 'Road Tire Tube', price: 601.99, sellDate: '2025-09-22', sellTime: '00:26', inStock: true },
{ model: 'Speed Gloves', price: 1758.26, sellDate: '2025-10-04', sellTime: '04:59', inStock: true },
{ model: 'Speed Gloves', price: 564.35, sellDate: '2025-07-10', sellTime: '18:21', inStock: true },
{ model: 'Hydration Pack', price: 954.84, sellDate: '2025-11-02', sellTime: '00:59', inStock: false },
{ model: 'Cycling Cap', price: 1511.5, sellDate: '2025-02-11', sellTime: '02:38', inStock: false },
{ model: 'HL Road Tire', price: 269.6, sellDate: '2025-06-18', sellTime: '04:58', inStock: false },
{ model: 'Road Tire Tube', price: 435.07, sellDate: '2025-07-22', sellTime: '23:12', inStock: false },
{ model: 'Fitness Watch', price: 1187.8, sellDate: '2025-08-13', sellTime: '10:19', inStock: true },
{ model: 'Racing Socks', price: 770.19, sellDate: '2025-02-02', sellTime: '20:37', inStock: true },
{ model: 'Carbon Handlebar', price: 60.41, sellDate: '2025-12-27', sellTime: '20:30', inStock: true },
{ model: 'Racing Socks', price: 944.21, sellDate: '2025-05-23', sellTime: '18:43', inStock: false },
{ model: 'Racing Socks', price: 621.96, sellDate: '2025-12-12', sellTime: '04:59', inStock: false },
{ model: 'HL Road Tire', price: 774.91, sellDate: '2025-06-02', sellTime: '03:48', inStock: true },
{ model: 'LED Bike Light', price: 1205.29, sellDate: '2025-04-15', sellTime: '22:08', inStock: false },
{ model: 'Racing Socks', price: 388.19, sellDate: '2025-05-24', sellTime: '08:36', inStock: true },
{ model: 'Windbreaker Jacket', price: 267.88, sellDate: '2025-05-25', sellTime: '15:00', inStock: true },
{ model: 'LED Bike Light', price: 283.72, sellDate: '2025-09-26', sellTime: '02:16', inStock: true },
{ model: 'Comfort Saddle', price: 1782.91, sellDate: '2025-03-07', sellTime: '09:43', inStock: false },
{ model: 'Trail Helmet', price: 1943.46, sellDate: '2025-06-05', sellTime: '01:49', inStock: true },
{ model: 'Speed Gloves', price: 1737.8, sellDate: '2025-09-18', sellTime: '14:21', inStock: true },
{ model: 'Road Tire Tube', price: 354.89, sellDate: '2025-08-11', sellTime: '02:03', inStock: true },
{ model: 'Hydration Pack', price: 1490.45, sellDate: '2025-12-04', sellTime: '02:23', inStock: true },
{ model: 'LED Bike Light', price: 844.48, sellDate: '2025-09-22', sellTime: '02:29', inStock: true },
{ model: 'Road Tire Tube', price: 1965.77, sellDate: '2025-02-10', sellTime: '23:52', inStock: false },
{ model: 'Action Camera', price: 522.33, sellDate: '2025-11-11', sellTime: '16:50', inStock: false },
{ model: 'Comfort Saddle', price: 109.4, sellDate: '2025-05-13', sellTime: '11:41', inStock: true },
{ model: 'Hydration Pack', price: 1067.76, sellDate: '2025-08-07', sellTime: '05:04', inStock: false },
{ model: 'Speed Gloves', price: 1738.77, sellDate: '2025-01-28', sellTime: '08:38', inStock: false },
{ model: 'Aero Bottle', price: 1600.35, sellDate: '2025-01-29', sellTime: '00:36', inStock: false },
{ model: 'Speed Gloves', price: 524.91, sellDate: '2025-12-15', sellTime: '12:56', inStock: true },
{ model: 'Windbreaker Jacket', price: 1780.51, sellDate: '2025-09-23', sellTime: '05:02', inStock: false },
{ model: 'Comfort Saddle', price: 1955.0, sellDate: '2025-09-29', sellTime: '13:03', inStock: false },
{ model: 'Speed Gloves', price: 957.4, sellDate: '2025-08-06', sellTime: '03:19', inStock: true },
{ model: 'Fitness Watch', price: 193.72, sellDate: '2025-04-01', sellTime: '19:49', inStock: false },
{ model: 'Speed Gloves', price: 677.94, sellDate: '2025-10-11', sellTime: '22:25', inStock: false },
{ model: 'LED Bike Light', price: 1155.9, sellDate: '2025-03-02', sellTime: '11:36', inStock: false },
{ model: 'LED Bike Light', price: 586.82, sellDate: '2025-11-22', sellTime: '20:29', inStock: false },
{ model: 'Action Camera', price: 406.41, sellDate: '2025-10-25', sellTime: '11:10', inStock: false },
{ model: 'Road Tire Tube', price: 595.55, sellDate: '2025-05-24', sellTime: '01:30', inStock: false },
{ model: 'Racing Socks', price: 1078.63, sellDate: '2025-04-28', sellTime: '02:57', inStock: true },
{ model: 'Cycling Cap', price: 1781.04, sellDate: '2025-10-07', sellTime: '06:58', inStock: false },
{ model: 'Trail Helmet', price: 181.8, sellDate: '2025-10-02', sellTime: '20:04', inStock: false },
{ model: 'HL Mountain Frame', price: 489.39, sellDate: '2025-07-20', sellTime: '10:51', inStock: true },
{ model: 'HL Road Tire', price: 1964.04, sellDate: '2025-07-10', sellTime: '15:01', inStock: true },
{ model: 'Action Camera', price: 1321.19, sellDate: '2025-02-02', sellTime: '13:39', inStock: true },
{ model: 'Trail Helmet', price: 1311.09, sellDate: '2025-12-27', sellTime: '14:45', inStock: false },
{ model: 'Windbreaker Jacket', price: 1573.57, sellDate: '2025-09-20', sellTime: '20:31', inStock: false },
{ model: 'Speed Gloves', price: 338.01, sellDate: '2025-10-22', sellTime: '18:56', inStock: false },
{ model: 'Carbon Handlebar', price: 309.18, sellDate: '2025-11-10', sellTime: '15:20', inStock: true },
{ model: 'LED Bike Light', price: 1289.0, sellDate: '2025-08-22', sellTime: '15:34', inStock: true },
{ model: 'Action Camera', price: 1655.66, sellDate: '2025-06-12', sellTime: '15:38', inStock: false },
{ model: 'Hydration Pack', price: 1126.33, sellDate: '2025-09-15', sellTime: '06:29', inStock: false },
{ model: 'Racing Socks', price: 157.45, sellDate: '2025-01-26', sellTime: '19:25', inStock: true },
{ model: 'Aero Bottle', price: 1707.67, sellDate: '2025-02-02', sellTime: '17:34', inStock: true },
{ model: 'Road Tire Tube', price: 601.95, sellDate: '2025-04-14', sellTime: '08:02', inStock: true },
{ model: 'HL Road Tire', price: 118.42, sellDate: '2025-02-08', sellTime: '06:08', inStock: false },
{ model: 'Racing Socks', price: 1721.99, sellDate: '2025-10-13', sellTime: '09:01', inStock: true },
{ model: 'Action Camera', price: 1620.39, sellDate: '2025-07-18', sellTime: '05:53', inStock: false },
{ model: 'Trail Helmet', price: 1051.16, sellDate: '2025-01-21', sellTime: '09:44', inStock: true },
{ model: 'Fitness Watch', price: 1534.64, sellDate: '2025-02-27', sellTime: '09:19', inStock: true },
{ model: 'Comfort Saddle', price: 984.12, sellDate: '2025-03-16', sellTime: '07:24', inStock: false },
{ model: 'Comfort Saddle', price: 1316.13, sellDate: '2025-02-11', sellTime: '11:01', inStock: true },
{ model: 'Carbon Handlebar', price: 774.69, sellDate: '2025-10-17', sellTime: '11:38', inStock: false },
{ model: 'Road Tire Tube', price: 1887.19, sellDate: '2025-10-19', sellTime: '06:02', inStock: true },
{ model: 'Cycling Cap', price: 519.44, sellDate: '2025-10-21', sellTime: '03:54', inStock: true },
{ model: 'Trail Helmet', price: 1149.2, sellDate: '2025-04-24', sellTime: '04:40', inStock: false },
{ model: 'Carbon Handlebar', price: 915.24, sellDate: '2025-07-10', sellTime: '05:22', inStock: true },
{ model: 'Comfort Saddle', price: 1625.63, sellDate: '2025-03-31', sellTime: '23:55', inStock: true },
{ model: 'Racing Socks', price: 143.76, sellDate: '2025-12-02', sellTime: '07:25', inStock: true },
{ model: 'Cycling Cap', price: 981.24, sellDate: '2025-08-09', sellTime: '19:52', inStock: false },
{ model: 'Comfort Saddle', price: 779.4, sellDate: '2025-06-12', sellTime: '17:08', inStock: true },
{ model: 'Carbon Handlebar', price: 1512.24, sellDate: '2025-07-27', sellTime: '07:02', inStock: true },
{ model: 'Cycling Cap', price: 444.79, sellDate: '2025-09-11', sellTime: '10:05', inStock: false },
];
const Table = memo(({ hotTableRef, data }) => {
return (
<HotTable
ref={hotTableRef}
pagination={true}
autoRowSize={true}
tabNavigation={false}
data={data}
width="100%"
height={250}
stretchH="all"
contextMenu={true}
rowHeaders={true}
colHeaders={true}
autoWrapRow={true}
autoWrapCol={true}
licenseKey="non-commercial-and-evaluation"
>
<HotColumn title="Model" type="text" data="model" width={150} headerClassName="htLeft" />
<HotColumn
title="Price"
type="numeric"
data="price"
width={80}
locale="en-US" numericFormat={{ style: 'currency', currency: 'USD', minimumFractionDigits: 2 }}
className="htRight"
headerClassName="htRight"
/>
<HotColumn
title="Date"
type="intl-date"
data="sellDate"
width={131}
locale="en-US" dateFormat={{ month: 'short', day: 'numeric', year: 'numeric' }}
className="htRight"
headerClassName="htRight"
/>
<HotColumn
title="Time"
type="intl-time"
data="sellTime"
width={81}
timeFormat={{ hour: '2-digit', minute: '2-digit', hour12: true }}
className="htRight"
headerClassName="htRight"
/>
<HotColumn title="In stock" type="checkbox" data="inStock" className="htCenter" headerClassName="htCenter" />
</HotTable>
);
});
const DebugInfo = memo(({ debugInfo }) => (
<>
<strong>Debug information:</strong>
<table className="debug-table">
<colgroup>
<col />
<col style={{ width: '200px' }} />
</colgroup>
<tbody>
<tr>
<td>
<code>isListening()</code>
</td>
<td>
<code className="isListening">{String(debugInfo.isListening)}</code>
</td>
</tr>
<tr>
<td>
<code>getFocusScopeManager().getActiveScopeId()</code>
</td>
<td>
<code className="focusScope">{String(debugInfo.focusScope)}</code>
</td>
</tr>
<tr>
<td>
<code>getShortcutManager().getActiveContextName()</code>
</td>
<td>
<code className="shortcutsContext">{String(debugInfo.shortcutsContext)}</code>
</td>
</tr>
</tbody>
</table>
</>
));
const ExampleComponent = () => {
const [debugInfo, setDebugInfo] = useState({
isListening: false,
focusScope: null,
shortcutsContext: null,
});
const hotRef = useRef(null);
const updateDebugInfo = useCallback(() => {
const hotInstance = hotRef.current?.hotInstance;
if (hotInstance) {
setDebugInfo({
isListening: hotInstance.isListening(),
focusScope: hotInstance.getFocusScopeManager().getActiveScopeId(),
shortcutsContext: hotInstance.getShortcutManager().getActiveContextName(),
});
}
}, []);
useEffect(() => {
const interval = setInterval(updateDebugInfo, 200);
return () => clearInterval(interval);
}, [updateDebugInfo]);
return (
<div className="example-container">
<input
className="placeholder-input"
type="text"
name="focusable-text-input"
placeholder="Focusable top text input"
/>
<Table hotTableRef={hotRef} data={data} />
<input
className="placeholder-input"
type="text"
name="focusable-text-input"
placeholder="Focusable bottom text input"
/>
<DebugInfo debugInfo={debugInfo} />
</div>
);
};
export default ExampleComponent;
CSS
.placeholder-input {
max-width: 20rem;
padding: 0.4rem 0.625rem;
font-size: var(--sl-text-sm);
line-height: 1.25rem;
color: var(--sl-color-text);
background: none;
border: 1px solid var(--sl-color-gray-5);
border-radius: 0;
outline: none;
}
.placeholder-input::placeholder {
color: var(--sl-color-gray-3);
}
.placeholder-input:focus {
border-color: var(--sl-color-accent);
}
.example-container {
gap: 1rem;
display: flex;
flex-direction: column;
}
.example-container > strong {
font-size: 0.875rem;
font-weight: 600;
color: var(--sl-color-white);
margin: 0.5rem 0 0;
}
.example-container .debug-table {
font-size: var(--sl-text-sm);
border-collapse: collapse;
width: 100%;
}
.example-container .debug-table td {
padding: 0.4rem 0.75rem !important;
border-bottom: 1px solid var(--sl-color-gray-5);
color: var(--sl-color-gray-2);
}
.example-container .debug-table td:last-child {
font-family: var(--sl-font-mono, ui-monospace, monospace);
}
.example-container .debug-table td code {
font-size: var(--sl-text-xs);
}

Modal scopes have a priority over inline scopes. If a modal scope is active, the inline scopes will not be activated. This is useful for dialogs, popups, or any UI that may overlap other inline scopes and need to be activated first.

const focusScopeManager = hot.getFocusScopeManager();
focusScopeManager.registerScope('dialog', dialogContainerElement, {
type: 'modal',
shortcutsContextName: 'plugin:dialog',
// Only activate the scope if the dialog is open
runOnlyIf: () => isDialogOpen(),
});

The example below demonstrates how the modal focus scope works using the dialog plugin as an example. The dialog scope takes over focus management for all inline scopes (grid and pagination) automatically, even when the dialog element appears after the inline scope elements in the DOM.

JavaScript
import { HotTable, HotColumn } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
import { useState, useEffect, useRef, useCallback, memo } from 'react';
// register Handsontable's modules
registerAllModules();
const data = [
{ model: 'Trail Helmet', price: 1298.14, sellDate: '2025-08-31', sellTime: '14:12', inStock: true },
{ model: 'Windbreaker Jacket', price: 178.9, sellDate: '2025-05-10', sellTime: '22:26', inStock: false },
{ model: 'Cycling Cap', price: 288.1, sellDate: '2025-09-15', sellTime: '09:37', inStock: true },
{ model: 'HL Mountain Frame', price: 94.49, sellDate: '2025-01-17', sellTime: '14:19', inStock: false },
{ model: 'Racing Socks', price: 430.38, sellDate: '2025-05-10', sellTime: '13:42', inStock: true },
{ model: 'Racing Socks', price: 138.85, sellDate: '2025-09-20', sellTime: '14:48', inStock: true },
{ model: 'HL Mountain Frame', price: 1909.63, sellDate: '2025-09-05', sellTime: '09:35', inStock: false },
{ model: 'Carbon Handlebar', price: 1080.7, sellDate: '2025-10-24', sellTime: '22:58', inStock: false },
{ model: 'Aero Bottle', price: 1571.13, sellDate: '2025-05-24', sellTime: '00:24', inStock: true },
{ model: 'Windbreaker Jacket', price: 919.09, sellDate: '2025-07-16', sellTime: '19:11', inStock: true },
{ model: 'HL Road Tire', price: 886.22, sellDate: '2025-09-09', sellTime: '00:42', inStock: false },
{ model: 'Speed Gloves', price: 635.13, sellDate: '2025-11-17', sellTime: '12:45', inStock: true },
{ model: 'Trail Helmet', price: 1440.64, sellDate: '2025-01-03', sellTime: '20:16', inStock: false },
{ model: 'Aero Bottle', price: 944.63, sellDate: '2025-11-15', sellTime: '16:14', inStock: false },
{ model: 'Windbreaker Jacket', price: 1161.43, sellDate: '2025-06-24', sellTime: '13:19', inStock: false },
{ model: 'LED Bike Light', price: 1012.5, sellDate: '2025-05-01', sellTime: '17:30', inStock: false },
{ model: 'Windbreaker Jacket', price: 635.37, sellDate: '2025-05-14', sellTime: '09:05', inStock: true },
{ model: 'Road Tire Tube', price: 1421.27, sellDate: '2025-01-31', sellTime: '13:33', inStock: true },
{ model: 'Action Camera', price: 1019.05, sellDate: '2025-12-07', sellTime: '01:26', inStock: false },
{ model: 'Carbon Handlebar', price: 603.96, sellDate: '2025-09-13', sellTime: '04:10', inStock: false },
{ model: 'Aero Bottle', price: 1334.03, sellDate: '2025-01-24', sellTime: '03:29', inStock: false },
{ model: 'Road Tire Tube', price: 1841.17, sellDate: '2025-05-22', sellTime: '01:45', inStock: false },
{ model: 'Aero Bottle', price: 1622.05, sellDate: '2025-01-13', sellTime: '08:30', inStock: true },
{ model: 'Comfort Saddle', price: 1456.24, sellDate: '2025-07-20', sellTime: '03:39', inStock: false },
{ model: 'Windbreaker Jacket', price: 1736.96, sellDate: '2025-09-25', sellTime: '00:43', inStock: true },
{ model: 'Fitness Watch', price: 1075.31, sellDate: '2025-11-07', sellTime: '17:47', inStock: true },
{ model: 'Cycling Cap', price: 726.01, sellDate: '2025-10-28', sellTime: '12:44', inStock: true },
{ model: 'Road Tire Tube', price: 601.99, sellDate: '2025-09-22', sellTime: '00:26', inStock: true },
{ model: 'Speed Gloves', price: 1758.26, sellDate: '2025-10-04', sellTime: '04:59', inStock: true },
{ model: 'Speed Gloves', price: 564.35, sellDate: '2025-07-10', sellTime: '18:21', inStock: true },
{ model: 'Hydration Pack', price: 954.84, sellDate: '2025-11-02', sellTime: '00:59', inStock: false },
{ model: 'Cycling Cap', price: 1511.5, sellDate: '2025-02-11', sellTime: '02:38', inStock: false },
{ model: 'HL Road Tire', price: 269.6, sellDate: '2025-06-18', sellTime: '04:58', inStock: false },
{ model: 'Road Tire Tube', price: 435.07, sellDate: '2025-07-22', sellTime: '23:12', inStock: false },
{ model: 'Fitness Watch', price: 1187.8, sellDate: '2025-08-13', sellTime: '10:19', inStock: true },
{ model: 'Racing Socks', price: 770.19, sellDate: '2025-02-02', sellTime: '20:37', inStock: true },
{ model: 'Carbon Handlebar', price: 60.41, sellDate: '2025-12-27', sellTime: '20:30', inStock: true },
{ model: 'Racing Socks', price: 944.21, sellDate: '2025-05-23', sellTime: '18:43', inStock: false },
{ model: 'Racing Socks', price: 621.96, sellDate: '2025-12-12', sellTime: '04:59', inStock: false },
{ model: 'HL Road Tire', price: 774.91, sellDate: '2025-06-02', sellTime: '03:48', inStock: true },
{ model: 'LED Bike Light', price: 1205.29, sellDate: '2025-04-15', sellTime: '22:08', inStock: false },
{ model: 'Racing Socks', price: 388.19, sellDate: '2025-05-24', sellTime: '08:36', inStock: true },
{ model: 'Windbreaker Jacket', price: 267.88, sellDate: '2025-05-25', sellTime: '15:00', inStock: true },
{ model: 'LED Bike Light', price: 283.72, sellDate: '2025-09-26', sellTime: '02:16', inStock: true },
{ model: 'Comfort Saddle', price: 1782.91, sellDate: '2025-03-07', sellTime: '09:43', inStock: false },
{ model: 'Trail Helmet', price: 1943.46, sellDate: '2025-06-05', sellTime: '01:49', inStock: true },
{ model: 'Speed Gloves', price: 1737.8, sellDate: '2025-09-18', sellTime: '14:21', inStock: true },
{ model: 'Road Tire Tube', price: 354.89, sellDate: '2025-08-11', sellTime: '02:03', inStock: true },
{ model: 'Hydration Pack', price: 1490.45, sellDate: '2025-12-04', sellTime: '02:23', inStock: true },
{ model: 'LED Bike Light', price: 844.48, sellDate: '2025-09-22', sellTime: '02:29', inStock: true },
{ model: 'Road Tire Tube', price: 1965.77, sellDate: '2025-02-10', sellTime: '23:52', inStock: false },
{ model: 'Action Camera', price: 522.33, sellDate: '2025-11-11', sellTime: '16:50', inStock: false },
{ model: 'Comfort Saddle', price: 109.4, sellDate: '2025-05-13', sellTime: '11:41', inStock: true },
{ model: 'Hydration Pack', price: 1067.76, sellDate: '2025-08-07', sellTime: '05:04', inStock: false },
{ model: 'Speed Gloves', price: 1738.77, sellDate: '2025-01-28', sellTime: '08:38', inStock: false },
{ model: 'Aero Bottle', price: 1600.35, sellDate: '2025-01-29', sellTime: '00:36', inStock: false },
{ model: 'Speed Gloves', price: 524.91, sellDate: '2025-12-15', sellTime: '12:56', inStock: true },
{ model: 'Windbreaker Jacket', price: 1780.51, sellDate: '2025-09-23', sellTime: '05:02', inStock: false },
{ model: 'Comfort Saddle', price: 1955.0, sellDate: '2025-09-29', sellTime: '13:03', inStock: false },
{ model: 'Speed Gloves', price: 957.4, sellDate: '2025-08-06', sellTime: '03:19', inStock: true },
{ model: 'Fitness Watch', price: 193.72, sellDate: '2025-04-01', sellTime: '19:49', inStock: false },
{ model: 'Speed Gloves', price: 677.94, sellDate: '2025-10-11', sellTime: '22:25', inStock: false },
{ model: 'LED Bike Light', price: 1155.9, sellDate: '2025-03-02', sellTime: '11:36', inStock: false },
{ model: 'LED Bike Light', price: 586.82, sellDate: '2025-11-22', sellTime: '20:29', inStock: false },
{ model: 'Action Camera', price: 406.41, sellDate: '2025-10-25', sellTime: '11:10', inStock: false },
{ model: 'Road Tire Tube', price: 595.55, sellDate: '2025-05-24', sellTime: '01:30', inStock: false },
{ model: 'Racing Socks', price: 1078.63, sellDate: '2025-04-28', sellTime: '02:57', inStock: true },
{ model: 'Cycling Cap', price: 1781.04, sellDate: '2025-10-07', sellTime: '06:58', inStock: false },
{ model: 'Trail Helmet', price: 181.8, sellDate: '2025-10-02', sellTime: '20:04', inStock: false },
{ model: 'HL Mountain Frame', price: 489.39, sellDate: '2025-07-20', sellTime: '10:51', inStock: true },
{ model: 'HL Road Tire', price: 1964.04, sellDate: '2025-07-10', sellTime: '15:01', inStock: true },
{ model: 'Action Camera', price: 1321.19, sellDate: '2025-02-02', sellTime: '13:39', inStock: true },
{ model: 'Trail Helmet', price: 1311.09, sellDate: '2025-12-27', sellTime: '14:45', inStock: false },
{ model: 'Windbreaker Jacket', price: 1573.57, sellDate: '2025-09-20', sellTime: '20:31', inStock: false },
{ model: 'Speed Gloves', price: 338.01, sellDate: '2025-10-22', sellTime: '18:56', inStock: false },
{ model: 'Carbon Handlebar', price: 309.18, sellDate: '2025-11-10', sellTime: '15:20', inStock: true },
{ model: 'LED Bike Light', price: 1289.0, sellDate: '2025-08-22', sellTime: '15:34', inStock: true },
{ model: 'Action Camera', price: 1655.66, sellDate: '2025-06-12', sellTime: '15:38', inStock: false },
{ model: 'Hydration Pack', price: 1126.33, sellDate: '2025-09-15', sellTime: '06:29', inStock: false },
{ model: 'Racing Socks', price: 157.45, sellDate: '2025-01-26', sellTime: '19:25', inStock: true },
{ model: 'Aero Bottle', price: 1707.67, sellDate: '2025-02-02', sellTime: '17:34', inStock: true },
{ model: 'Road Tire Tube', price: 601.95, sellDate: '2025-04-14', sellTime: '08:02', inStock: true },
{ model: 'HL Road Tire', price: 118.42, sellDate: '2025-02-08', sellTime: '06:08', inStock: false },
{ model: 'Racing Socks', price: 1721.99, sellDate: '2025-10-13', sellTime: '09:01', inStock: true },
{ model: 'Action Camera', price: 1620.39, sellDate: '2025-07-18', sellTime: '05:53', inStock: false },
{ model: 'Trail Helmet', price: 1051.16, sellDate: '2025-01-21', sellTime: '09:44', inStock: true },
{ model: 'Fitness Watch', price: 1534.64, sellDate: '2025-02-27', sellTime: '09:19', inStock: true },
{ model: 'Comfort Saddle', price: 984.12, sellDate: '2025-03-16', sellTime: '07:24', inStock: false },
{ model: 'Comfort Saddle', price: 1316.13, sellDate: '2025-02-11', sellTime: '11:01', inStock: true },
{ model: 'Carbon Handlebar', price: 774.69, sellDate: '2025-10-17', sellTime: '11:38', inStock: false },
{ model: 'Road Tire Tube', price: 1887.19, sellDate: '2025-10-19', sellTime: '06:02', inStock: true },
{ model: 'Cycling Cap', price: 519.44, sellDate: '2025-10-21', sellTime: '03:54', inStock: true },
{ model: 'Trail Helmet', price: 1149.2, sellDate: '2025-04-24', sellTime: '04:40', inStock: false },
{ model: 'Carbon Handlebar', price: 915.24, sellDate: '2025-07-10', sellTime: '05:22', inStock: true },
{ model: 'Comfort Saddle', price: 1625.63, sellDate: '2025-03-31', sellTime: '23:55', inStock: true },
{ model: 'Racing Socks', price: 143.76, sellDate: '2025-12-02', sellTime: '07:25', inStock: true },
{ model: 'Cycling Cap', price: 981.24, sellDate: '2025-08-09', sellTime: '19:52', inStock: false },
{ model: 'Comfort Saddle', price: 779.4, sellDate: '2025-06-12', sellTime: '17:08', inStock: true },
{ model: 'Carbon Handlebar', price: 1512.24, sellDate: '2025-07-27', sellTime: '07:02', inStock: true },
{ model: 'Cycling Cap', price: 444.79, sellDate: '2025-09-11', sellTime: '10:05', inStock: false },
];
const Table = memo(({ hotTableRef, data }) => {
return (
<HotTable
ref={hotTableRef}
pagination={true}
dialog={true}
autoRowSize={true}
tabNavigation={false}
data={data}
width="100%"
height={250}
stretchH="all"
contextMenu={true}
rowHeaders={true}
colHeaders={true}
autoWrapRow={true}
autoWrapCol={true}
licenseKey="non-commercial-and-evaluation"
>
<HotColumn title="Model" type="text" data="model" width={150} headerClassName="htLeft" />
<HotColumn
title="Price"
type="numeric"
data="price"
width={80}
locale="en-US"
numericFormat={{ style: 'currency', currency: 'USD', minimumFractionDigits: 2 }}
className="htRight"
headerClassName="htRight"
/>
<HotColumn
title="Date"
type="intl-date"
data="sellDate"
width={131}
locale="en-US"
dateFormat={{ month: 'short', day: 'numeric', year: 'numeric' }}
className="htRight"
headerClassName="htRight"
/>
<HotColumn
title="Time"
type="intl-time"
data="sellTime"
width={81}
timeFormat={{ hour: '2-digit', minute: '2-digit', hour12: true }}
className="htRight"
headerClassName="htRight"
/>
<HotColumn title="In stock" type="checkbox" data="inStock" className="htCenter" headerClassName="htCenter" />
</HotTable>
);
});
const DebugInfo = memo(({ debugInfo }) => (
<>
<strong>Debug information:</strong>
<table className="debug-table">
<colgroup>
<col />
<col style={{ width: '200px' }} />
</colgroup>
<tbody>
<tr>
<td>
<code>isListening()</code>
</td>
<td>
<code className="isListening">{String(debugInfo.isListening)}</code>
</td>
</tr>
<tr>
<td>
<code>getFocusScopeManager().getActiveScopeId()</code>
</td>
<td>
<code className="focusScope">{String(debugInfo.focusScope)}</code>
</td>
</tr>
<tr>
<td>
<code>getShortcutManager().getActiveContextName()</code>
</td>
<td>
<code className="shortcutsContext">{String(debugInfo.shortcutsContext)}</code>
</td>
</tr>
</tbody>
</table>
</>
));
const ExampleComponent = () => {
const [debugInfo, setDebugInfo] = useState({
isListening: false,
focusScope: null,
shortcutsContext: null,
});
const hotRef = useRef(null);
const updateDebugInfo = useCallback(() => {
const hotInstance = hotRef.current?.hotInstance;
if (hotInstance) {
setDebugInfo({
isListening: hotInstance.isListening(),
focusScope: hotInstance.getFocusScopeManager().getActiveScopeId(),
shortcutsContext: hotInstance.getShortcutManager().getActiveContextName(),
});
}
}, []);
useEffect(() => {
const hotInstance = hotRef.current?.hotInstance;
if (hotInstance) {
hotInstance.getPlugin('dialog').show({
content: 'This is a simple text message displayed in the dialog.',
closable: true,
background: 'semi-transparent',
});
}
}, []);
useEffect(() => {
const interval = setInterval(updateDebugInfo, 200);
return () => clearInterval(interval);
}, [updateDebugInfo]);
return (
<div className="example-container">
<input
className="placeholder-input"
type="text"
name="focusable-text-input"
placeholder="Focusable top text input"
/>
<Table hotTableRef={hotRef} data={data} />
<input
className="placeholder-input"
type="text"
name="focusable-text-input"
placeholder="Focusable bottom text input"
/>
<DebugInfo debugInfo={debugInfo} />
</div>
);
};
export default ExampleComponent;
TypeScript
import { HotTable, HotColumn } from '@handsontable/react-wrapper';
import { registerAllModules } from 'handsontable/registry';
import { useState, useEffect, useRef, useCallback, memo } from 'react';
// register Handsontable's modules
registerAllModules();
const data = [
{ model: 'Trail Helmet', price: 1298.14, sellDate: '2025-08-31', sellTime: '14:12', inStock: true },
{ model: 'Windbreaker Jacket', price: 178.9, sellDate: '2025-05-10', sellTime: '22:26', inStock: false },
{ model: 'Cycling Cap', price: 288.1, sellDate: '2025-09-15', sellTime: '09:37', inStock: true },
{ model: 'HL Mountain Frame', price: 94.49, sellDate: '2025-01-17', sellTime: '14:19', inStock: false },
{ model: 'Racing Socks', price: 430.38, sellDate: '2025-05-10', sellTime: '13:42', inStock: true },
{ model: 'Racing Socks', price: 138.85, sellDate: '2025-09-20', sellTime: '14:48', inStock: true },
{ model: 'HL Mountain Frame', price: 1909.63, sellDate: '2025-09-05', sellTime: '09:35', inStock: false },
{ model: 'Carbon Handlebar', price: 1080.7, sellDate: '2025-10-24', sellTime: '22:58', inStock: false },
{ model: 'Aero Bottle', price: 1571.13, sellDate: '2025-05-24', sellTime: '00:24', inStock: true },
{ model: 'Windbreaker Jacket', price: 919.09, sellDate: '2025-07-16', sellTime: '19:11', inStock: true },
{ model: 'HL Road Tire', price: 886.22, sellDate: '2025-09-09', sellTime: '00:42', inStock: false },
{ model: 'Speed Gloves', price: 635.13, sellDate: '2025-11-17', sellTime: '12:45', inStock: true },
{ model: 'Trail Helmet', price: 1440.64, sellDate: '2025-01-03', sellTime: '20:16', inStock: false },
{ model: 'Aero Bottle', price: 944.63, sellDate: '2025-11-15', sellTime: '16:14', inStock: false },
{ model: 'Windbreaker Jacket', price: 1161.43, sellDate: '2025-06-24', sellTime: '13:19', inStock: false },
{ model: 'LED Bike Light', price: 1012.5, sellDate: '2025-05-01', sellTime: '17:30', inStock: false },
{ model: 'Windbreaker Jacket', price: 635.37, sellDate: '2025-05-14', sellTime: '09:05', inStock: true },
{ model: 'Road Tire Tube', price: 1421.27, sellDate: '2025-01-31', sellTime: '13:33', inStock: true },
{ model: 'Action Camera', price: 1019.05, sellDate: '2025-12-07', sellTime: '01:26', inStock: false },
{ model: 'Carbon Handlebar', price: 603.96, sellDate: '2025-09-13', sellTime: '04:10', inStock: false },
{ model: 'Aero Bottle', price: 1334.03, sellDate: '2025-01-24', sellTime: '03:29', inStock: false },
{ model: 'Road Tire Tube', price: 1841.17, sellDate: '2025-05-22', sellTime: '01:45', inStock: false },
{ model: 'Aero Bottle', price: 1622.05, sellDate: '2025-01-13', sellTime: '08:30', inStock: true },
{ model: 'Comfort Saddle', price: 1456.24, sellDate: '2025-07-20', sellTime: '03:39', inStock: false },
{ model: 'Windbreaker Jacket', price: 1736.96, sellDate: '2025-09-25', sellTime: '00:43', inStock: true },
{ model: 'Fitness Watch', price: 1075.31, sellDate: '2025-11-07', sellTime: '17:47', inStock: true },
{ model: 'Cycling Cap', price: 726.01, sellDate: '2025-10-28', sellTime: '12:44', inStock: true },
{ model: 'Road Tire Tube', price: 601.99, sellDate: '2025-09-22', sellTime: '00:26', inStock: true },
{ model: 'Speed Gloves', price: 1758.26, sellDate: '2025-10-04', sellTime: '04:59', inStock: true },
{ model: 'Speed Gloves', price: 564.35, sellDate: '2025-07-10', sellTime: '18:21', inStock: true },
{ model: 'Hydration Pack', price: 954.84, sellDate: '2025-11-02', sellTime: '00:59', inStock: false },
{ model: 'Cycling Cap', price: 1511.5, sellDate: '2025-02-11', sellTime: '02:38', inStock: false },
{ model: 'HL Road Tire', price: 269.6, sellDate: '2025-06-18', sellTime: '04:58', inStock: false },
{ model: 'Road Tire Tube', price: 435.07, sellDate: '2025-07-22', sellTime: '23:12', inStock: false },
{ model: 'Fitness Watch', price: 1187.8, sellDate: '2025-08-13', sellTime: '10:19', inStock: true },
{ model: 'Racing Socks', price: 770.19, sellDate: '2025-02-02', sellTime: '20:37', inStock: true },
{ model: 'Carbon Handlebar', price: 60.41, sellDate: '2025-12-27', sellTime: '20:30', inStock: true },
{ model: 'Racing Socks', price: 944.21, sellDate: '2025-05-23', sellTime: '18:43', inStock: false },
{ model: 'Racing Socks', price: 621.96, sellDate: '2025-12-12', sellTime: '04:59', inStock: false },
{ model: 'HL Road Tire', price: 774.91, sellDate: '2025-06-02', sellTime: '03:48', inStock: true },
{ model: 'LED Bike Light', price: 1205.29, sellDate: '2025-04-15', sellTime: '22:08', inStock: false },
{ model: 'Racing Socks', price: 388.19, sellDate: '2025-05-24', sellTime: '08:36', inStock: true },
{ model: 'Windbreaker Jacket', price: 267.88, sellDate: '2025-05-25', sellTime: '15:00', inStock: true },
{ model: 'LED Bike Light', price: 283.72, sellDate: '2025-09-26', sellTime: '02:16', inStock: true },
{ model: 'Comfort Saddle', price: 1782.91, sellDate: '2025-03-07', sellTime: '09:43', inStock: false },
{ model: 'Trail Helmet', price: 1943.46, sellDate: '2025-06-05', sellTime: '01:49', inStock: true },
{ model: 'Speed Gloves', price: 1737.8, sellDate: '2025-09-18', sellTime: '14:21', inStock: true },
{ model: 'Road Tire Tube', price: 354.89, sellDate: '2025-08-11', sellTime: '02:03', inStock: true },
{ model: 'Hydration Pack', price: 1490.45, sellDate: '2025-12-04', sellTime: '02:23', inStock: true },
{ model: 'LED Bike Light', price: 844.48, sellDate: '2025-09-22', sellTime: '02:29', inStock: true },
{ model: 'Road Tire Tube', price: 1965.77, sellDate: '2025-02-10', sellTime: '23:52', inStock: false },
{ model: 'Action Camera', price: 522.33, sellDate: '2025-11-11', sellTime: '16:50', inStock: false },
{ model: 'Comfort Saddle', price: 109.4, sellDate: '2025-05-13', sellTime: '11:41', inStock: true },
{ model: 'Hydration Pack', price: 1067.76, sellDate: '2025-08-07', sellTime: '05:04', inStock: false },
{ model: 'Speed Gloves', price: 1738.77, sellDate: '2025-01-28', sellTime: '08:38', inStock: false },
{ model: 'Aero Bottle', price: 1600.35, sellDate: '2025-01-29', sellTime: '00:36', inStock: false },
{ model: 'Speed Gloves', price: 524.91, sellDate: '2025-12-15', sellTime: '12:56', inStock: true },
{ model: 'Windbreaker Jacket', price: 1780.51, sellDate: '2025-09-23', sellTime: '05:02', inStock: false },
{ model: 'Comfort Saddle', price: 1955.0, sellDate: '2025-09-29', sellTime: '13:03', inStock: false },
{ model: 'Speed Gloves', price: 957.4, sellDate: '2025-08-06', sellTime: '03:19', inStock: true },
{ model: 'Fitness Watch', price: 193.72, sellDate: '2025-04-01', sellTime: '19:49', inStock: false },
{ model: 'Speed Gloves', price: 677.94, sellDate: '2025-10-11', sellTime: '22:25', inStock: false },
{ model: 'LED Bike Light', price: 1155.9, sellDate: '2025-03-02', sellTime: '11:36', inStock: false },
{ model: 'LED Bike Light', price: 586.82, sellDate: '2025-11-22', sellTime: '20:29', inStock: false },
{ model: 'Action Camera', price: 406.41, sellDate: '2025-10-25', sellTime: '11:10', inStock: false },
{ model: 'Road Tire Tube', price: 595.55, sellDate: '2025-05-24', sellTime: '01:30', inStock: false },
{ model: 'Racing Socks', price: 1078.63, sellDate: '2025-04-28', sellTime: '02:57', inStock: true },
{ model: 'Cycling Cap', price: 1781.04, sellDate: '2025-10-07', sellTime: '06:58', inStock: false },
{ model: 'Trail Helmet', price: 181.8, sellDate: '2025-10-02', sellTime: '20:04', inStock: false },
{ model: 'HL Mountain Frame', price: 489.39, sellDate: '2025-07-20', sellTime: '10:51', inStock: true },
{ model: 'HL Road Tire', price: 1964.04, sellDate: '2025-07-10', sellTime: '15:01', inStock: true },
{ model: 'Action Camera', price: 1321.19, sellDate: '2025-02-02', sellTime: '13:39', inStock: true },
{ model: 'Trail Helmet', price: 1311.09, sellDate: '2025-12-27', sellTime: '14:45', inStock: false },
{ model: 'Windbreaker Jacket', price: 1573.57, sellDate: '2025-09-20', sellTime: '20:31', inStock: false },
{ model: 'Speed Gloves', price: 338.01, sellDate: '2025-10-22', sellTime: '18:56', inStock: false },
{ model: 'Carbon Handlebar', price: 309.18, sellDate: '2025-11-10', sellTime: '15:20', inStock: true },
{ model: 'LED Bike Light', price: 1289.0, sellDate: '2025-08-22', sellTime: '15:34', inStock: true },
{ model: 'Action Camera', price: 1655.66, sellDate: '2025-06-12', sellTime: '15:38', inStock: false },
{ model: 'Hydration Pack', price: 1126.33, sellDate: '2025-09-15', sellTime: '06:29', inStock: false },
{ model: 'Racing Socks', price: 157.45, sellDate: '2025-01-26', sellTime: '19:25', inStock: true },
{ model: 'Aero Bottle', price: 1707.67, sellDate: '2025-02-02', sellTime: '17:34', inStock: true },
{ model: 'Road Tire Tube', price: 601.95, sellDate: '2025-04-14', sellTime: '08:02', inStock: true },
{ model: 'HL Road Tire', price: 118.42, sellDate: '2025-02-08', sellTime: '06:08', inStock: false },
{ model: 'Racing Socks', price: 1721.99, sellDate: '2025-10-13', sellTime: '09:01', inStock: true },
{ model: 'Action Camera', price: 1620.39, sellDate: '2025-07-18', sellTime: '05:53', inStock: false },
{ model: 'Trail Helmet', price: 1051.16, sellDate: '2025-01-21', sellTime: '09:44', inStock: true },
{ model: 'Fitness Watch', price: 1534.64, sellDate: '2025-02-27', sellTime: '09:19', inStock: true },
{ model: 'Comfort Saddle', price: 984.12, sellDate: '2025-03-16', sellTime: '07:24', inStock: false },
{ model: 'Comfort Saddle', price: 1316.13, sellDate: '2025-02-11', sellTime: '11:01', inStock: true },
{ model: 'Carbon Handlebar', price: 774.69, sellDate: '2025-10-17', sellTime: '11:38', inStock: false },
{ model: 'Road Tire Tube', price: 1887.19, sellDate: '2025-10-19', sellTime: '06:02', inStock: true },
{ model: 'Cycling Cap', price: 519.44, sellDate: '2025-10-21', sellTime: '03:54', inStock: true },
{ model: 'Trail Helmet', price: 1149.2, sellDate: '2025-04-24', sellTime: '04:40', inStock: false },
{ model: 'Carbon Handlebar', price: 915.24, sellDate: '2025-07-10', sellTime: '05:22', inStock: true },
{ model: 'Comfort Saddle', price: 1625.63, sellDate: '2025-03-31', sellTime: '23:55', inStock: true },
{ model: 'Racing Socks', price: 143.76, sellDate: '2025-12-02', sellTime: '07:25', inStock: true },
{ model: 'Cycling Cap', price: 981.24, sellDate: '2025-08-09', sellTime: '19:52', inStock: false },
{ model: 'Comfort Saddle', price: 779.4, sellDate: '2025-06-12', sellTime: '17:08', inStock: true },
{ model: 'Carbon Handlebar', price: 1512.24, sellDate: '2025-07-27', sellTime: '07:02', inStock: true },
{ model: 'Cycling Cap', price: 444.79, sellDate: '2025-09-11', sellTime: '10:05', inStock: false },
];
const Table = memo(({ hotTableRef, data }) => {
return (
<HotTable
ref={hotTableRef}
pagination={true}
dialog={true}
autoRowSize={true}
tabNavigation={false}
data={data}
width="100%"
height={250}
stretchH="all"
contextMenu={true}
rowHeaders={true}
colHeaders={true}
autoWrapRow={true}
autoWrapCol={true}
licenseKey="non-commercial-and-evaluation"
>
<HotColumn title="Model" type="text" data="model" width={150} headerClassName="htLeft" />
<HotColumn
title="Price"
type="numeric"
data="price"
width={80}
locale="en-US" numericFormat={{ style: 'currency', currency: 'USD', minimumFractionDigits: 2 }}
className="htRight"
headerClassName="htRight"
/>
<HotColumn
title="Date"
type="intl-date"
data="sellDate"
width={131}
locale="en-US" dateFormat={{ month: 'short', day: 'numeric', year: 'numeric' }}
className="htRight"
headerClassName="htRight"
/>
<HotColumn
title="Time"
type="intl-time"
data="sellTime"
width={81}
timeFormat={{ hour: '2-digit', minute: '2-digit', hour12: true }}
className="htRight"
headerClassName="htRight"
/>
<HotColumn title="In stock" type="checkbox" data="inStock" className="htCenter" headerClassName="htCenter" />
</HotTable>
);
});
const DebugInfo = memo(({ debugInfo }) => (
<>
<strong>Debug information:</strong>
<table className="debug-table">
<colgroup>
<col />
<col style={{ width: '200px' }} />
</colgroup>
<tbody>
<tr>
<td>
<code>isListening()</code>
</td>
<td>
<code className="isListening">{String(debugInfo.isListening)}</code>
</td>
</tr>
<tr>
<td>
<code>getFocusScopeManager().getActiveScopeId()</code>
</td>
<td>
<code className="focusScope">{String(debugInfo.focusScope)}</code>
</td>
</tr>
<tr>
<td>
<code>getShortcutManager().getActiveContextName()</code>
</td>
<td>
<code className="shortcutsContext">{String(debugInfo.shortcutsContext)}</code>
</td>
</tr>
</tbody>
</table>
</>
));
const ExampleComponent = () => {
const [debugInfo, setDebugInfo] = useState({
isListening: false,
focusScope: null,
shortcutsContext: null,
});
const hotRef = useRef(null);
const updateDebugInfo = useCallback(() => {
const hotInstance = hotRef.current?.hotInstance;
if (hotInstance) {
setDebugInfo({
isListening: hotInstance.isListening(),
focusScope: hotInstance.getFocusScopeManager().getActiveScopeId(),
shortcutsContext: hotInstance.getShortcutManager().getActiveContextName(),
});
}
}, []);
useEffect(() => {
const hotInstance = hotRef.current?.hotInstance;
if (hotInstance) {
hotInstance.getPlugin('dialog').show({
content: 'This is a simple text message displayed in the dialog.',
closable: true,
background: 'semi-transparent',
});
}
}, []);
useEffect(() => {
const interval = setInterval(updateDebugInfo, 200);
return () => clearInterval(interval);
}, [updateDebugInfo]);
return (
<div className="example-container">
<input
className="placeholder-input"
type="text"
name="focusable-text-input"
placeholder="Focusable top text input"
/>
<Table hotTableRef={hotRef} data={data} />
<input
className="placeholder-input"
type="text"
name="focusable-text-input"
placeholder="Focusable bottom text input"
/>
<DebugInfo debugInfo={debugInfo} />
</div>
);
};
export default ExampleComponent;
CSS
.placeholder-input {
max-width: 20rem;
padding: 0.4rem 0.625rem;
font-size: var(--sl-text-sm);
line-height: 1.25rem;
color: var(--sl-color-text);
background: none;
border: 1px solid var(--sl-color-gray-5);
border-radius: 0;
outline: none;
}
.placeholder-input::placeholder {
color: var(--sl-color-gray-3);
}
.placeholder-input:focus {
border-color: var(--sl-color-accent);
}
.example-container {
gap: 1rem;
display: flex;
flex-direction: column;
}
.example-container > strong {
font-size: 0.875rem;
font-weight: 600;
color: var(--sl-color-white);
margin: 0.5rem 0 0;
}
.example-container .debug-table {
font-size: var(--sl-text-sm);
border-collapse: collapse;
width: 100%;
}
.example-container .debug-table td {
padding: 0.4rem 0.75rem !important;
border-bottom: 1px solid var(--sl-color-gray-5);
color: var(--sl-color-gray-2);
}
.example-container .debug-table td:last-child {
font-family: var(--sl-font-mono, ui-monospace, monospace);
}
.example-container .debug-table td code {
font-size: var(--sl-text-xs);
}

Register a focus scope

To register a focus scope:

  1. Access the FocusScopeManager API:

    const focusScopeManager = hot.getFocusScopeManager();
  2. Use the registerScope() method:

    focusScopeManager.registerScope('customScope', containerElement);

Connect a scope with a shortcuts context

To connect a scope with a shortcuts context, use the shortcutsContextName option. When the scope is activated, the shortcuts context automatically switches to the scope’s specified context name. This allows you to define custom shortcuts that work only within that scope. For more information, see the Custom shortcuts page. If no context name is specified, the scope uses the grid context name by default.

const focusScopeManager = hot.getFocusScopeManager();
const shortcutManager = hot.getShortcutManager();
focusScopeManager.registerScope('customScope', containerElement, {
shortcutsContextName: 'plugin:customScope',
});
// Add shortcuts to the customScope context
const customScopeContext = shortcutManager.getContext('plugin:customScope');
customScopeContext.addShortcut({
group: 'customScope',
keys: [['enter']],
callback: () => {
console.log('Enter pressed within the customScope scope');
},
});

Add conditional scope activation

To add conditional scope activation, use the runOnlyIf option. This allows you to enable or disable the scope based on custom logic. The option is useful for situations where your UI depends on whether it has any focusable elements, or when you want to prevent the scope from activating for a particular part of the UI. For cases where focus should bypass the scope activation after Tab or Shift+Tab key presses, the logic should return false.

const focusScopeManager = hot.getFocusScopeManager();
focusScopeManager.registerScope('customScope', containerElement, {
runOnlyIf: () => isPluginActive(),
});

Custom focus detection

By default, a scope is considered active if the focused element is within the scope’s container element. However, there are cases where you need to provide custom logic to determine if the scope should be active. You can provide custom logic using the contains option.

const focusScopeManager = hot.getFocusScopeManager();
focusScopeManager.registerScope('myPlugin', containerElement, {
contains: (target) => {
// check if the target is within the scope's container element or
// if its parent has the 'my-plugin' class
return containerElement.contains(target) || target.closest('.my-plugin');
},
onActivate: (focusSource) => {
console.log('MyPlugin scope activated');
},
});

Scope callbacks

You can provide a callback function to be called when the scope is activated using the onActivate option. The callback function is called with the source of the activation as the first argument. You can also provide a callback function to be called when the scope is deactivated using the onDeactivate option.

The focusSource argument can be one of the following values:

  • unknown: The scope is activated by an unknown source.
  • click: The scope is activated by a click event.
  • tab_from_above: The scope is activated by a Tab key press.
  • tab_from_below: The scope is activated by a Shift+Tab key press.
const focusScopeManager = hot.getFocusScopeManager();
focusScopeManager.registerScope('customScope', containerElement, {
onActivate: (focusSource) => {
console.log('Custom scope activated');
},
onDeactivate: () => {
console.log('Custom scope deactivated');
},
});

Manage focus scopes

Get the active scope

To get the currently active scope ID:

const focusScopeManager = hot.getFocusScopeManager();
const activeScopeId = focusScopeManager.getActiveScopeId();
if (activeScopeId) {
console.log(`Active scope: ${activeScopeId}`);
} else {
console.log('No active scope');
}

Activate a scope

The focus manager automatically tries to activate the appropriate scope based on the focused element. However, there are cases where you need to manually activate a scope. For example, you might need to activate a scope after programmatically triggering an action. An example is the Dialog plugin: when the show() method is called, it manually activates its focus scope as there is no event triggered that would activate the scope.

const focusScopeManager = hot.getFocusScopeManager();
focusScopeManager.activateScope('myPlugin');

Deactivate a scope

To manually deactivate a scope by its ID:

const focusScopeManager = hot.getFocusScopeManager();
focusScopeManager.deactivateScope('myPlugin');

Unregister a scope

To remove a scope from the collection:

const focusScopeManager = hot.getFocusScopeManager();
focusScopeManager.unregisterScope('myPlugin');

Automatic focus management

The focus scope manager automatically:

  • Listens to document events and activates the appropriate scope based on the focused element
  • Updates the Core#isListening state based on scope activity
  • Switches the shortcuts context to the scope’s specified context name when the scope is activated
  • Handles tab navigation between scopes

API reference

For the complete API reference, see the following pages:

APIs

Configuration options

Core methods

Hooks

Troubleshooting

Didn’t find what you need? Try this: