diff --git a/dev/components/components/button.vue b/dev/components/components/button.vue index 7a33bbb92453..13c2b780fbc6 100644 --- a/dev/components/components/button.vue +++ b/dev/components/components/button.vue @@ -50,10 +50,17 @@

-
- - - + +
+
+ +
+
+ +
+
+ +
@@ -480,7 +487,9 @@ export default { loading2: false, percentage: 0, clickTimes: 0, - test: 'Initial value' + test: 'Initial value', + testN: 0, + tag: 'button' } }, methods: { @@ -517,9 +526,11 @@ export default { }, submit () { this.$q.notify('Submit called') + console.log('test', this.test, 'testN', this.testN) }, reset () { this.test = 'Initial value' + this.testN = 0 this.$q.notify('Reset called') } }, diff --git a/dev/components/components/fab.vue b/dev/components/components/fab.vue index 5ff865d56119..9a3c26209ee8 100644 --- a/dev/components/components/fab.vue +++ b/dev/components/components/fab.vue @@ -19,7 +19,6 @@
- @@ -52,6 +51,8 @@ + +

There's also the absolute positioned one on bottom right of screen which maintains position on Page scroll. diff --git a/dev/components/components/popover.vue b/dev/components/components/popover.vue index 720bcfcddbff..311bc97c97ad 100644 --- a/dev/components/components/popover.vue +++ b/dev/components/components/popover.vue @@ -17,6 +17,8 @@ :key="n" v-close-overlay @click.native="showNotify()" + @keyup.native.13.32="showNotify()" + :tabindex="0" > @@ -32,6 +34,8 @@ :key="n" v-close-overlay @click.native="showNotify()" + @keyup.native.13.32="showNotify()" + :tabindex="0" > @@ -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" > @@ -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" > @@ -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" > diff --git a/dev/components/form/select.vue b/dev/components/form/select.vue index a48946c239e1..1a6d18f823b2 100644 --- a/dev/components/form/select.vue +++ b/dev/components/form/select.vue @@ -58,11 +58,11 @@

With Filter

- - - - - + + + + +

With Static Label

