Skip to content

Commit

Permalink
Keyboard Nav: let users rebind their shortcuts (#13781)
Browse files Browse the repository at this point in the history
* click-outside and shortcuts enabled/disabled toggle

* Trap focus when modal open

* Enabled/disabled saved to localStorage

* Autofocus edit button on variable index

* Modal overflow styles

* Functional rebind

* Saving rebinds to localStorage for all majors

* Started on defaultCommandBindings

* Modal header style and cancel rebind on escape

* keyboardable keybindings w buttons instead of spans

* recording and defaultvalues

* Enter short-circuits rebind

* Only some commands are rebindable, and dont show dupes

* No unused get import

* More visually distinct header on modal

* Disallowed keys for rebind, showing buffer as you type, and moving dedupe to modal logic
  • Loading branch information
philrenaud committed Aug 3, 2022
1 parent 3983019 commit 354a149
Show file tree
Hide file tree
Showing 5 changed files with 334 additions and 162 deletions.
70 changes: 50 additions & 20 deletions ui/app/components/keyboard-shortcuts-modal.hbs
Original file line number Diff line number Diff line change
@@ -1,27 +1,57 @@
{{#if this.keyboard.shortcutsVisible}}
{{keyboard-commands (array this.escapeCommand)}}
<ul class="keyboard-shortcuts">
<button
class="button is-borderless dismiss"
type="button"
{{on "click" (toggle "keyboard.shortcutsVisible" this)}}
>
{{x-icon "cancel"}}
</button>
{{#each this.commands as |command|}}
<li>
<strong>{{command.label}}</strong>
<span class="keys">
{{#each command.pattern as |key|}}
<span>{{clean-keycommand key}}</span>
{{/each}}
</span>
</li>
{{/each}}
</ul>
<div class="keyboard-shortcuts"
{{on-click-outside
(toggle "keyboard.shortcutsVisible" this)
}}
>
<header>
<button
{{autofocus}}
class="button is-borderless dismiss"
type="button"
{{on "click" (toggle "keyboard.shortcutsVisible" this)}}
>
{{x-icon "cancel"}}
</button>
<h2>Keyboard Shortcuts</h2>
<p>Click a key pattern to re-bind it to a shortcut of your choosing.</p>
</header>
<ul class="commands-list">
{{#each this.commands as |command|}}
<li>
<strong>{{command.label}}</strong>
<span class="keys">
{{#if command.recording}}
<span class="recording">Recording; ESC to cancel.</span>
{{else}}
{{#if command.custom}}
<button type="button" class="reset-to-default" {{on "click" (action this.keyboard.resetCommandToDefault command)}}>reset to default</button>
{{/if}}
{{/if}}

<button disabled={{or (not command.rebindable) command.recording}} type="button" {{on "click" (action this.keyboard.rebindCommand command)}}>
{{#each command.pattern as |key|}}
<span>{{clean-keycommand key}}</span>
{{/each}}
</button>
</span>
</li>
{{/each}}
</ul>
<footer>
<strong>Keyboard shortcuts {{#if this.keyboard.enabled}}enabled{{else}}disabled{{/if}}</strong>
<Toggle
data-test-cpu-toggle
@isActive={{this.keyboard.enabled}}
@onToggle={{this.toggleListener}}
title="{{if this.keyboard.enabled "enable" "disable"}} keyboard shortcuts"
/>
</footer>
</div>
{{/if}}

{{#if this.keyboard.displayHints}}
{{#if (and this.keyboard.enabled this.keyboard.displayHints)}}
{{#each this.hints as |hint|}}
<span
{{did-insert this.tetherToElement element=hint.element hint=hint}}
Expand Down
14 changes: 12 additions & 2 deletions ui/app/components/keyboard-shortcuts-modal.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import { computed } from '@ember/object';
import { action } from '@ember/object';
import Tether from 'tether';

export default class KeyboardShortcutsModalComponent extends Component {
Expand All @@ -18,9 +19,14 @@ export default class KeyboardShortcutsModalComponent extends Component {
* commands: filter keyCommands to those that have an action and a label,
* to distinguish between those that are just visual hints of existing commands
*/
@computed('keyboard.keyCommands.length')
@computed('keyboard.keyCommands.[]')
get commands() {
return this.keyboard.keyCommands.filter((c) => c.label && c.action);
return this.keyboard.keyCommands.reduce((memo, c) => {
if (c.label && c.action && !memo.find((m) => m.label === c.label)) {
memo.push(c);
}
return memo;
}, []);
}

/**
Expand Down Expand Up @@ -49,4 +55,8 @@ export default class KeyboardShortcutsModalComponent extends Component {
untetherFromElement(self, _, { hint }) {
hint.binder.destroy();
}

@action toggleListener() {
this.keyboard.enabled = !this.keyboard.enabled;
}
}
Loading

0 comments on commit 354a149

Please sign in to comment.