Skip to content

Commit

Permalink
Action and popovermenu accessibility
Browse files Browse the repository at this point in the history
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
  • Loading branch information
skjnldsv committed Apr 9, 2019
1 parent c1b183f commit e381d5c
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 18 deletions.
76 changes: 59 additions & 17 deletions src/components/Action/Action.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,31 @@

<template>
<!-- if only one action, check if we need to bind to click or not -->
<action :href="isSingleAction && firstAction.href ? firstAction.href : '#'"
:class="[isSingleAction ? `${firstAction.icon} action-item--single` : 'action-item--multiple']"
v-bind="mainActionElement()" class="action-item"
v-on="isSingleAction && firstAction.action ? { click: firstAction.action } : {}">
<a v-if="isSingleAction" href="#" :class="firstAction.icon"
class="action-item--single" @click="firstAction.action ? firstAction.action : null" />
<!-- more than one action -->
<div v-else
:class="{'action-item--open': opened}"
class="action-item"
@keydown.space.exact.prevent="toggleMenu"
@keydown.up.exact.prevent="focusPreviousAction"
@keydown.down.exact.prevent="focusNextAction"
@keydown.shift.tab.prevent="focusPreviousAction"
@keydown.tab.exact.prevent="focusNextAction"
@keydown.page-up.exact.prevent="focusFirstAction"
@keydown.page-down.exact.prevent="focusLastAction"
@keydown.esc.exact.prevent="closeMenu">
<!-- If more than one action, create a popovermenu -->
<template v-if="!isSingleAction">
<div v-click-outside="closeMenu" tabindex="0" class="icon action-item__menutoggle"
@click.prevent="toggleMenu" />
<div :class="{ 'open': opened }" class="action-item__menu popovermenu">
<popover-menu :menu="actions" />
</div>
</template>
</action>
<a v-click-outside="closeMenu"
class="icon action-item__menutoggle"
href="#" aria-haspopup="true"
:aria-controls="randomId"
:aria-expanded="opened"
@click.prevent="toggleMenu" />
<div :class="{ 'open': opened }" class="action-item__menu popovermenu" tabindex="-1">
<popover-menu :id="randomId" :menu="actions" tabindex="-1" />
</div>
</div>
</template>

<script>
Expand Down Expand Up @@ -77,7 +89,9 @@ export default {
},
data() {
return {
opened: this.open
opened: this.open,
focusIndex: 0,
randomId: Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5)
}
},
computed: {
Expand All @@ -100,16 +114,34 @@ export default {
methods: {
toggleMenu() {
this.opened = !this.opened
// focus first on menu open
if (this.opened) {
this.focusFirstAction()
}
this.$emit('update:open', this.opened)
},
closeMenu() {
this.opened = false
this.$emit('update:open', this.opened)
},
mainActionElement() {
return {
is: this.isSingleAction ? 'a' : 'div'
}
focusAction() {
this.$el.querySelectorAll('.focusable')[this.focusIndex].focus()
},
focusPreviousAction() {
this.focusIndex = Math.max(this.focusIndex - 1, 0)
this.focusAction()
},
focusNextAction() {
this.focusIndex = Math.min(this.focusIndex + 1, this.$el.querySelectorAll('.focusable').length - 1)
this.focusAction()
},
focusFirstAction() {
this.focusIndex = 0
this.focusAction()
},
focusLastAction() {
this.focusIndex = this.$el.querySelectorAll('.focusable').length - 1
this.focusAction()
}
}
}
Expand All @@ -120,6 +152,15 @@ export default {
.action-item {
display: inline-block;
&:hover,
&:focus,
&__menutoggle:focus,
&__menutoggle:active {
&,
.action-item__menutoggle {
opacity: 1;
}
}
// icons
&--single,
Expand All @@ -133,6 +174,7 @@ export default {
// icon-more
&__menutoggle {
display: inline-block;
opacity: .7;
@include iconfont('more');
}
// properly position the menu
Expand Down
3 changes: 2 additions & 1 deletion src/components/PopoverMenu/PopoverMenuItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<a v-if="item.href" :href="(item.href) ? item.href : '#' "
:target="(item.target) ? item.target : '' "
:download="item.download"
class="focusable"
rel="noreferrer noopener" @click="action">
<span v-if="!iconIsUrl" :class="item.icon" />
<img v-else :src="item.icon">
Expand Down Expand Up @@ -69,7 +70,7 @@
</span>

<!-- If item.action is set instead, a button will be used -->
<button v-else-if="item.action" class="menuitem" :class="{active: item.active}"
<button v-else-if="item.action" class="menuitem focusable" :class="{active: item.active}"
@click.stop.prevent="item.action">
<span :class="item.icon" />
<p v-if="item.text && item.longtext">
Expand Down

0 comments on commit e381d5c

Please sign in to comment.