diff --git a/src/components/action-sheet/QActionSheet.js b/src/components/action-sheet/QActionSheet.js index 2dadd7c63a11..4b8e48735e72 100644 --- a/src/components/action-sheet/QActionSheet.js +++ b/src/components/action-sheet/QActionSheet.js @@ -59,7 +59,7 @@ export default { }, nativeOn: { click: this.__onCancel, - keydown: this.__onKeyCancel + keyup: this.__onKeyCancel } }, [ h(QItemMain, { staticClass: 'text-center text-primary' }, [ @@ -116,7 +116,7 @@ export default { }, [this.grid ? 'on' : 'nativeOn']: { click: () => this.__onOk(action), - keydown: e => { + keyup: e => { if (getEventKey(e) === /* Enter */ 13) { this.__onOk(action) } diff --git a/src/components/autocomplete/QAutocomplete.js b/src/components/autocomplete/QAutocomplete.js index fb55c630eee0..e488b754dd42 100644 --- a/src/components/autocomplete/QAutocomplete.js +++ b/src/components/autocomplete/QAutocomplete.js @@ -218,7 +218,8 @@ export default { 'class': dark ? 'bg-dark' : null, props: { fit: true, - anchorClick: false + anchorClick: false, + noFocus: true }, on: { show: () => { diff --git a/src/components/color/QColorPicker.js b/src/components/color/QColorPicker.js index 066b33a102a2..4458ee93365e 100644 --- a/src/components/color/QColorPicker.js +++ b/src/components/color/QColorPicker.js @@ -127,8 +127,7 @@ export default { ? [{ name: 'touch-pan', modifiers: { - prevent: true, - stop: true + mightPrevent: true }, value: this.__saturationPan }] diff --git a/src/components/datetime/QDatetimePicker.mat.vue b/src/components/datetime/QDatetimePicker.mat.vue index 5d11bff476bc..e19022a0c142 100644 --- a/src/components/datetime/QDatetimePicker.mat.vue +++ b/src/components/datetime/QDatetimePicker.mat.vue @@ -7,23 +7,35 @@ - {{ monthString }} + + {{ monthString }} + - {{ day }} + + {{ day }} + - {{ year }} + + {{ year }} + @@ -31,34 +43,52 @@ v-if="typeHasTime" class="q-datetime-time row flex-center" > -
+
- {{ __pad(hour, '  ') }} + + {{ hour }} + : - {{ __pad(minute) }} + + {{ __pad(minute) }} +
+ @keyup.13.32="toggleAmPm()" + :tabindex="0" + > + + AM + +
+ @keyup.13.32="toggleAmPm()" + :tabindex="0" + > + + PM + +
@@ -76,6 +106,7 @@ :class="{active: n + yearMin === year}" :disable="!editable" @click="setYear(n + yearMin)" + :tabindex="-1" > {{ n + yearMin }}
@@ -93,6 +124,7 @@ :class="{active: month === index + monthMin}" :disable="!editable" @click="setMonth(index + monthMin, true)" + :tabindex="-1" > {{ $q.i18n.date.months[index + monthMin - 1] }} @@ -112,6 +144,7 @@ :repeat-timeout="__repeatTimeout" :disable="beforeMinDays > 0 || disable || readonly" @click="setMonth(month - 1)" + :tabindex="-1" />
{{ monthStamp }} @@ -125,6 +158,7 @@ :repeat-timeout="__repeatTimeout" :disable="afterMaxDays > 0 || disable || readonly" @click="setMonth(month + 1)" + :tabindex="-1" />
@@ -392,25 +426,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' } } diff --git a/src/components/datetime/datetime.mat.styl b/src/components/datetime/datetime.mat.styl index 443f3e0cc278..cfdbb0db4673 100644 --- a/src/components/datetime/datetime.mat.styl +++ b/src/components/datetime/datetime.mat.styl @@ -39,6 +39,10 @@ div + .q-datetime-time .q-datetime-link cursor pointer opacity .6 + > span + display inline-block + width 100% + outline none &.active opacity 1 @@ -168,10 +172,11 @@ 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-clock-position position absolute diff --git a/src/components/dialog/QDialog.js b/src/components/dialog/QDialog.js index bdea517220a3..77834c75a8fc 100644 --- a/src/components/dialog/QDialog.js +++ b/src/components/dialog/QDialog.js @@ -23,6 +23,7 @@ export default { preventClose: Boolean, noBackdropDismiss: Boolean, noEscDismiss: Boolean, + noRefocus: Boolean, position: String, color: { type: String, @@ -86,6 +87,7 @@ export default { minimized: true, noBackdropDismiss: this.noBackdropDismiss || this.preventClose, noEscDismiss: this.noEscDismiss || this.preventClose, + noRefocus: this.noRefocus, position: this.position }, on: { @@ -95,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 } @@ -108,7 +110,7 @@ export default { return } - node = this.$refs.modal.$el.getElementsByTagName('BUTTON') + node = this.$refs.modal.$el.getElementsByClassName('q-btn') if (node.length) { node[node.length - 1].focus() } diff --git a/src/components/fab/QFab.js b/src/components/fab/QFab.js index 7911518ccc70..54a64b3aa2bc 100644 --- a/src/components/fab/QFab.js +++ b/src/components/fab/QFab.js @@ -8,7 +8,10 @@ export default { mixins: [FabMixin, ModelToggleMixin], provide () { return { - __qFabClose: this.hide + __qFabClose: evt => this.hide(evt).then(() => { + this.$refs.trigger && this.$refs.trigger.$el && this.$refs.trigger.$el.focus() + return evt + }) } }, props: { @@ -37,6 +40,7 @@ export default { } }, [ h(QBtn, { + ref: 'trigger', props: { fab: true, outline: this.outline, @@ -64,7 +68,7 @@ export default { h('div', { staticClass: 'q-fab-actions flex no-wrap inline items-center', 'class': `q-fab-${this.direction}` - }, this.$slots.default) + }, this.showing ? this.$slots.default : null) ]) } } diff --git a/src/components/knob/QKnob.js b/src/components/knob/QKnob.js index 9e912d834636..d19ca2440260 100644 --- a/src/components/knob/QKnob.js +++ b/src/components/knob/QKnob.js @@ -66,6 +66,9 @@ export default { }, computedDecimals () { return this.decimals !== void 0 ? this.decimals || 0 : (String(this.step).trim('0').split('.')[1] || '').length + }, + computedStep () { + return this.decimals !== void 0 ? 1 / Math.pow(10, this.decimals || 0) : this.step } }, data () { @@ -142,18 +145,35 @@ export default { }, 100) this.__onInput(ev, this.centerPosition, true) }, + __onKeyDown (ev) { + const keyCode = ev.keyCode + if (!this.editable || ![37, 40, 39, 38].includes(keyCode)) { + return + } + const step = ev.ctrlKey ? 10 * this.computedStep : this.computedStep + const offset = [37, 40].includes(keyCode) ? -step : step + this.__onInputValue(between(this.model + offset, this.min, this.max)) + }, + __onKeyUp (ev) { + const keyCode = ev.keyCode + if (!this.editable || ![37, 40, 39, 38].includes(keyCode)) { + return + } + this.__emitChange() + }, __onInput (ev, center = this.__getCenter(), emitChange) { if (!this.editable) { return } - let + const pos = position(ev), height = Math.abs(pos.top - center.top), distance = Math.sqrt( Math.pow(Math.abs(pos.top - center.top), 2) + Math.pow(Math.abs(pos.left - center.left), 2) - ), - angle = Math.asin(height / distance) * (180 / Math.PI) + ) + + let angle = Math.asin(height / distance) * (180 / Math.PI) if (pos.top < center.top) { angle = center.left < pos.left ? 90 - angle : 270 + angle @@ -166,16 +186,18 @@ export default { angle = 360 - angle } - let + const model = this.min + (angle / 360) * (this.max - this.min), modulo = model % this.step - let value = between( + const value = between( model - modulo + (Math.abs(modulo) >= this.step / 2 ? (modulo < 0 ? -1 : 1) * this.step : 0), this.min, this.max ) - + this.__onInputValue(value, emitChange) + }, + __onInputValue (value, emitChange) { if (this.computedDecimals) { value = parseFloat(value.toFixed(this.computedDecimals)) } @@ -192,13 +214,16 @@ export default { this.$emit('input', value) if (emitChange) { - this.$nextTick(() => { - if (JSON.stringify(value) !== JSON.stringify(this.value)) { - this.$emit('change', value) - } - }) + this.__emitChange(value) } }, + __emitChange (value = this.model) { + this.$nextTick(() => { + if (JSON.stringify(value) !== JSON.stringify(this.value)) { + this.$emit('change', value) + } + }) + }, __getCenter () { let knobOffset = offset(this.$el) return { @@ -255,7 +280,16 @@ export default { h( 'div', - { staticClass: 'q-knob-label row flex-center content-center' }, + { + staticClass: 'q-knob-label row flex-center content-center', + attrs: { + tabindex: this.editable ? 0 : -1 + }, + on: { + keydown: this.__onKeyDown, + keyup: this.__onKeyUp + } + }, this.$slots.default || [ h('span', [ this.model ]) ] diff --git a/src/components/modal/QModal.js b/src/components/modal/QModal.js index 83698c95142f..921aad1bb1fb 100644 --- a/src/components/modal/QModal.js +++ b/src/components/modal/QModal.js @@ -83,6 +83,7 @@ export default { default: false }, noRouteDismiss: Boolean, + noRefocus: Boolean, minimized: Boolean, maximized: Boolean }, @@ -146,6 +147,9 @@ export default { }) }, __show () { + if (!this.noRefocus) { + this.__refocusTarget = document.activeElement + } const body = document.body body.appendChild(this.$el) @@ -156,6 +160,7 @@ export default { if (!this.noEscDismiss) { this.hide().then(() => { this.$emit('escape-key') + this.$emit('dismiss') }) } }) @@ -171,11 +176,15 @@ export default { el.scrollTop = 0 }) }) + this.$nextTick(() => content.focus()) }, __hide () { EscapeKey.pop() this.__preventScroll(false) this.__register(false) + if (!this.noRefocus && this.__refocusTarget) { + this.__refocusTarget.focus() + } }, __stopPropagation (e) { e.stopPropagation() @@ -245,6 +254,7 @@ export default { staticClass: 'modal-content scroll', style: this.modalCss, 'class': this.contentClasses, + attrs: { tabindex: -1 }, on: { click: this.__stopPropagation, touchstart: this.__stopPropagation diff --git a/src/components/modal/modal.ios.styl b/src/components/modal/modal.ios.styl index e5122fe40340..da33e9d6f172 100644 --- a/src/components/modal/modal.ios.styl +++ b/src/components/modal/modal.ios.styl @@ -18,6 +18,7 @@ maximized-modal() max-height 80vh border-radius $modal-border-radius -webkit-backface-visibility hidden + outline none .modal z-index $z-modal diff --git a/src/components/modal/modal.mat.styl b/src/components/modal/modal.mat.styl index 78171570ea48..dd821d5335e5 100644 --- a/src/components/modal/modal.mat.styl +++ b/src/components/modal/modal.mat.styl @@ -16,6 +16,7 @@ maximized-modal() min-width 280px max-height 80vh -webkit-backface-visibility hidden + outline none .modal z-index $z-modal diff --git a/src/components/popover/QPopover.js b/src/components/popover/QPopover.js index c739380ab9a4..66c36c87e740 100644 --- a/src/components/popover/QPopover.js +++ b/src/components/popover/QPopover.js @@ -39,6 +39,8 @@ export default { type: Array, validator: offsetValidator }, + noFocus: Boolean, + noRefocus: Boolean, disable: Boolean }, watch: { @@ -59,6 +61,8 @@ export default { return h('div', { staticClass: 'q-popover scroll', + ref: 'content', + attrs: { tabindex: -1 }, on: { click (e) { e.stopPropagation() } } @@ -75,6 +79,7 @@ export default { if (this.anchorClick) { this.anchorEl.classList.add('cursor-pointer') this.anchorEl.addEventListener('click', this.toggle) + this.anchorEl.addEventListener('keyup', this.__toggleKey) } }) if (this.value) { @@ -84,10 +89,14 @@ export default { beforeDestroy () { if (this.anchorClick && this.anchorEl) { this.anchorEl.removeEventListener('click', this.toggle) + this.anchorEl.removeEventListener('keyup', this.__toggleKey) } }, methods: { __show (evt) { + if (!this.noRefocus) { + this.__refocusTarget = document.activeElement + } document.body.appendChild(this.$el) EscapeKey.register(() => { this.hide() }) this.scrollTarget = getScrollTarget(this.anchorEl) @@ -96,12 +105,20 @@ export default { this.__updatePosition(0, evt, true) clearTimeout(this.timer) + if (!this.noFocus && this.$refs.content) { + this.$refs.content.focus() + } this.timer = setTimeout(() => { document.body.addEventListener('click', this.__bodyHide, true) document.body.addEventListener('touchstart', this.__bodyHide, true) this.showPromise && this.showPromiseResolve() }, 0) }, + __toggleKey (evt) { + if (evt.keyCode === 13) { + this.toggle(evt) + } + }, __bodyHide (evt) { if ( evt && evt.target && @@ -123,6 +140,9 @@ export default { document.body.removeChild(this.$el) this.hidePromise && this.hidePromiseResolve() + if (!this.noRefocus && this.__refocusTarget) { + this.__refocusTarget.focus() + } }, reposition (event, animate) { if (this.fit) { diff --git a/src/components/popover/popover.ios.styl b/src/components/popover/popover.ios.styl index 4c7634b9cce6..15e9877e34af 100644 --- a/src/components/popover/popover.ios.styl +++ b/src/components/popover/popover.ios.styl @@ -6,6 +6,7 @@ overflow-y auto overflow-x hidden max-width $popover-max-width + outline none > .q-list:only-child border none diff --git a/src/components/popover/popover.mat.styl b/src/components/popover/popover.mat.styl index 4c7634b9cce6..15e9877e34af 100644 --- a/src/components/popover/popover.mat.styl +++ b/src/components/popover/popover.mat.styl @@ -6,6 +6,7 @@ overflow-y auto overflow-x hidden max-width $popover-max-width + outline none > .q-list:only-child border none diff --git a/src/components/range/QRange.js b/src/components/range/QRange.js index f20418e2bea7..2116de40c322 100644 --- a/src/components/range/QRange.js +++ b/src/components/range/QRange.js @@ -240,6 +240,29 @@ export default { this.currentMinPercentage = (this.model.min - this.min) / (this.max - this.min) this.currentMaxPercentage = (this.model.max - this.min) / (this.max - this.min) }, + __onKeyDown (ev, type) { + const keyCode = ev.keyCode + if (!this.editable || ![37, 40, 39, 38].includes(keyCode)) { + return + } + const + decimals = this.computedDecimals, + step = ev.ctrlKey ? 10 * this.computedStep : this.computedStep, + offset = [37, 40].includes(keyCode) ? -step : step, + model = decimals ? parseFloat((this.model[type] + offset).toFixed(decimals)) : (this.model[type] + offset) + + this.model[type] = between(model, type === 'min' ? this.min : this.model.min, type === 'max' ? this.max : this.model.max) + this.currentMinPercentage = (this.model.min - this.min) / (this.max - this.min) + this.currentMaxPercentage = (this.model.max - this.min) / (this.max - this.min) + this.__update() + }, + __onKeyUp (ev, type) { + const keyCode = ev.keyCode + if (!this.editable || ![37, 40, 39, 38].includes(keyCode)) { + return + } + this.__update(true) + }, __validateProps () { if (this.min >= this.max) { console.error('Range error: min >= max', this.$el, this.min, this.max) @@ -266,7 +289,12 @@ export default { 'class': [ edge ? 'handle-at-minimum' : null, { dragging: this.dragging } - ] + ], + attrs: { tabindex: this.editable ? 0 : -1 }, + on: { + keydown: ev => this.__onKeyDown(ev, lower), + keyup: ev => this.__onKeyUp(ev, lower) + } }, [ this.label || this.labelAlways ? h(QChip, { diff --git a/src/components/select/QSelect.vue b/src/components/select/QSelect.vue index 5331a0f08677..62f3fefd84ab 100644 --- a/src/components/select/QSelect.vue +++ b/src/components/select/QSelect.vue @@ -77,13 +77,13 @@ :class="dark ? 'bg-dark' : null" @show="__onShow" @hide="__onClose(true)" + @keydown.native="__keyboardHandleKey" > popover.reposition()) } }, @@ -388,7 +387,7 @@ export default { return } this.__onFocus() - if (this.filter && this.autofocusFilter) { + if (this.filter) { this.$refs.filter.focus() } }, diff --git a/src/components/slider/QSlider.js b/src/components/slider/QSlider.js index 0f8ee4ebb457..6d66bba450c3 100644 --- a/src/components/slider/QSlider.js +++ b/src/components/slider/QSlider.js @@ -4,6 +4,7 @@ import { notDivides, SliderMixin } from './slider-utils' +import { between } from '../../utils/format' import { QChip } from '../chip' export default { @@ -94,6 +95,28 @@ export default { this.model = getModel(percentage, this.min, this.max, this.step, this.computedDecimals) this.currentPercentage = (this.model - this.min) / (this.max - this.min) }, + __onKeyDown (ev) { + const keyCode = ev.keyCode + if (!this.editable || ![37, 40, 39, 38].includes(keyCode)) { + return + } + const + decimals = this.computedDecimals, + step = ev.ctrlKey ? 10 * this.computedStep : this.computedStep, + offset = [37, 40].includes(keyCode) ? -step : step, + model = decimals ? parseFloat((this.model + offset).toFixed(decimals)) : (this.model + offset) + + this.model = between(model, this.min, this.max) + this.currentPercentage = (this.model - this.min) / (this.max - this.min) + this.__update() + }, + __onKeyUp (ev) { + const keyCode = ev.keyCode + if (!this.editable || ![37, 40, 39, 38].includes(keyCode)) { + return + } + this.__update(true) + }, __validateProps () { if (this.min >= this.max) { console.error('Range error: min >= max', this.$el, this.min, this.max) @@ -121,6 +144,11 @@ export default { 'class': { dragging: this.dragging, 'handle-at-minimum': !this.fillHandleAlways && this.model === this.min + }, + attrs: { tabindex: this.editable ? 0 : -1 }, + on: { + keydown: this.__onKeyDown, + keyup: this.__onKeyUp } }, [ this.label || this.labelAlways diff --git a/src/components/slider/slider-utils.js b/src/components/slider/slider-utils.js index 41b3c075a970..426fa46e0d68 100644 --- a/src/components/slider/slider-utils.js +++ b/src/components/slider/slider-utils.js @@ -88,6 +88,9 @@ export let SliderMixin = { }, computedDecimals () { return this.decimals !== void 0 ? this.decimals || 0 : (String(this.step).trim('0').split('.')[1] || '').length + }, + computedStep () { + return this.decimals !== void 0 ? 1 / Math.pow(10, this.decimals || 0) : this.step } }, methods: { diff --git a/src/components/tab/QRouteTab.js b/src/components/tab/QRouteTab.js index d9eca693f2ea..1fcd371107bd 100644 --- a/src/components/tab/QRouteTab.js +++ b/src/components/tab/QRouteTab.js @@ -51,7 +51,8 @@ export default { exactActiveClass: 'q-router-link-exact-active' }, nativeOn: { - click: this.select + click: this.select, + keyup: e => e.keyCode === 13 && this.select(e) }, staticClass: 'q-tab column flex-center relative-position', 'class': this.classes, diff --git a/src/components/tab/QTab.js b/src/components/tab/QTab.js index f7100733e6d2..881fbe3758f4 100644 --- a/src/components/tab/QTab.js +++ b/src/components/tab/QTab.js @@ -24,7 +24,8 @@ export default { staticClass: 'q-tab column flex-center relative-position', 'class': this.classes, on: { - click: this.select + click: this.select, + keyup: e => e.keyCode === 13 && this.select(e) }, directives: process.env.THEME === 'mat' ? [{ name: 'ripple' }] diff --git a/src/components/tab/tab-mixin.js b/src/components/tab/tab-mixin.js index 7f739856e042..a0bbd8ea99a6 100644 --- a/src/components/tab/tab-mixin.js +++ b/src/components/tab/tab-mixin.js @@ -24,7 +24,8 @@ export default { }, alert: Boolean, count: [Number, String], - color: String + color: String, + tabindex: Number }, inject: { data: { @@ -71,6 +72,9 @@ export default { if (!this.active || !this.data.highlight) { return 'display: none;' } + }, + computedTabIndex () { + return this.disable || this.active ? -1 : this.tabindex || 0 } }, methods: { @@ -123,6 +127,11 @@ export default { })) } + child.push(h('div', { + staticClass: 'q-tab-focus-helper absolute-full', + attrs: { tabindex: this.computedTabIndex } + })) + return child } } diff --git a/src/components/tab/tabs.ios.styl b/src/components/tab/tabs.ios.styl index c81ee31ecc5c..73049f809cb6 100644 --- a/src/components/tab/tabs.ios.styl +++ b/src/components/tab/tabs.ios.styl @@ -55,6 +55,14 @@ .q-tab-icon font-size $tabs-icon-font-size +.q-tab-focus-helper + z-index -1 + outline none + &:focus + z-index unset + background currentColor + opacity .1 + @media (max-width $breakpoint-sm-max) .q-tab &.hide-icon .q-tab-icon-parent, diff --git a/src/components/tab/tabs.mat.styl b/src/components/tab/tabs.mat.styl index c05abdbe234d..92cea9945bc5 100644 --- a/src/components/tab/tabs.mat.styl +++ b/src/components/tab/tabs.mat.styl @@ -48,6 +48,14 @@ .q-tab-icon font-size $tabs-icon-font-size +.q-tab-focus-helper + z-index -1 + outline none + &:focus + z-index unset + background currentColor + opacity .1 + @media (max-width $breakpoint-sm-max) .q-tab &.hide-icon .q-tab-icon-parent, diff --git a/src/directives/back-to-top.js b/src/directives/back-to-top.js index a24cbd92bb94..a70de915e73f 100644 --- a/src/directives/back-to-top.js +++ b/src/directives/back-to-top.js @@ -54,6 +54,11 @@ export default { }, goToTop () { setScrollPosition(ctx.scrollTarget, 0, ctx.animate ? ctx.duration : 0) + }, + goToTopKey (evt) { + if (evt.keyCode === 13) { + setScrollPosition(ctx.scrollTarget, 0, ctx.animate ? ctx.duration : 0) + } } } ctx.update = debounce(ctx.updateNow, 25) @@ -68,6 +73,7 @@ export default { ctx.scrollTarget.addEventListener('scroll', ctx.update, listenOpts.passive) window.addEventListener('resize', ctx.update, listenOpts.passive) el.addEventListener('click', ctx.goToTop) + el.addEventListener('keyup', ctx.goToTopKey) }, update (el, binding) { if (JSON.stringify(binding.oldValue) !== JSON.stringify(binding.value)) { @@ -85,6 +91,7 @@ export default { ctx.scrollTarget.removeEventListener('scroll', ctx.update, listenOpts.passive) window.removeEventListener('resize', ctx.update, listenOpts.passive) el.removeEventListener('click', ctx.goToTop) + el.removeEventListener('keyup', ctx.goToTopKey) delete el.__qbacktotop } } diff --git a/src/directives/close-overlay.js b/src/directives/close-overlay.js index ecba2208fb54..15784df558f6 100644 --- a/src/directives/close-overlay.js +++ b/src/directives/close-overlay.js @@ -1,23 +1,31 @@ export default { name: 'close-overlay', bind (el, binding, vnode) { - const handler = ev => { - let vm = vnode.componentInstance - while ((vm = vm.$parent)) { - const name = vm.$options.name - if (name === 'QPopover' || name === 'QModal') { - vm.hide(ev) - break + const + handler = ev => { + let vm = vnode.componentInstance + while ((vm = vm.$parent)) { + const name = vm.$options.name + if (name === 'QPopover' || name === 'QModal') { + vm.hide(ev) + break + } + } + }, + handlerKey = ev => { + if (ev.keyCode === 13) { + handler(ev) } } - } - el.__qclose = { handler } + el.__qclose = { handler, handlerKey } el.addEventListener('click', handler) + el.addEventListener('keyup', handlerKey) }, unbind (el) { const ctx = el.__qclose if (!ctx) { return } el.removeEventListener('click', ctx.handler) + el.removeEventListener('keyup', ctx.handlerKey) delete el.__qclose } } diff --git a/src/directives/go-back.js b/src/directives/go-back.js index d7e4449ddbf9..7c015832435e 100644 --- a/src/directives/go-back.js +++ b/src/directives/go-back.js @@ -15,9 +15,15 @@ export default { vnode.context.$router.replace(ctx.value) } } + ctx.goBackKey = ev => { + if (ev.keyCode === 13) { + ctx.goBack(ev) + } + } el.__qgoback = ctx el.addEventListener('click', ctx.goBack) + el.addEventListener('keyup', ctx.goBackKey) }, update (el, binding) { if (binding.oldValue !== binding.value) { @@ -28,6 +34,7 @@ export default { const ctx = el.__qgoback if (!ctx) { return } el.removeEventListener('click', ctx.goBack) + el.removeEventListener('keyup', ctx.goBackKey) delete el.__qgoback } } diff --git a/src/directives/ripple.js b/src/directives/ripple.js index 64eb2f961b8d..305f8efaf378 100644 --- a/src/directives/ripple.js +++ b/src/directives/ripple.js @@ -64,11 +64,17 @@ export default { if (ctx.enabled) { showRipple(evt, el, modifiers.stop) } + }, + keyup (evt) { + if (ctx.enabled && evt.keyCode === 13) { + showRipple(evt, el, modifiers.stop) + } } } el.__qripple = ctx el.addEventListener('click', ctx.click, false) + el.addEventListener('keyup', ctx.keyup, false) }, update (el, { value, oldValue }) { if (el.__qripple && value !== oldValue) { @@ -82,6 +88,7 @@ export default { } el.removeEventListener('click', ctx.click, false) + el.removeEventListener('keyup', ctx.keyup, false) delete el.__qripple } } diff --git a/src/mixins/input.js b/src/mixins/input.js index 35d3ed9fb7e5..21660eca5990 100644 --- a/src/mixins/input.js +++ b/src/mixins/input.js @@ -55,6 +55,9 @@ export default { }) }, __onKeydown (e) { + if (e.keyCode === 13) { + this.__emit() + } this.$emit('keydown', e) }, __onKeyup (e) {