Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pressing Tab blurs the editor #238

Closed
nmanandhar opened this issue Jul 13, 2020 · 14 comments
Closed

Pressing Tab blurs the editor #238

nmanandhar opened this issue Jul 13, 2020 · 14 comments

Comments

@nmanandhar
Copy link
Contributor

nmanandhar commented Jul 13, 2020

Pressing tab loses the focus from the editor and moves focus to other elements

@marijnh
Copy link
Member

marijnh commented Jul 13, 2020

See also https://codemirror.net/6/examples/tab/

This is by design, since tab is an essential part of keyboard web navigation, and trapping it harms accessibility. I will in the future look if I can find a way of trapping tab in a way that provides keyboard users with an obvious way to escape the editor, but the default behavior will remain leaving it alone.

@nmanandhar
Copy link
Contributor Author

I was a little surprised by this behaiour because In all editors I have come across, tab just adds 4 spaces

@wrnrlr
Copy link

wrnrlr commented Aug 20, 2020

Could it be an option to use Esc to blur the editor and focus the parent element.
Tab can be used afterwards in the expected way.
I was looking for a way to do this for Prosemirror because I need tab for other things.

@marijnh
Copy link
Member

marijnh commented Aug 20, 2020

I'm not sure how discoverable that would be... and there isn't always a (reasonable) focusable parent element (and tab order isn't hierarchical, so it's not unlikely that, after moving focus out of the editor, your next tab press will move it back in).

@curran
Copy link
Contributor

curran commented Aug 20, 2020

@nmanandhar I'm curious, what editors on the Web have you come across where the tab key indents?

@mischnic
Copy link

@twavv
Copy link

twavv commented Aug 31, 2020

The escape option mirrors how Jupyter behaves. We could lean further into that: when tab-navigating a page, don't focus into the CodeMirror, but focus the overall element and require the user to press "enter" to start typing. I think that makes the escape-to-exit functionality more obvious.

I (personally) think that using tab for indenting is a necessary evil. I'm willing to bet that the current behavior will result in decreased accessibility as people constantly accidentally exit the code area (since sooooo many people are used to tabbing behavior).

Edit:

I'm not sure how discoverable that would be... and there isn't always a (reasonable) focusable parent element (and tab order isn't hierarchical, so it's not unlikely that, after moving focus out of the editor, your next tab press will move it back in).

I think re-focusing the outer element makes sense here (probably just a <div tabindex="0" /> element), since you can then tab to the next focusable element element on the page (side stepping the lack-of-hierarchy-problem).

@dwelle
Copy link

dwelle commented Sep 3, 2020

Just in case people are wondering, you can override the default behavior if you choose to do so:

import { defaultKeymap, indentMore, indentLess } from "@codemirror/next/commands";

EditorState.create({
  extensions: [
    keymap([
      ...defaultKeymap,
      {
        key: "Tab",
        preventDefault: true,
        run: indentMore,
      },
      {
        key: "Shift-Tab",
        preventDefault: true,
        run: indentLess,
      },
    ]),
  ],
});

@alinnert
Copy link

This is by design, since tab is an essential part of keyboard web navigation

Not really. Tab changes the focused element regardless of web or non-web environment. Documents are one exception to this general rule, which includes code files, which are the main contents of CodeMirror, aren't they? I can see this "the web world has to behave very differently than the native world because reasons" movement every now and then, and I'm not a fan of it. All it does is creating an inconsistent UX. Imagine pressing tab in a word processor or your code editor and it blurs the document/file instead of indenting the text/code. Code editors are most likely used in applications, not in web forms. The latter would justify "press tab to change focus" but this is not where I see much use in CodeMirror.

I'm curious, what editors on the Web have you come across where the tab key indents?

Again, the "on the web" should not make a difference. It's about use-case and context. If you ask me which editors in general I've came across where the tab key does not indent, the answer is: none. All editors indent your code whether it's native (Scintilla/Notepad++, IntelliJ, Xcode, VS...) or web (Monaco/VS Code, Ace, CodeJar). Because it makes sense in this context.

@marijnh
Copy link
Member

marijnh commented Oct 28, 2020

Again, the "on the web" should not make a difference.

It absolutely does. This component aims to be web-native and accessible, and is going to set its defaults accordingly. If you have a problem with that you can configure it differently, but see for example the content of a keyboard trap for why that is user-hostile and inaccessible.

@alinnert
Copy link

It absolutely does.

You basically just said that keyboard traps and poor accessibility is not a problem in non-web environments. This is what I mean with "it doesn't matter". Everything you make should be accessible, whether it's a website, web app or native app.

But there are different approaches to how this is achieved. Applications normally use keyboard shortcuts to access different parts of them, which automatically removes focus from the document (alt + some key, or something unique to the app). But this is an implementation detail of the application, not something a component can take care of on its own.

On a side note: Even in a keyboard trap you can still move focus to the Browser by pressing alt, or ctrl + e, or any other browser shortcut and start tabbing through the document again from the very top. Or from the bottom by using shift + tab. You can also use the browsers find feature to place the focus anywhere you want as long as there's text. I use this very frequently to focus links without tabbing all the way to them. It's not like a keyboard trap is a dead end...

But anyway: The Monaco Editor uses ctrl + m to toggle the behaviour of the tab key. This proves that this is possible and I think that's a good way to solve this. Basically all you need to do is conditionally preventDefault. At least I think so.

Assuming the default won't change nonetheless, could you provide an additional defaultKeymapWithTabKey or one that only provides the differences? Like keymap([...defaultKeymap, ...useTabKey]) or something like that. Not only is the solution above quite a bit to write/remember/look up, it's also not the whole story. If there's no text selected the tab key should insert a tab character. Otherwise it differs from editor to editor. IntelliJ always indents if there's any selection. Monaco only indents if an entire line is selected or if the selection spans multiple lines. Personally, I don't have a preference here since, for me, this is a very rare edge case.

@hubgit
Copy link
Contributor

hubgit commented Nov 25, 2020

@nmanandhar I'm curious, what editors on the Web have you come across where the tab key indents?

https://gist.github.com/ (which uses CodeMirror) is a pretty big one.

@twavv
Copy link

twavv commented Nov 25, 2020

I do strongly think that tab should be indent - it's what practically every developer expects. Also, other editors (like document editors) use tab for indent (e.g., create a sub-bullet).

This issue has come up elsewhere, and the escape-to-exit-edit-mode suggestion has come up at least once: chakra-ui/chakra-ui#5

I know it's customizable in "user space," but the default seems strange.

marijnh added a commit that referenced this issue Dec 14, 2020
As an emergency escape-from-keyboard-trap mechanism when tab is
bound to another command.

Issue #238
marijnh added a commit to codemirror/commands that referenced this issue Jan 22, 2021
FEATURE: The new `insertTab` command inserts a tab when nothing is selected,
and defers to `indentMore` otherwise.

FEATURE: The package now exports a `defaultTabBinding` object that provides
a recommended binding for tab (if you must bind tab).

Issue codemirror/dev#238
marijnh added a commit to codemirror/website that referenced this issue Jan 22, 2021
@marijnh
Copy link
Member

marijnh commented Jan 22, 2021

Attached patches add more information about handling tab to the website, plus an example tab binding to the commands package. I hope people will find that, if not, I guess I'll use it as a link to point people to when the inevitable issues are opened.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants