microsoft / tabster

Web Application Keyboard Navigation Tools
https://tabster.io
MIT License
122 stars 36 forks source link

Tabster should include a way to indicate that it was the cause of programmatic focus #384

Open khmakoto opened 7 months ago

khmakoto commented 7 months ago

When focus has been moved programmatically because of Tabster (say to restore focus to a trigger element after dismissing a popover or dialog), there should be a way to indicate that tabster was the cause of this programmatic focus (maybe through the keyborg event).

ling1726 commented 6 months ago

This should already be possible https://github.com/microsoft/keyborg/blob/bdfc82f67b743c64e8d9ec0bfac50b75d72e9cef/src/FocusEvent.ts#L252-L259

image

khmakoto commented 6 months ago

@ling1726 I know that you can check if something was programmatically focused or not, but I don't think you can check whether tabster was the cause of the focus moving programmatically or if something else was the cause, can you?

ling1726 commented 6 months ago

Ah @khmakoto I see what you mean. Can you please describe the scenario where this would be needed?

khmakoto commented 6 months ago

It's for scenarios like the one in Tooltip here, where we do not want a tooltip to show if things like closing another surface would cause focus to be restored to a trigger button with a Tooltip attached to it. However, there are products that have a mixture of tabster usage + their own custom solutions for certain focus related scenarios where they sometimes move focus programmatically and would like the Tooltip to show up in those scenarios. which is impossible now because there is no way to differentiate between those.

https://github.com/microsoft/fluentui/blob/master/packages/react-components/react-tooltip/src/components/Tooltip/useTooltip.tsx#L179-L199

mshoho commented 6 months ago

Tabster dispatches tabster:movefocus event every time before it moves focus. See TabsterMoveFocusEventDetail for the event's detail signature (it has next element and related keyboard event, if any). You can also can call preventDefault() and Tabster won't handle it at all (but you will have all the data about what it wanted to focus).

mshoho commented 6 months ago

Tabster also adds typings for addEventListener() so that you don't need to import the event signature directly, it will be inferred automatically when you do document.addEventListener('tabster:movefocus', e => ...).