microsoft / tabster

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

Cannot enter whitespace with "tab" key into monaco editor since around tabster v4.7.3 #316

Open chenxinyanc opened 10 months ago

chenxinyanc commented 10 months ago

I'm not sure from which version this issue starts to manifest, but tabster v4.7.0 definitely does not have such issue.

Reproduction (CodeSandbox): https://codesandbox.io/s/fluent-ui-v9-tabster-with-monaco-editor-ldwt64?file=/src/example.tsx

When I press "tab" key inside monaco editor, I expect to either

but instead my focus gets moved to the auto-completion box, or the button.

Recording_20231031T171522

chenxinyanc commented 9 months ago

Is there any update to this bug? We've been continuously upgrading Fluent UI v9 but we are still keeping the version of tabster pinned right now.

mshoho commented 9 months ago

This is not actually a bug, more like a side effect of the central focus management and a component with custom focus management. Tabster has uncontrolled areas, if you apply data-tabster='{"uncontrolled": {}}' on the editor container, Tabster will let the to handle focus inside. Like this

      <div style={{ width: "100%" }} data-tabster='{"uncontrolled": {}}'>
        <Editor className={styles.monacoContainer} defaultValue="test123" />
      </div>

https://codesandbox.io/p/sandbox/fluent-ui-v9-tabster-with-monaco-editor-forked-zlcqxd?file=%2Fsrc%2Fexample.tsx%3A37%2C1-40%2C1 — I have just quickly added a wrapper div for the sake of demonstration.

From the FluentUI perspective, we will expose that uncontrolled API so that you don't have to add custom data attributes yourself, but use the FUI API instead.

cf commented 9 months ago

If you load monaco after a menu in fluent ui 9, @mshoho's method still does not work.

But you can work around this by putting FocusTrapZone around the editor:

import { FocusTrapZone } from '@fluentui/react';
import { useUncontrolledFocus } from '@fluentui/react-components';
...
const YourComponent = ()=>{
  const attr = useUncontrolledFocus();
  return(
    <FocusTrapZone
      style={{
        width: "100%",
        height: "100%",
      }}
      {...attr}
      isClickableOutsideFocusTrap
      forceFocusInsideTrap={false}
    >
       <Editor />
    </FocusTrapZone>
  );
};
mshoho commented 9 months ago

@cf, could you create a codesandbox repro for it? Using extra FocusTrapZone is certainly not the best way of solving it. And latest version of Tabster supports a parameter for uncontrolled, you can do data-tabster='{"uncontrolled": { completely: true }}' to gain complete control over the area (that might have some corner cases, we'll describe the implications in the FUI uncontrolled API documentation soon). In any case, I would rather solve it in Tabster instead of using extra FocusTrapZone.