Skip to content

RFC: Keyboard Shortcuts #3020

Open
Open

Description

@slorber

Initially proposed by @yangshun here: #2267

💥 Proposal: Keyboard Shortcuts

Difficulty: Easy-Medium

How it works - plugins can register keyboard shortcuts which Docusaurus will attach as a global event listener and show a list of all supported shortcuts on the website when the user types ?, like Reddit:

Screen Shot 2020-06-05 at 7 55 28 PM

Of course it'll be up to the plugins to define their own logic for responding to events. Docusaurus can provide the keyboard event listening mechanism and call plugin code when a specific key combination occurs.

Activity

  1. added
    proposalThis issue is a proposal, usually non-trivial change
    status: needs triageThis issue has not been triaged by maintainers
    mlhMajor League Hacking Fellowship
    and removed
    status: needs triageThis issue has not been triaged by maintainers
    on Jul 1, 2020
  2. slorber commented on Jul 1, 2020

    @slorber
    CollaboratorAuthor

    Initially tagged for MLH, also @taylorallen0913 told me he was interested to work on this.


    I don't have a strong opinion on how this should be implemented. Maybe we could discuss about an exhaustive list of shortcuts we'd like to support initially, and see from there if we are able to design this feature?

    Some thoughts:

    • The shortcuts should run client-side
    • If we had a core plugin api like "addShortcut" in contentLoaded lifecycle, it's likely to be limited because we'd have to handle shortcuts in a declarative way (ie the shortcuts should be serialized to json and only then be wired on the frontend)
    • plugins don't often do this often, but they are able to ship frontend code as well (see ideal image plugin, which provides an image component). I think could use a declarative way to use shortcuts, maybe using a JSX-based shortcut lib.
  3. taylorallen0913 commented on Jul 1, 2020

    @taylorallen0913
    Contributor

    Heres my ideas on how we can implement this:

    Core functionalities:

    • Use the Context API and wrap our client to register a global event listener
    • Write our own useKeyboardShortcut hook that handles registering shortcuts and customizing them
    • Create our own data structure to store our keyboard shortcuts
    • Map all of our keybind names, shortcuts, etc. to a menu

    Optional functionalities:

    • Custom user keyboard shortcuts from list of actions
    • Shortcut rebindability

    I plan to implement all of this inside a new docusaurus-keyboard-shortcuts monorepo.

    This is my general idea for the keybind data structure, and obviously it will be stored in memory in either the hook or context. Also the way I have it set up currently is that you have to register the hook on a file-by-file basis so you can control when the keyboard shortcuts are active.

    Screen Shot 2020-07-01 at 11 17 53 AM

    I am also doing some testing of my implementation here. I wrote it in my own repo because I am not completely familiar with the codebase yet, and I should be able to just transfer everything over when I get it to reasonably functioning state.

    If anyone has any ideas please let me know so I can improve this.

  4. anshulrgoyal commented on Jul 2, 2020

    @anshulrgoyal
    Contributor

    I was thinking if @docusaurus/plugins-content-docs want to add a keyboard shortcut to move to the next page in the sidebar how it be handled by @taylorallen0913 implementation.

  5. taylorallen0913 commented on Jul 2, 2020

    @taylorallen0913
    Contributor

    I was thinking if @docusaurus/plugins-content-docs want to add a keyboard shortcut to move to the next page in the sidebar how it be handled by @taylorallen0913 implementation.

    I think the way we should implement should be as general as possible— making the system scalable, so that down the line, as we add more plugins, the keyboard shortcut functionalities are not limited. The way I see this being possible is allowing the plugin to provide a function/callback for what they want the keyboard shortcut to accomplish. In theory, it would allow almost anything to executed with a keyboard shortcut as long as the task is programmatically possible (which I assume should not limit anything).

    This is an example on how a plugin would register their desired shortcut, most likely just consuming a reducer on mount:

    image

    Do you agree on the approach i’m taking? What do you think could be improved?

  6. slorber commented on Oct 1, 2020

    @slorber
    CollaboratorAuthor

    As we have new MLH interns coming soon, was thinking about this issue.

    To me, it's not totally clear if shortcuts should be provided by a plugin, by a theme, or both.
    This feature is not very easy to design.

  7. added
    featureThis is not a bug or issue with Docusausus, per se. It is a feature request for the future.
    and removed
    proposalThis issue is a proposal, usually non-trivial change
    on Oct 30, 2021
  8. Josh-Cena commented on Nov 20, 2021

    @Josh-Cena
    Collaborator

    The ts-eslint website uses a client module to register a global key listener. It's a konami code easter egg. (For those who don't know what konami code is: try typing ↑↑↓↓←→←→BA on the website)

    I think it's a good model to follow for plugins. There's no need to populate the core with more lifecycle APIs. Each plugin can add a set of hotkeys and register them to a global file (we should do the same for the linkification logic: instead of routing the logic to the core, prefer plugins writing to a global data register), and the theme will pick up that generated file and render it as a hotkey map popup.

  9. yangshun commented on Nov 20, 2021

    @yangshun
    Contributor

    I think the purpose of putting this in core is so that in the case of overlapping/conflicting shortcuts, we can throw errors or inform users. Letting Docusaurus core manage keyboard shortcuts will also allow shortcuts to be contextual, e.g. when focus is in a component, Ctrl + K does something different from search. This can also be done entirely in userland, but just a bit more work for users.

  10. Josh-Cena commented on Nov 20, 2021

    @Josh-Cena
    Collaborator

    I think the purpose of putting this in core is so that in the case of overlapping/conflicting shortcuts, we can throw errors or inform users.

    I was about to that "this can be done by writing to @generated/hotkeys.json during contentLoaded as well" but I realized that there's no guaranteed execution order :( Indeed we would at least need a new lifecycle that runs in series, allowing each plugin to write to a global data register in a deterministic order. This would be useful for file path -> URL mapping as well.

    allow shortcuts to be contextual

    Isn't that ultimately on the theme though? Ideally the core doesn't know much about what's happening inside the Layout comp?

    This can also be done entirely in userland, but just a bit more work for users.

    We would definitely want a more imperative API to register hotkeys, maybe in the form of a utility function in the plugin. Not sure if site builders would want addition hotkeys / hotkey configuration🤔 I imagine as soon as we release this there would be requests like "let me use WASD instead of ↑↓←→ for navigation"

  11. slorber commented on Dec 8, 2021

    @slorber
    CollaboratorAuthor

    Direct writing to a file seems like a bad idea. In addition to race conditions it's also an implicit API surface, more complex to implement for users.

    I also agree that shortcuts can be contextual, and shortcuts can be namespaced by plugin.

    Not directly related but I'd also like to have a core hook that tells a page by which plugin/id it was created (each page is always created by a plugin, maybe not minor edge cases like the 404?) => that can allow custom login on a per-instance basis in swizzled components.

    Random thought: what are the advantages for plugins to expose shortcuts as a Node.js API?
    Handling of shortcuts has to be implemented in the themes anyway to wire a key to a concrete action implementation.
    Maybe the Node.js API should only expose options to customize the shortcut keys, and that's all we need?

    What kind of shortcut would benefit from new lifecycle APIs?

  12. removed
    mlhMajor League Hacking Fellowship
    on Apr 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureThis is not a bug or issue with Docusausus, per se. It is a feature request for the future.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions