Skip to content

Commit

Permalink
Improve keyboard navigation
Browse files Browse the repository at this point in the history
- QModal
  - fix not emmiting dismiss on ESC
  - focus after show
- QPopover
  - focus after show
  - refocus after hide (noRefocus prop)
  - allow toggle by keyboard ENTER
- QDialog
  - fix button focus
  - find button by class name (q-btn)
- QColor and QDatetime
  - fix tabindex lost on close
  - fix popup not closing on blur
- QColorPicker - fix incorrect tabindex on disable
- QDatetimePicker.mat - allow keyboard adjustment of all values
- QActionsheet - select option with ENTER/SPACE, navigation with TAB
- QAutocomplete - use QPopup with noFocus
- QKnob, QSlider, QRange - keyboard updating (UP|RIGHT +, DOWN|LEFT -, CTRL+... 10*)
- QSelect
  - remove autofocusFilter - always select filter if present
  - move keyboard navigation on QPopover
  - delay popover.reposition on filter to allow resize
- v-back-to-top, v-close-overlay, v-go-back, v-ripple - trigger by keyboard ENTER
  • Loading branch information
pdanpdan committed Apr 18, 2018
1 parent 54a15f6 commit 0520f94
Show file tree
Hide file tree
Showing 26 changed files with 293 additions and 77 deletions.
12 changes: 11 additions & 1 deletion dev/components/components/popover.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
:key="n"
v-close-overlay
@click.native="showNotify()"
@keyup.native.13.32="showNotify()"
:tabindex="0"
>
<q-item-main label="Label" sublabel="Click me" />
</q-item>
Expand All @@ -32,6 +34,8 @@
:key="n"
v-close-overlay
@click.native="showNotify()"
@keyup.native.13.32="showNotify()"
:tabindex="0"
>
<q-item-main label="X Label" sublabel="X Click me" />
</q-item>
Expand All @@ -57,7 +61,9 @@
v-for="n in 3"
:key="n"
v-close-overlay
@click="showNotify()"
@click.native="showNotify()"
@keyup.native.13.32="showNotify()"
:tabindex="0"
>
<q-item-main label="Label" />
</q-item>
Expand Down Expand Up @@ -118,6 +124,8 @@
src="~assets/map.png"
style="height: 150px; width: 200px;"
@click="showNotify(), $refs.popover3.hide()"
@keyup.13.32="showNotify(), $refs.popover3.hide()"
:tabindex="0"
>
</q-popover>
</q-btn>
Expand All @@ -140,6 +148,8 @@
v-for="n in 20"
:key="n"
@click.native="showNotify(), $refs.popover5.hide()"
@keyup.native.13.32="showNotify(), $refs.popover5.hide()"
:tabindex="0"
>
<q-item-main label="Label" sublabel="Click me" />
</q-item>
Expand Down
14 changes: 10 additions & 4 deletions dev/components/form/all.vue
Original file line number Diff line number Diff line change
Expand Up @@ -226,15 +226,15 @@

<p class="q-subtitle">Selected option: {{ JSON.stringify(option) }}</p>
<q-select :dark="dark" :error="error" :warning="warning" :disable="disable" :readonly="readonly" :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="onChange" @input="onInput" @clear="onClear" v-model="option" :options="countries" placeholder="Select" filter />
<q-select :dark="dark" :error="error" :warning="warning" :disable="disable" :readonly="readonly" :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="onChange" @input="onInput" @clear="onClear" v-model="option" :options="countries" float-label="Select (autofocus filter)" filter autofocus-filter />
<q-select :dark="dark" :error="error" :warning="warning" :disable="disable" :readonly="readonly" :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="onChange" @input="onInput" @clear="onClear" v-model="option" :options="countries" float-label="Select" filter />
<q-select :dark="dark" color="primary" :error="error" :warning="warning" :disable="disable" :readonly="readonly" inverted :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="val => { option = val; onChange(val) }" @input="onInput" @clear="onClear" :value="option" :options="countries" float-label="Select (onChange)" filter />

