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

RFC: Keyboard Shortcuts #3020

Open
slorber opened this issue Jul 1, 2020 · 9 comments
Open

RFC: Keyboard Shortcuts #3020

slorber opened this issue Jul 1, 2020 · 9 comments
Labels
feature This is not a bug or issue with Docusausus, per se. It is a feature request for the future.

Comments

@slorber
Copy link
Collaborator

slorber commented Jul 1, 2020

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.

@slorber slorber added proposal This issue is a proposal, usually non-trivial change status: needs triage This issue has not been triaged by maintainers mlh Major League Hacking Fellowship v2 and removed status: needs triage This issue has not been triaged by maintainers labels Jul 1, 2020
@slorber
Copy link
Collaborator Author

slorber commented Jul 1, 2020

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.

@taylorallen0913
Copy link
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.

@anshulrgoyal
Copy link
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.

@taylorallen0913
Copy link
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?

@slorber
Copy link
Collaborator Author

slorber commented Oct 1, 2020

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.

@Josh-Cena Josh-Cena removed the v2 label Oct 30, 2021
@Josh-Cena Josh-Cena added feature This is not a bug or issue with Docusausus, per se. It is a feature request for the future. and removed proposal This issue is a proposal, usually non-trivial change labels Oct 30, 2021
@Josh-Cena
Copy link
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.

@yangshun
Copy link
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.

@Josh-Cena
Copy link
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"

@slorber
Copy link
Collaborator Author

slorber commented Dec 8, 2021

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature This is not a bug or issue with Docusausus, per se. It is a feature request for the future.
Projects
None yet
Development

No branches or pull requests

5 participants