Skip to content

Commit

Permalink
Merge pull request #4835 from nextcloud-libraries/fix/nc-actions--fix…
Browse files Browse the repository at this point in the history
…-roles

fix(NcActions): fix role and aria attributes
  • Loading branch information
susnux committed Nov 16, 2023
2 parents ceb0c3c + 63bc999 commit a80f0a3
Show file tree
Hide file tree
Showing 13 changed files with 395 additions and 49 deletions.
18 changes: 14 additions & 4 deletions src/components/NcActionButton/NcActionButton.vue
Expand Up @@ -173,19 +173,19 @@ export default {
</docs>

<template>
<li class="action" :class="{ 'action--disabled': disabled }">
<li class="action" :class="{ 'action--disabled': disabled }" :role="isInSemanticMenu && 'presentation'">
<button class="action-button"
:class="{ focusable: isFocusable }"
:aria-label="ariaLabel"
:title="title"
role="menuitem"
:role="isInSemanticMenu && 'menuitem'"
type="button"
@click="onClick">
<!-- @slot Manually provide icon -->
<slot name="icon">
<span :class="[isIconUrl ? 'action-button__icon--url' : icon]"
:style="{ backgroundImage: isIconUrl ? `url(${icon})` : null }"
:aria-hidden="ariaHidden"
aria-hidden="true"
class="action-button__icon" />
</slot>

Expand Down Expand Up @@ -235,6 +235,13 @@ export default {
},
mixins: [ActionTextMixin],
inject: {
isInSemanticMenu: {
from: 'NcActions:isSemanticMenu',
default: false,
},
},
props: {
/**
* disabled state of the action button
Expand All @@ -245,7 +252,9 @@ export default {
},
/**
* aria-hidden attribute for the icon slot
* @deprecated To be removed in @nextcloud/vue 9. Migration guide: remove ariaHidden prop from NcAction* components.
* @todo Add a check in @nextcloud/vue 9 that this prop is not provided,
* otherwise root element will inherit incorrect aria-hidden.
*/
ariaHidden: {
type: Boolean,
Expand All @@ -261,6 +270,7 @@ export default {
default: false,
},
},
computed: {
/**
* determines if the action is focusable
Expand Down
21 changes: 18 additions & 3 deletions src/components/NcActionButtonGroup/NcActionButtonGroup.vue
Expand Up @@ -81,24 +81,33 @@ export default {
</docs>

<template>
<li class="nc-button-group-base">
<div v-if="name">
<li class="nc-button-group-base" :role="isInSemanticMenu && 'presentation'">
<div v-if="name" :id="labelId">
{{ name }}
</div>
<ul class="nc-button-group-content">
<ul class="nc-button-group-content" role="group" :aria-labelledby="name ? labelId : undefined">
<slot />
</ul>
</li>
</template>

<script>
import { defineComponent } from 'vue'
import GenRandomId from '../../utils/GenRandomId.js'
/**
* A wrapper for allowing inlining NcAction components within the action menu
*/
export default defineComponent({
name: 'NcActionButtonGroup',
inject: {
isInSemanticMenu: {
from: 'NcActions:isSemanticMenu',
default: false,
},
},
props: {
/**
* Optional text shown below the button group
Expand All @@ -109,6 +118,12 @@ export default defineComponent({
type: String,
},
},
computed: {
labelId() {
return `nc-action-button-group-${GenRandomId()}`
},
},
})
</script>

Expand Down
10 changes: 9 additions & 1 deletion src/components/NcActionCaption/NcActionCaption.vue
Expand Up @@ -30,14 +30,22 @@ This component is made to be used inside of the [NcActions](#NcActions) componen
</docs>

<template>
<li class="app-navigation-caption">
<li class="app-navigation-caption" :role="isInSemanticMenu && 'presentation'">
{{ name }}
</li>
</template>

<script>
export default {
name: 'NcActionCaption',
inject: {
isInSemanticMenu: {
from: 'NcActions:isSemanticMenu',
default: false,
},
},
props: {
/**
* The caption's text
Expand Down
23 changes: 21 additions & 2 deletions src/components/NcActionCheckbox/NcActionCheckbox.vue
Expand Up @@ -35,8 +35,8 @@ This component is made to be used inside of the [NcActions](#NcActions) componen
</docs>

<template>
<li class="action" :class="{ 'action--disabled': disabled }">
<span class="action-checkbox">
<li class="action" :class="{ 'action--disabled': disabled }" :role="isInSemanticMenu && 'presentation'">
<span class="action-checkbox" :role="isInSemanticMenu && 'menuitemcheckbox'" :aria-checked="ariaChecked">
<input :id="id"
ref="checkbox"
:disabled="disabled"
Expand Down Expand Up @@ -64,6 +64,13 @@ export default {
mixins: [ActionGlobalMixin],
inject: {
isInSemanticMenu: {
from: 'NcActions:isSemanticMenu',
default: false,
},
},
props: {
/**
* id attribute of the checkbox element
Expand Down Expand Up @@ -115,6 +122,18 @@ export default {
isFocusable() {
return !this.disabled
},
/**
* aria-checked attribute for role="menuitemcheckbox"
*
* @return {'true'|'false'|undefined} aria-checked value if needed
*/
ariaChecked() {
if (this.isInSemanticMenu) {
return this.checked ? 'true' : 'false'
}
return undefined
},
},
methods: {
Expand Down
6 changes: 4 additions & 2 deletions src/components/NcActionInput/NcActionInput.vue
Expand Up @@ -147,7 +147,7 @@ For the `NcSelect` component, all events will be passed through. Please see the
<slot name="icon">
<span :class="[isIconUrl ? 'action-input__icon--url' : icon]"
:style="{ backgroundImage: isIconUrl ? `url(${icon})` : null }"
:aria-hidden="ariaHidden"
aria-hidden="true"
class="action-input__icon" />
</slot>
</span>
Expand Down Expand Up @@ -370,7 +370,9 @@ export default {
default: '',
},
/**
* aria-hidden attribute for the icon slot
* @deprecated To be removed in @nextcloud/vue 9. Migration guide: remove ariaHidden prop from NcAction* components.
* @todo Add a check in @nextcloud/vue 9 that this prop is not provided,
* otherwise root element will inherit incorrect aria-hidden.
*/
ariaHidden: {
type: Boolean,
Expand Down
17 changes: 13 additions & 4 deletions src/components/NcActionLink/NcActionLink.vue
Expand Up @@ -78,22 +78,22 @@ export default {
</docs>

<template>
<li class="action">
<li class="action" :role="isInSemanticMenu && 'presentation'">
<a :download="download"
:href="href"
:aria-label="ariaLabel"
:target="target"
:title="title"
class="action-link focusable"
rel="nofollow noreferrer noopener"
role="menuitem"
:role="isInSemanticMenu && 'menuitem'"
@click="onClick">

<!-- @slot Manually provide icon -->
<slot name="icon">
<span :class="[isIconUrl ? 'action-link__icon--url' : icon]"
:style="{ backgroundImage: isIconUrl ? `url(${icon})` : null }"
:aria-hidden="ariaHidden"
aria-hidden="true"
class="action-link__icon" />
</slot>

Expand Down Expand Up @@ -133,6 +133,13 @@ export default {
mixins: [ActionTextMixin],
inject: {
isInSemanticMenu: {
from: 'NcActions:isSemanticMenu',
default: false,
},
},
props: {
/**
* destionation to link to
Expand Down Expand Up @@ -175,7 +182,9 @@ export default {
default: null,
},
/**
* aria-hidden attribute for the icon slot
* @deprecated To be removed in @nextcloud/vue 9. Migration guide: remove ariaHidden prop from NcAction* components.
* @todo Add a check in @nextcloud/vue 9 that this prop is not provided,
* otherwise root element will inherit incorrect aria-hidden.
*/
ariaHidden: {
type: Boolean,
Expand Down
23 changes: 21 additions & 2 deletions src/components/NcActionRadio/NcActionRadio.vue
Expand Up @@ -37,8 +37,8 @@ So that only one of each name set can be selected at the same time.
</docs>

<template>
<li class="action" :class="{ 'action--disabled': disabled }">
<span class="action-radio">
<li class="action" :class="{ 'action--disabled': disabled }" :role="isInSemanticMenu && 'presentation'">
<span class="action-radio" role="menuitemradio" :aria-checked="ariaChecked">
<input :id="id"
ref="radio"
:disabled="disabled"
Expand Down Expand Up @@ -67,6 +67,13 @@ export default {
mixins: [ActionGlobalMixin],
inject: {
isInSemanticMenu: {
from: 'NcActions:isSemanticMenu',
default: false,
},
},
props: {
/**
* id attribute of the radio element
Expand Down Expand Up @@ -126,6 +133,18 @@ export default {
isFocusable() {
return !this.disabled
},
/**
* aria-checked attribute for role="menuitemcheckbox"
*
* @return {'true'|'false'|undefined} aria-checked value if needed
*/
ariaChecked() {
if (this.isInSemanticMenu) {
return this.checked ? 'true' : 'false'
}
return undefined
},
},
methods: {
Expand Down
17 changes: 13 additions & 4 deletions src/components/NcActionRouter/NcActionRouter.vue
Expand Up @@ -22,19 +22,21 @@
-->

<template>
<li class="action">
<router-link :to="to"
<li class="action" :role="isInSemanticMenu && 'presentation'">
<RouterLink :to="to"
:aria-label="ariaLabel"
:exact="exact"
:title="title"
class="action-router focusable"
rel="nofollow noreferrer noopener"
:role="isInSemanticMenu && 'menuitem'"
@click.native="onClick">
<!-- @slot Manually provide icon -->
<slot name="icon">
<span :class="[isIconUrl ? 'action-router__icon--url' : icon]"
:style="{ backgroundImage: isIconUrl ? `url(${icon})` : null }"
class="action-router__icon" />
class="action-router__icon"
aria-hidden="true" />
</slot>

<!-- long text with name -->
Expand All @@ -61,7 +63,7 @@

<!-- fake slot to gather inner text -->
<slot v-if="false" />
</router-link>
</RouterLink>
</li>
</template>

Expand All @@ -73,6 +75,13 @@ export default {
mixins: [ActionTextMixin],
inject: {
isInSemanticMenu: {
from: 'NcActions:isSemanticMenu',
default: false,
},
},
props: {
/**
* router-link to prop [https://router.vuejs.org/api/#to](https://router.vuejs.org/api/#to)
Expand Down
2 changes: 1 addition & 1 deletion src/components/NcActionSeparator/NcActionSeparator.vue
Expand Up @@ -24,7 +24,7 @@
-->

<template>
<li class="action action-separator action--disabled" />
<li class="action action-separator action--disabled" role="separator" />
</template>

<script>
Expand Down
10 changes: 8 additions & 2 deletions src/components/NcActionText/NcActionText.vue
Expand Up @@ -22,14 +22,14 @@
-->

<template>
<li class="action">
<li class="action" :role="isInSemanticMenu && 'presentation'">
<span class="action-text"
@click="onClick">
<!-- @slot Manually provide icon -->
<slot name="icon">
<span v-if="icon !== ''"
:class="[isIconUrl ? 'action-text__icon--url' : icon]"
:aria-hidden="ariaHidden"
aria-hidden="true"
:style="{ backgroundImage: isIconUrl ? `url(${icon})` : null }"
class="action-text__icon" />
</slot>
Expand Down Expand Up @@ -70,6 +70,12 @@ export default {
mixins: [ActionTextMixin],
inject: {
isInSemanticMenu: {
from: 'NcActions:isSemanticMenu',
default: false,
},
},
}
</script>

Expand Down

0 comments on commit a80f0a3

Please sign in to comment.