<p class="q-subtitle">Selected options: {{ JSON.stringify(options) }}</p>
<q-select :dark="dark" :error="error" :warning="warning" :disable="disable" :readonly="readonly" multiple :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="onChange" @input="onInput" @clear="onClear" v-model="options" :options="countries" float-label="Select multiple (autofocus filter)" filter autofocus-filter />
<q-select :dark="dark" :error="error" :warning="warning" :disable="disable" :readonly="readonly" multiple :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="onChange" @input="onInput" @clear="onClear" v-model="options" :options="countries" float-label="Select multiple" filter />
<q-select :dark="dark" color="primary" :error="error" :warning="warning" :disable="disable" :readonly="readonly" multiple inverted :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="val => { options = val; onChange(val) }" @input="onInput" @clear="onClear" :value="options" :options="countries" float-label="Select multiple (onChange)" filter />
<q-select :dark="dark" :error="error" :warning="warning" :disable="disable" :readonly="readonly" multiple chips :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="onChange" @input="onInput" @clear="onClear" v-model="options" :options="countries" float-label="Select multiple - chips (autofocus filter)" filter autofocus-filter />
<q-select :dark="dark" :error="error" :warning="warning" :disable="disable" :readonly="readonly" multiple chips :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="onChange" @input="onInput" @clear="onClear" v-model="options" :options="countries" float-label="Select multiple - chips" filter />
<q-select :dark="dark" color="primary" :error="error" :warning="warning" :disable="disable" :readonly="readonly" multiple chips inverted :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="val => { options = val; onChange(val) }" @input="onInput" @clear="onClear" :value="options" :options="countries" float-label="Select multiple - chips (onChange)" filter />
<q-select :dark="dark" color="amber-2" :error="error" :warning="warning" :disable="disable" :readonly="readonly" multiple chips inverted-light :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="val => { options = val; onChange(val) }" @input="onInput" @clear="onClear" :value="options" :options="countries" float-label="Select multiple - chips (onChange, autofocus filter)" filter autofocus-filter />
<q-select :dark="dark" color="amber-2" :error="error" :warning="warning" :disable="disable" :readonly="readonly" multiple chips inverted-light :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="val => { options = val; onChange(val) }" @input="onInput" @clear="onClear" :value="options" :options="countries" float-label="Select multiple - chips (onChange)" filter />
<q-select :dark="dark" color="white" :error="error" :warning="warning" :disable="disable" :readonly="readonly" multiple chips inverted-light :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="val => { options = val; onChange(val) }" @input="onInput" @clear="onClear" :value="options" :options="countries" float-label="Select multiple - chips (onChange)" filter />
<q-select :dark="dark" color="black" :error="error" :warning="warning" :disable="disable" :readonly="readonly" multiple chips inverted :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="val => { options = val; onChange(val) }" @input="onInput" @clear="onClear" :value="options" :options="countries" float-label="Select multiple - chips (onChange)" filter />

Expand All @@ -245,6 +245,9 @@
<q-color :dark="dark" :error="error" :warning="warning" :disable="disable" :readonly="readonly" :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="onChange" @input="onInput" @clear="onClear" v-model="color" :default-value="defaultColor" :float-label="`Color (default ${defaultColor})`" />
<q-color :dark="dark" color="primary" :error="error" :warning="warning" :disable="disable" :readonly="readonly" inverted :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="val => { color = val; onChange(val) }" @input="onInput" @clear="onClear" :value="color" :default-value="defaultColor" :float-label="`Color (default ${defaultColor}, onChange)`" :after="[ { icon: 'colorize', handler () { color = '#f00' } }]" />

<q-color :dark="dark" :error="error" :warning="warning" :disable="disable" :readonly="readonly" :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="onChange" @input="onInput" @clear="onClear" v-model="color" placeholder="Color - modal (RGBA)" modal format-model="rgba" :after="[ { icon: 'colorize', handler () { color = '#f00' } }]" />
<q-color :dark="dark" :error="error" :warning="warning" :disable="disable" :readonly="readonly" :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="onChange" @input="onInput" @clear="onClear" v-model="color" placeholder="Color - popover (RGBA)" popover format-model="rgba" :after="[ { icon: 'colorize', handler () { color = '#f00' } }]" />

