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
- QDialog - fix button focus
- 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
  • Loading branch information
pdanpdan committed Apr 17, 2018
1 parent f6a9e28 commit 8c5af21
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 38 deletions.
6 changes: 6 additions & 0 deletions dev/components/form/all.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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
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
47 changes: 37 additions & 10 deletions src/components/datetime/QDatetimePicker.mat.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,29 @@
:class="{active: view === 'month'}"
class="q-datetime-link small col-auto col-md-12"
@click="!disable && (view = 'month')"
@keydown.down.left="setMonth(month - 1, true)"
@keydown.up.right="setMonth(month + 1, true)"
:tabindex="0"
>
{{ monthString }}
</span>
<span
:class="{active: view === 'day'}"
class="q-datetime-link col-auto col-md-12"
@click="!disable && (view = 'day')"
@keydown.down.left="setDay(day - 1, true)"
@keydown.up.right="setDay(day + 1, true)"
:tabindex="0"
>
{{ day }}
</span>
<span
:class="{active: view === 'year'}"
class="q-datetime-link small col-auto col-md-12"
@click="!disable && (view = 'year')"
@keydown.down.left="setYear(year - 1, true)"
@keydown.up.right="setYear(year + 1, true)"
:tabindex="0"
>
{{ year }}
</span>
Expand All @@ -31,19 +40,25 @@
v-if="typeHasTime"
class="q-datetime-time row flex-center"
>
<div class="q-datetime-clockstring col-auto col-md-12">
<div class="q-datetime-clockstring col-auto col-md-12 row no-wrap flex-center">
<span
:class="{active: view === 'hour'}"
class="q-datetime-link col-auto col-md-12"
class="q-datetime-link col-md text-right q-pr-sm"
@click="!disable && (view = 'hour')"
@keydown.down.left="setHour(hour - 1, true)"
@keydown.up.right="setHour(hour + 1, true)"
:tabindex="0"
>
{{ __pad(hour, '&nbsp;&nbsp;') }}
{{ hour }}
</span>
<span style="opacity: 0.6">:</span>
<span
:class="{active: view === 'minute'}"
class="q-datetime-link col-auto col-md-12"
class="q-datetime-link col-md text-left q-pl-sm"
@click="!disable && (view = 'minute')"
@keydown.down.left="setMinute(minute - 1, true)"
@keydown.up.right="setMinute(minute + 1, true)"
:tabindex="0"
>
{{ __pad(minute) }}
</span>
Expand All @@ -53,11 +68,15 @@
:class="{active: am}"
class="q-datetime-link"
@click="toggleAmPm()"
@keyup.13.32="toggleAmPm()"
:tabindex="0"
>AM</div>
<div
:class="{active: !am}"
class="q-datetime-link"
@click="toggleAmPm()"
@keyup.13.32="toggleAmPm()"
:tabindex="0"
>PM</div>
</div>
</div>
Expand All @@ -76,6 +95,7 @@
:class="{active: n + yearMin === year}"
:disable="!editable"
@click="setYear(n + yearMin)"
:tabindex="-1"
>
{{ n + yearMin }}
</q-btn>
Expand All @@ -93,6 +113,7 @@
:class="{active: month === index + monthMin}"
:disable="!editable"
@click="setMonth(index + monthMin, true)"
:tabindex="-1"
>
{{ $q.i18n.date.months[index + monthMin - 1] }}
</q-btn>
Expand All @@ -112,6 +133,7 @@
:repeatTimeout="__repeatTimeout"
:disable="beforeMinDays > 0 || disable || readonly"
@click="setMonth(month - 1)"
:tabindex="-1"
></q-btn>
<div class="col q-datetime-month-stamp">
{{ monthStamp }}
Expand All @@ -125,6 +147,7 @@
:repeatTimeout="__repeatTimeout"
:disable="afterMaxDays > 0 || disable || readonly"
@click="setMonth(month + 1)"
:tabindex="-1"
></q-btn>
</div>
<div class="q-datetime-weekdays row items-center justify-start">
Expand Down Expand Up @@ -391,25 +414,29 @@ export default {
},
methods: {
/* date */
setYear (value) {
setYear (value, skipView) {
if (this.editable) {
this.view = 'day'
if (!skipView) {
this.view = 'day'
}
this.model = new Date(this.model.setFullYear(this.__parseTypeValue('year', value)))
}
},
setMonth (value) {
setMonth (value, skipView) {
if (this.editable) {
this.view = 'day'
if (!skipView) {
this.view = 'day'
}
this.model = adjustDate(this.model, {month: value})
}
},
setDay (value) {
setDay (value, skipView) {
if (this.editable) {
this.model = new Date(this.model.setDate(this.__parseTypeValue('date', value)))
if (this.type === 'date') {
this.$emit('canClose')
}
else {
else if (!skipView) {
this.view = 'hour'
}
}
Expand Down
13 changes: 9 additions & 4 deletions src/components/datetime/datetime.mat.styl
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ div + .q-datetime-time
.q-datetime-link
cursor pointer
opacity .6
outline none
&.active
opacity 1

Expand Down Expand Up @@ -168,10 +169,14 @@ div + .q-datetime-time
&.q-datetime-day-active > span, &:not(.q-datetime-fillerday):not(.disabled):not(.q-datetime-day-active):hover
color black

body.desktop .q-datetime-clock-position:not(.active):hover
background $grey-2 !important
body.desktop .q-datetime-dark .q-datetime-clock-position:not(.active):hover
color black
body.desktop
.q-datetime-clock-position:not(.active):hover
background $grey-2 !important
.q-datetime-dark .q-datetime-clock-position:not(.active):hover
color black
.q-datetime-link
&:focus
outline 1px dashed rgba(255, 255, 255, .6)

.q-datetime-clock-position
position absolute
Expand Down
2 changes: 1 addition & 1 deletion src/components/dialog/QDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export default {
show: () => {
this.$emit('show')

if (!this.$q.platform.is.desktop || (!this.prompt && !this.options)) {
if (!this.$q.platform.is.desktop) {
return
}

Expand Down
Loading

0 comments on commit 8c5af21

Please sign in to comment.