Skip to content

Commit

Permalink
New keyboard shortcuts + tooltips refactoring (vuejs#519)
Browse files Browse the repository at this point in the history
* Tooltip style tweak

* Refactoring with new i18n plugin

* Add [F] to focus filter input

* Fix index going out of bounds

* Tooltip key background has more contrast in Dark mode

* More history keyboard shortcuts

* App keyboard shortcuts + improvements

* Disable keyboard shortcuts if target is textarea

* Improved entry list keyboard navigation + bug fixes

* Update locale interpolation

* Change Force refresh to Ctrl+Alt+R to avoid conflict with page refresh

* Better keyboard shortcuts

* Shortcuts: now uses `key` and modifiers are now exclusive

For example, modifier 'ctrl+alt' isn't dispatch if 'shift' is pressed too.

* Change Tabs shorctus

* Fix Ctrl+Alt+R shortcut on Mac

* Added Backspace to Ctrl+Del for convenience on MacBook

* Fix key tooltip on MacOS

* Removed right-margin on keys in tooltips

* Fix icon alignment on MacOS

* New GlobalRefs plugin for better code maintainability

* More explicit keyboard mixin

* Fix tests
  • Loading branch information
Guillaume Chau authored Jan 22, 2018
1 parent 99cc2e3 commit 000a632
Show file tree
Hide file tree
Showing 21 changed files with 573 additions and 177 deletions.
50 changes: 42 additions & 8 deletions src/devtools/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,39 @@
<span class="message" :key="message">{{ message }}</span>
</transition>
</span>
<a class="button components"
<a
class="button components"
:class="{ active: tab === 'components'}"
v-tooltip="$t('App.components.tooltip')"
@click="switchTab('components')"
v-tooltip="'Switch to Components'">
>
<i class="material-icons">device_hub</i>
<span class="pane-name">Components</span>
</a>
<a class="button vuex"
<a
class="button vuex"
:class="{ active: tab === 'vuex'}"
v-tooltip="$t('App.vuex.tooltip')"
@click="switchTab('vuex')"
v-tooltip="'Switch to Vuex'">
>
<i class="material-icons">restore</i>
<span class="pane-name">Vuex</span>
</a>
<a class="button events"
<a
class="button events"
:class="{ active: tab === 'events' }"
v-tooltip="$t('App.events.tooltip')"
@click="switchTab('events')"
v-tooltip="'Switch to Events'">
>
<i class="material-icons">grain</i>
<span class="pane-name">Events</span>
<span class="event-count" v-if="newEventCount > 0">{{ newEventCount }}</span>
</a>
<a class="button refresh"
<a
class="button refresh"
v-tooltip="$t('App.refresh.tooltip')"
@click="refresh"
v-tooltip="'Force Refresh'">
>
<i class="material-icons" ref="refresh">refresh</i>
<span class="pane-name">Refresh</span>
</a>
Expand All @@ -49,11 +57,37 @@ import ComponentsTab from './views/components/ComponentsTab.vue'
import EventsTab from './views/events/EventsTab.vue'
import VuexTab from './views/vuex/VuexTab.vue'
import { SPECIAL_TOKENS } from '../util'
import Keyboard from './mixins/keyboard'
import { mapState } from 'vuex'
export default {
name: 'app',
mixins: [
Keyboard({
onKeyDown ({ key, code, modifiers }) {
switch (modifiers) {
case 'ctrl+alt':
if (key === 'r' || code === 'KeyR') {
this.refresh()
return false
}
break
case 'ctrl':
if (code === 'Digit1') {
this.switchTab('components')
return false
} else if (code === 'Digit2') {
this.switchTab('vuex')
return false
} else if (code === 'Digit3') {
this.switchTab('events')
return false
}
}
}
})
],
components: {
components: ComponentsTab,
vuex: VuexTab,
Expand Down
2 changes: 0 additions & 2 deletions src/devtools/components/ActionHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@
.material-icons
font-size 16px
margin-right 0
position relative
top 1px
color inherit
@media (min-width: $wide)
margin-right 5px
Expand Down
4 changes: 2 additions & 2 deletions src/devtools/components/DataField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@
<template v-else>
<i
class="icon-button material-icons"
v-tooltip="cancelEditTooltip"
v-tooltip="$t('DataField.edit.cancel.tooltip')"
@click="cancelEdit()"
>close</i>
<i
class="icon-button material-icons"
v-tooltip="submitEditTooltip"
v-tooltip="$t('DataField.edit.submit.tooltip')"
@click="submitEdit()"
>done</i>
</template>
Expand Down
6 changes: 3 additions & 3 deletions src/devtools/components/ScrollPane.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ export default {
},
mounted () {
if (this.scrollEvent) {
bridge.on(this.scrollEvent, this.scroll)
bridge.on(this.scrollEvent, this.scrollToBottom)
}
},
destroyed () {
if (this.scrollEvent) {
bridge.removeListener(this.scrollEvent, this.scroll)
bridge.removeListener(this.scrollEvent, this.scrollToBottom)
}
},
methods: {
scroll () {
scrollToBottom () {
this.$nextTick(() => {
const container = this.$refs.scrollContainer
if (container.children.length) {
Expand Down
5 changes: 1 addition & 4 deletions src/devtools/components/StateInspector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
>
<div
class="data-type selectable-item"
v-tooltip="dataTypeTooltip"
v-tooltip="$t('StateInspector.dataType.tooltip')"
@click="toggle(dataType, $event)"
>
<span
Expand Down Expand Up @@ -76,9 +76,6 @@ export default {
(keyOrder[b] || (b.charCodeAt(0) + 999))
)
})
},
dataTypeTooltip () {
return `<span class="keyboard">${this.$keys.ctrl}</span> + <i class="material-icons">mouse</i>: Collapse All<br><span class="keyboard">${this.$keys.shift}</span> + <i class="material-icons">mouse</i>: Expand All`
}
},
methods: {
Expand Down
18 changes: 18 additions & 0 deletions src/devtools/env.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Vue from 'vue'

export const isChrome = typeof chrome !== 'undefined' && !!chrome.devtools
export const isMac = navigator.platform === 'MacIntel'
export const keys = {
ctrl: isMac ? '&#8984;' : 'Ctrl',
shift: 'Shift',
alt: isMac ? '&#8997;' : 'Alt',
del: 'Del',
enter: 'Enter',
esc: 'Esc'
}

Object.defineProperties(Vue.prototype, {
'$isChrome': { get: () => isChrome },
'$isMac': { get: () => isMac },
'$keys': { get: () => keys }
})
6 changes: 4 additions & 2 deletions src/devtools/global.styl
Original file line number Diff line number Diff line change
Expand Up @@ -299,14 +299,16 @@ $arrow-color = #444

.keyboard
display inline-block
min-width 22px
text-align center
background rgba($grey, .3)
padding 2px 4px 0
border-radius 3px
margin-bottom 6px
box-shadow 0 3px 0 rgba($grey, .2)
.dark &
background rgba($grey, .7)
box-shadow 0 3px 0 rgba($grey, .4)
background rgba($grey, .9)
box-shadow 0 3px 0 rgba($grey, .6)

.mono
font-family Menlo, Consolas, monospace
Expand Down
17 changes: 1 addition & 16 deletions src/devtools/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,7 @@ import App from './App.vue'
import store from './store'
import './plugins'
import { parse } from '../util'

// Env

const isChrome = typeof chrome !== 'undefined' && !!chrome.devtools
const isMac = navigator.platform === 'MacIntel'
const keys = {
ctrl: isMac ? '&#8984;' : 'Ctrl',
shift: 'Shift',
alt: isMac ? '&#8997;' : 'Alt'
}

Object.defineProperties(Vue.prototype, {
'$isChrome': { get: () => isChrome },
'$isMac': { get: () => isMac },
'$keys': { get: () => keys }
})
import { isChrome } from './env'

// UI

Expand Down
78 changes: 78 additions & 0 deletions src/devtools/locales/en.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
export default {
App: {
components: {
tooltip: '[[{{keys.ctrl}}]] + [[1]] Switch to Components'
},
events: {
tooltip: '[[{{keys.ctrl}}]] + [[3]] Switch to Events'
},
refresh: {
tooltip: '[[{{keys.ctrl}}]] + [[{{keys.alt}}]] + [[R]] Force Refresh'
},
vuex: {
tooltip: '[[{{keys.ctrl}}]] + [[2]] Switch to Vuex'
}
},
StateInspector: {
dataType: {
tooltip: '[[{{keys.ctrl}}]] + <<mouse>>: Collapse All<br>[[{{keys.shift}}]] + <<mouse>>: Expand All'
}
},
DataField: {
edit: {
cancel: {
tooltip: '[[{{keys.esc}}]] Cancel'
},
submit: {
tooltip: '[[{{keys.enter}}]] Submit change'
}
},
quickEdit: {
number: {
tooltip: `Quick Edit<br><br>
[[{{keys.ctrl}}]] + <<mouse>>: {{operator}}5<br>
[[{{keys.shift}}]] + <<mouse>>: {{operator}}10<br>
[[{{keys.alt}}]] + <<mouse>>: {{operator}}100`
}
}
},
ComponentTree: {
select: {
tooltip: '[[S]] Select component in the page'
},
filter: {
tooltip: '[[{{keys.ctrl}}]] + [[F]] Filter components by name'
}
},
EventsHistory: {
filter: {
tooltip: '[[{{keys.ctrl}}]] + [[F]] To filter on components, type <input><<search>> &lt;MyComponent&gt;</input> or just <input><<search>> &lt;mycomp</input>.'
},
clear: {
tooltip: '[[{{keys.ctrl}}]] + [[{{keys.del}}]] Clear Log'
},
startRecording: {
tooltip: '[[R]] Start recording'
},
stopRecording: {
tooltip: '[[R]] Stop recording'
}
},
VuexHistory: {
filter: {
tooltip: '[[{{keys.ctrl}}]] + [[F]] Filter mutations'
},
commitAll: {
tooltip: '[[{{keys.ctrl}}]] + [[{{keys.enter}}]] Commit all'
},
revertAll: {
tooltip: '[[{{keys.ctrl}}]] + [[{{keys.del}}]] Revert all'
},
startRecording: {
tooltip: '[[R]] Start recording'
},
stopRecording: {
tooltip: '[[R]] Stop recording'
}
}
}
15 changes: 3 additions & 12 deletions src/devtools/mixins/data-field-edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,6 @@ export default {
}
}
return null
},

cancelEditTooltip () {
return '<span class="keyboard">Esc</span> Cancel'
},

submitEditTooltip () {
return '<span class="keyboard">Enter</span> Submit change'
}
},

Expand Down Expand Up @@ -236,10 +228,9 @@ export default {
},

quickEditNumberTooltip (operator) {
return `Quick Edit<br><br>
<span class="keyboard">${this.$keys.ctrl}</span> + <i class="material-icons">mouse</i>: ${operator}5<br>
<span class="keyboard">${this.$keys.shift}</span> + <i class="material-icons">mouse</i>: ${operator}10<br>
<span class="keyboard">${this.$keys.alt}</span> + <i class="material-icons">mouse</i>: ${operator}100`
return this.$t('DataField.quickEdit.number.tooltip', {
operator
})
}
}
}
12 changes: 12 additions & 0 deletions src/devtools/mixins/entry-list.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { scrollIntoView } from 'src/util'

export default {
watch: {
inspectedIndex (value) {
this.$nextTick(() => {
const el = value === -1 ? this.$refs.baseEntry : this.$refs.entries[value]
el && scrollIntoView(this.$globalRefs.leftScroll, el, false)
})
}
}
}
Loading

0 comments on commit 000a632

Please sign in to comment.