<p class="q-subtitle">Color selected: {{ JSON.stringify(colorP) }}</p>
<div class="row gutter-sm">
<div>
Expand Down Expand Up @@ -273,6 +276,9 @@
<q-datetime :dark="dark" color="orange" :error="error" :warning="warning" :disable="disable" :readonly="readonly" type="datetime" formatModel="date" inverted :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="val => { date = val; onChange(val) }" @input="onInput" @clear="onClear" :value="date" :default-value="defaultDate" :float-label="`Datetime (default ${defaultDate}, onChange)`" />
<q-datetime :dark="dark" color="amber-2" :error="error" :warning="warning" :disable="disable" :readonly="readonly" type="datetime" formatModel="date" inverted-light :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="val => { date = val; onChange(val) }" @input="onInput" @clear="onClear" :value="date" :default-value="defaultDate" :float-label="`Datetime (default ${defaultDate}, onChange)`" :after="[ { icon: 'today', handler () { date = new Date() } }]" />

<q-datetime :dark="dark" :error="error" :warning="warning" :disable="disable" :readonly="readonly" type="date" formatModel="date" :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="onChange" @input="onInput" @clear="onClear" v-model="date" placeholder="Date - modal" modal :after="[ { icon: 'today', handler () { date = new Date('2018-10-21') } }]" />
<q-datetime :dark="dark" :error="error" :warning="warning" :disable="disable" :readonly="readonly" type="date" formatModel="date" :clearable="clearable" class="q-ma-sm" @focus="onFocus" @blur="onBlur" @change="onChange" @input="onInput" @clear="onClear" v-model="date" placeholder="Date - popover" popover :after="[ { icon: 'today', handler () { date = new Date('2018-10-21') } }]" />

<p class="q-subtitle">Date selected: {{ JSON.stringify(date) }}</p>
<div class="row gutter-sm">
<div>
Expand Down
6 changes: 3 additions & 3 deletions dev/components/form/select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@
<q-select simple v-model="select" :options="selectOptions"></q-select>

<p class="caption">With Filter</p>
<q-select filter autofocus-filter v-model="select" :options="selectListOptions"></q-select>
<q-select filter autofocus-filter v-model="select" :options="selectLongListOptions"></q-select>
<q-select filter autofocus-filter inverted v-model="select" :options="selectListOptions"></q-select>
<q-select filter v-model="select" :options="selectListOptions"></q-select>
<q-select filter v-model="select" :options="selectLongListOptions"></q-select>
<q-select filter inverted v-model="select" :options="selectListOptions"></q-select>
<q-select filter inverted v-model="select" :options="selectLongListOptions"></q-select>
<q-select filter multiple checkbox v-model="multipleSelect" :options="selectListOptions"></q-select>

