Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(NcActions): fix role and aria attributes #4835

Merged
merged 6 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 14 additions & 4 deletions src/components/NcActionButton/NcActionButton.vue
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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