Skip to content

Commit

Permalink
Merge pull request #36 from Qvant-lab/add-more-accessibility
Browse files Browse the repository at this point in the history
[QCascader, QButton, QBreadcrumbs] Add more accessibility
  • Loading branch information
cheesytim committed Jan 22, 2021
2 parents 970c1e2 + 26a3d3c commit 2221b8f
Show file tree
Hide file tree
Showing 12 changed files with 227 additions and 23 deletions.
4 changes: 4 additions & 0 deletions src/qComponents/QBreadcrumbs/src/q-breadcrumbs.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
white-space: nowrap;
text-overflow: ellipsis;

&:focus {
text-decoration: underline;
}

&_exact-active:not(:first-child),
&_last:not(:first-child) {
font-weight: var(--font-weight-bold);
Expand Down
21 changes: 21 additions & 0 deletions src/qComponents/QButton/src/q-button.scss
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@
margin-left: 16px;
}

&:focus {
outline: none;
}

&:hover {
background-color: var(--color-primary);
background-image: none;
box-shadow: -1px -1px 4px rgba(var(--color-rgb-white), 0.25),
1px 1px 4px rgba(var(--color-rgb-blue), 0.4),
Expand Down Expand Up @@ -64,6 +69,13 @@
}

&_theme {
&_primary {
&:focus {
background-color: var(--color-primary-darker);
background-image: none;
}
}

&_secondary {
color: var(--color-primary-blue);
background-color: var(--color-tertiary-gray);
Expand All @@ -80,6 +92,11 @@
outline: none;
box-shadow: var(--box-shadow-pressed);
}

&:focus {
color: var(--color-tertiary-white);
background-color: var(--color-primary-darker);
}
}

