mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
Picking a model closed the menu and then flashed the pill's tooltip over the fresh selection. The existing focus guard gated on `:focus-visible` alone, which does not separate a mouse pick from a Tab: the dropdown autofocuses its search field and keyboard-navigates its rows, so Chromium is already in keyboard modality when the menu restores focus to the trigger, and the guard never fired. Track the device behind the last real interaction and use it to qualify `:focus-visible`. A mouse pick reports `pointer` and stays silent; Tab focus still opens the tip.
26 lines
1.2 KiB
TypeScript
26 lines
1.2 KiB
TypeScript
/** Which input device drove the most recent interaction.
|
|
*
|
|
* Chromium's `:focus-visible` is not enough to tell a mouse pick from a Tab.
|
|
* Radix menus autofocus their content on open and keyboard-navigate their
|
|
* items, so by the time a mouse click closes the menu and restores focus to
|
|
* the trigger, Chromium has decided the page is in keyboard modality and
|
|
* matches `:focus-visible` on that restore (verified in Chrome — the model
|
|
* pill's tooltip popped open after every mouse pick). Track the device
|
|
* ourselves and use it to qualify `:focus-visible`.
|
|
*/
|
|
|
|
export type InputModality = 'keyboard' | 'pointer'
|
|
|
|
let modality: InputModality = 'keyboard'
|
|
|
|
/** Capture-phase so a `stopPropagation` deeper in the tree can't blind us. */
|
|
if (typeof document !== 'undefined') {
|
|
document.addEventListener('pointerdown', () => (modality = 'pointer'), { capture: true, passive: true })
|
|
document.addEventListener('keydown', () => (modality = 'keyboard'), { capture: true, passive: true })
|
|
}
|
|
|
|
/** The device behind the last pointerdown/keydown. Defaults to `keyboard` so a
|
|
* surface that has seen no input yet keeps the accessible behavior. */
|
|
export function lastInputModality(): InputModality {
|
|
return modality
|
|
}
|