Expand Down
5 changes: 2 additions & 3 deletions src/components/action-sheet/QActionSheet.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ export default {
tabindex: 0
},
nativeOn: {
click: this.__onCancel,
keydown: this.__onCancel
click: this.__onCancel
}
}, [
h(QItemMain, { staticClass: 'text-center text-primary' }, [
Expand Down Expand Up @@ -117,7 +116,7 @@ export default {
},
[this.grid ? 'on' : 'nativeOn']: {
click: () => this.__onOk(action),
keydown: () => this.__onOk(action)
keyup: ev => [13, 32].includes(ev.keyCode) && this.__onOk(action)
}
}, this.grid
? [
Expand Down
3 changes: 2 additions & 1 deletion src/components/autocomplete/QAutocomplete.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ export default {
'class': dark ? 'bg-dark' : null,
props: {
fit: true,
anchorClick: false
anchorClick: false,
noFocus: true
},
on: {
show: () => {
Expand Down
31 changes: 21 additions & 10 deletions src/components/color/QColor.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,24 +116,35 @@ export default {
this.$emit('focus')
},
__onBlur (e) {
if (this.$refs.popup && this.$refs.popup.showing) {
if (!this.focused) {
return
}

this.__onHide()
setTimeout(() => {
const el = document.activeElement
if (el !== document.body && !this.$refs.popup.$el.contains(el)) {
if (
!this.$refs.popup ||
!this.$refs.popup.showing ||
(el !== document.body && !this.$refs.popup.$el.contains(el))
) {
this.__onHide()
this.hide()
}
}, 1)
},
__onHide (forceUpdate) {
this.focused && this.$emit('blur')
this.focused = false
__onHide (forceUpdate, keepFocus) {
if (forceUpdate || this.isPopover) {
this.__update(forceUpdate)
}
if (!this.focused) {
return
}
if (keepFocus) {
this.$el.focus()
return
}
this.$emit('blur')
this.focused = false
},
__setModel (val, forceUpdate) {
this.model = clone(val)
Expand Down Expand Up @@ -188,7 +199,7 @@ export default {
},
on: {
click: () => {
this.__onHide()
this.__onHide(false, true)
this.hide()
}
}
Expand All @@ -203,7 +214,7 @@ export default {
},
on: {
click: () => {
this.__onHide(true)
this.__onHide(true, true)
this.hide()
}
}
Expand Down Expand Up @@ -264,7 +275,7 @@ export default {
},
on: {
show: this.__onFocus,
hide: val => this.__onHide(true)
hide: val => this.__onHide(true, true)
}
}, this.__getPicker(h))
: h(QModal, {
Expand All @@ -277,7 +288,7 @@ export default {
transition: this.transition
},
on: {
dismiss: this.__onHide
dismiss: () => this.__onHide(false, true)
}
}, this.__getPicker(h, true)),

Expand Down
6 changes: 3 additions & 3 deletions src/components/color/QColorPicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ export default {
min: 0,
max,
readonly: !this.editable,
tabindex: this.disable ? 0 : -1
tabindex: this.editable ? 0 : -1
},
staticClass: 'full-width text-center q-no-input-spinner',
domProps: {
Expand All @@ -232,10 +232,10 @@ export default {
domProps: { value: this.model.hex },
attrs: {
readonly: !this.editable,
tabindex: this.disable ? 0 : -1
tabindex: this.editable ? 0 : -1
},
on: {
input: this.__onHexChange,
change: this.__onHexChange,
blur: evt => this.editable && this.__onHexChange(evt, true)
},
staticClass: 'full-width text-center uppercase'
Expand Down
31 changes: 21 additions & 10 deletions src/components/datetime/QDatetime.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,24 +129,35 @@ export default {
this.$emit('focus')
},
__onBlur (e) {
if (this.$refs.popup && this.$refs.popup.showing) {
if (!this.focused) {
return
}

this.__onHide()
setTimeout(() => {
const el = document.activeElement
if (el !== document.body && !this.$refs.popup.$el.contains(el)) {
if (
!this.$refs.popup ||
!this.$refs.popup.showing ||
(el !== document.body && !this.$refs.popup.$el.contains(el))
) {
this.__onHide()
this.hide()
}
}, 1)
},
__onHide (forceUpdate) {
this.focused && this.$emit('blur')
this.focused = false
__onHide (forceUpdate, keepFocus) {
if (forceUpdate || this.isPopover) {
this.__update(forceUpdate)
}
if (!this.focused) {
return
}
if (keepFocus) {
this.$el.focus()
return
}
this.$emit('blur')
this.focused = false
},
__setModel (val, forceUpdate) {
this.model = clone(val)
Expand Down Expand Up @@ -220,7 +231,7 @@ export default {
},
on: {
click: () => {
this.__onHide()
this.__onHide(false, true)
this.hide()
this.__resetView()
}
Expand All @@ -237,7 +248,7 @@ export default {
},
on: {
click: () => {
this.__onHide(true)
this.__onHide(true, true)
this.hide()
this.__resetView()
}
Expand Down Expand Up @@ -299,7 +310,7 @@ export default {
},
on: {
show: this.__onFocus,
hide: val => this.__onHide(true)
hide: () => this.__onHide(true, true)
}
}, this.__getPicker(h))
: h(QModal, {
Expand All @@ -312,7 +323,7 @@ export default {
transition: this.transition
},
on: {
dismiss: this.__onHide
dismiss: () => this.__onHide(false, true)
}
}, this.__getPicker(h, true)),

Expand Down
Loading

0 comments on commit 0520f94

Please sign in to comment.