&_link {
Expand All @@ -92,6 +109,10 @@
background-image: none;
box-shadow: none;

&:focus {
text-decoration: underline;
}

&:hover {
color: var(--color-primary-black);
background-color: transparent;
Expand Down
7 changes: 7 additions & 0 deletions src/qComponents/QCascader/QCascader.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import Component from './src/QCascader';

const module = require('../helpers');

module.randId = jest.fn();

describe('QCascader', () => {
let instance;
let options;
Expand Down Expand Up @@ -36,6 +40,9 @@ describe('QCascader', () => {
});

it('should match snapshot', () => {
const spy = prefix => `${prefix}000`;
module.randId.mockImplementation(spy);
instance = mount(Component, options);
expect(instance.element).toMatchSnapshot();
});

Expand Down
21 changes: 16 additions & 5 deletions src/qComponents/QCascader/__snapshots__/QCascader.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ Object {
"areTagsHovered": false,
"checkedNodes": Array [],
"checkedValues": Array [],
"focus": false,
"id": "q-cascader-000",
"inputInitialHeight": 0,
"inputValue": null,
"popper": null,
Expand All @@ -23,11 +25,14 @@ exports[`QCascader should match snapshot 1`] = `
<!---->
<input
aria-controls="q-cascader-000"
aria-haspopup="true"
aria-label=""
autocomplete="off"
class="q-input__inner"
placeholder="placeholder"
readonly="readonly"
role="button"
tabindex=""
type="text"
/>
Expand Down Expand Up @@ -55,13 +60,15 @@ exports[`QCascader should match snapshot 1`] = `
class="q-cascader-panel"
>
<div
aria-labelledby="q-cascader-000"
class="q-cascader-menu"
role="menu"
>
<div
class="q-cascader-menu__wrap"
>
<div
class="q-scrollbar"
class="q-scrollbar q-scrollbar_has-horizontal-bar q-scrollbar_has-vertical-bar"
>
<div
class="q-scrollbar__wrap q-cascader-menu__scrollbar q-scrollbar__wrap_hidden-default"
Expand All @@ -71,6 +78,9 @@ exports[`QCascader should match snapshot 1`] = `
>
<div
class="q-cascader-node"
id="q-cascader-000-node-0-0"
role="menuitem"
tabindex="-1"
>
<!---->
Expand All @@ -86,6 +96,9 @@ exports[`QCascader should match snapshot 1`] = `
</div>
<div
class="q-cascader-node"
id="q-cascader-000-node-0-1"
role="menuitem"
tabindex="-1"
>
<!---->
Expand All @@ -102,21 +115,19 @@ exports[`QCascader should match snapshot 1`] = `
<div
class="q-scrollbar__bar q-scrollbar__bar_horizontal"
style="display: none;"
>
<div
class="q-scrollbar__thumb"
style="transform: translateX(0%); webkit-transform: translateX(0%);"
style="width: 0px; transform: translateX(0%); webkit-transform: translateX(0%);"
/>
</div>
<div
class="q-scrollbar__bar q-scrollbar__bar_vertical"
style="display: none;"
>
<div
class="q-scrollbar__thumb"
style="transform: translateY(0%); webkit-transform: translateY(0%);"
style="height: 0px; transform: translateY(0%); webkit-transform: translateY(0%);"
/>
</div>
</div>
Expand Down
71 changes: 59 additions & 12 deletions src/qComponents/QCascader/src/QCascader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@
:placeholder="calcPlaceholder"
:disabled="isDisabled"
:validate-event="false"
aria-haspopup="true"
role="button"
:aria-controls="id"
:aria-expanded="popper"
:class="{
'q-input_focus': Boolean(popper),
'q-input_hover': areTagsHovered
}"
@focus="handleFocus"
@blur="handleBlur"
@mouseenter.native="handleMouseEnter"
@mouseleave.native="showClose = false"
@focus="handleInputFocus"
@click="togglePopper"
>
<template slot="suffix">
Expand Down Expand Up @@ -103,7 +106,7 @@
<script>
import { createPopper } from '@popperjs/core';
import Emitter from '../../mixins/emitter';
import { addResizeListener, removeResizeListener } from '../../helpers';
import { addResizeListener, removeResizeListener, randId } from '../../helpers';
import QCascaderPanel from './QCascaderPanel';
Expand Down Expand Up @@ -252,7 +255,9 @@ export default {
inputInitialHeight: 0,
popper: null,
showClose: false,
areTagsHovered: false
areTagsHovered: false,
focus: false,
id: randId('q-cascader-')
};
},
Expand Down Expand Up @@ -329,13 +334,54 @@ export default {
this.inputInitialHeight = input?.$el?.offsetHeight ?? DEFAULT_INPUT_HEIGHT;
addResizeListener(this.$el, this.updateStyle);
document.addEventListener('keyup', this.handleKeyUp, true);
},
beforeDestroy() {
removeResizeListener(this.$el, this.updateStyle);
document.removeEventListener('keyup', this.handleKeyUp, true);
},
methods: {
handleKeyUp(e) {
if (!this.focus) return;
if (e.target.classList.contains('q-input__inner') && e.key === 'Enter') {
this.togglePopper();
}
switch (e.key) {
case 'Escape': {
this.$refs.input.blur();
this.hidePopper();
break;
}
case 'Backspace': {
this.deleteTag();
break;
}
case 'Tab': {
if (!this.$refs.reference.contains(document.activeElement)) {
this.hidePopper();
this.focus = false;
}
break;
}
case 'ArrowRight':
case 'ArrowUp':
case 'ArrowLeft':
case 'ArrowDown': {
this.$refs.panel.navigateFocus(e);
break;
}
default:
break;
}
},
handleTagsHover() {
this.areTagsHovered = true;
this.showClose = true;
Expand All @@ -353,9 +399,14 @@ export default {
}
},
deleteTag({ value }) {
deleteTag({ value } = {}) {
if (!this.checkedValues) return;
const result = new Set(this.checkedValues);
result.delete(value);
if (value) {
result.delete(value);
} else {
result.delete(this.checkedValues[this.checkedValues.length - 1]);
}
const payload = Array.from(result);
this.emit(payload.length ? payload : null);
},
Expand Down Expand Up @@ -417,14 +468,10 @@ export default {
}
},
handleFocus(e) {
handleInputFocus(e) {
this.$emit('focus', e);
this.focus = true;
},
handleBlur(e) {
this.$emit('blur', e);
},
updateStyle() {
const { $el, inputInitialHeight } = this;
if (!$el) return;
Expand Down
23 changes: 21 additions & 2 deletions src/qComponents/QCascader/src/QCascaderMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,19 @@
<div
v-for="(node, key) in nodes"
v-else
:id="`${cascader.id}-node-${index}-${key}`"
:key="key"
:class="getNodeClass(node)"
@click="e => handleExpand(e, node)"
role="menuitem"
tabindex="-1"
@click="e => expandMenuItem(e, node)"
@keyup.enter="e => handleEnterKeyUp(e, node, index, key)"
@keyup.right="e => expandMenuItem(e, node)"
>
<q-checkbox
v-if="cascader.multiple"
:ref="`QCheckbox${index}${key}`"
input-tab-index="-1"
:value="getChecked(node)"
:indeterminate="getIndeterminate(node)"
@change="isChecked => handleValueChange(node, isChecked)"
Expand Down Expand Up @@ -110,6 +117,17 @@ export default {
},
methods: {
handleEnterKeyUp(e, node, index, key) {
if (this.cascader.multiple) {
const QCheckboxInstance = this.$refs[`QCheckbox${index}${key}`]?.[0];
if (QCheckboxInstance) {
QCheckboxInstance.nativeClick();
}
return;
}
this.expandMenuItem(e, node);
},
getIndeterminate(node) {
if (
!this.cascader.checkedValues ||
Expand Down Expand Up @@ -220,7 +238,8 @@ export default {
};
},
handleExpand(e, value) {
expandMenuItem(e, value) {
if (e.key === 'ArrowRight' && !value.children) return;
if (!value.children && !this.cascader.multiple) {
this.cascader.emit(value.value);
}
Expand Down
Loading

0 comments on commit 2221b8f

Please sign in to comment.