Skip to content

Commit

Permalink
Merge pull request #5330 from nextcloud/backport/5218/stable28
Browse files Browse the repository at this point in the history
[stable28] fix(menubar): menubar and table menus a11y
  • Loading branch information
juliushaertl committed Feb 1, 2024
2 parents 3a5228f + 633c543 commit e4c8c73
Show file tree
Hide file tree
Showing 13 changed files with 224 additions and 186 deletions.
25 changes: 14 additions & 11 deletions src/components/Editor/SessionList.vue
Expand Up @@ -22,17 +22,20 @@

<template>
<NcPopover class="session-list" placement="bottom">
<div slot="trigger">
<button :title="label"
:aria-label="label"
class="avatar-list">
<div class="avatardiv icon-group" />
<AvatarWrapper v-for="session in sessionsVisible"
:key="session.id"
:session="session"
:size="40" />
</button>
</div>
<template #trigger="{ attrs }">
<div>
<button :title="label"
:aria-label="label"
class="avatar-list"
v-bind="attrs">
<div class="avatardiv icon-group" />
<AvatarWrapper v-for="session in sessionsVisible"
:key="session.id"
:session="session"
:size="40" />
</button>
</div>
</template>
<template #default>
<div class="session-menu">
<slot name="lastSaved" />
Expand Down
56 changes: 0 additions & 56 deletions src/components/InlineActionsContainer.vue

This file was deleted.

7 changes: 2 additions & 5 deletions src/components/Menu/ActionAttachmentUpload.vue
Expand Up @@ -25,14 +25,11 @@
:name="actionEntry.label"
:title="actionEntry.label"
:aria-label="actionEntry.label"
:container="menuIDSelector"
role="menu"
aria-haspopup>
:container="menuIDSelector">
<template #icon>
<component :is="icon"
:name="actionEntry.label"
:aria-label="actionEntry.label"
aria-haspopup />
:aria-label="actionEntry.label" />
</template>
<NcActionButton v-if="$editorUpload"
close-after-click
Expand Down
15 changes: 10 additions & 5 deletions src/components/Menu/ActionFormattingHelp.vue
Expand Up @@ -20,25 +20,30 @@
-
-->
<template>
<NcActionButton close-after-click
<NextcloudVueNcActionButton close-after-click
data-text-action-entry="formatting-help"
v-on="$listeners">
<template #icon>
<Help />
</template>
{{ t('text', 'Formatting help') }}
</NcActionButton>
</NextcloudVueNcActionButton>
</template>

<script>
import { defineComponent } from 'vue'
import { NcActionButton } from '@nextcloud/vue'
import { NcActionButton as NextcloudVueNcActionButton } from '@nextcloud/vue'
import { Help } from '../icons.js'
export default defineComponent({
name: 'ActionFormattingHelp',
// This component is used as a direct child of NcActions.
// Even if it actually renders NcActionButton, NcActions cannot see it due to rendering limitations in Vue.
// Though it works in general, NcActions doesn't handle it correctly. See NcActions docs for details.
// Hotfix - rename the component to NcActionButton because it represents and renders it.
// eslint-disable-next-line vue/match-component-file-name
name: 'NcActionButton',
components: {
NcActionButton,
NextcloudVueNcActionButton,
Help,
},
})
Expand Down
4 changes: 1 addition & 3 deletions src/components/Menu/ActionInsertLink.vue
Expand Up @@ -19,7 +19,6 @@
-->
<template>
<NcActions class="entry-action entry-action__insert-link"
aria-haspopup
:title="actionEntry.label"
:aria-label="actionEntry.label"
:class="activeClass"
Expand All @@ -31,8 +30,7 @@
<template #icon>
<component :is="icon"
:name="actionEntry.label"
:aria-label="actionEntry.label"
aria-haspopup />
:aria-label="actionEntry.label" />
</template>
<NcActionButton v-if="state.active"
:data-text-action-entry="`${actionEntry.key}-remove`"
Expand Down
43 changes: 27 additions & 16 deletions src/components/Menu/ActionList.vue
Expand Up @@ -2,6 +2,7 @@
- @copyright Copyright (c) 2022 Vinicius Reis <vinicius@nextcloud.com>
-
- @author Vinicius Reis <vinicius@nextcloud.com>
- @author Grigorii K. Shartsev <me@shgk.me>
-
- @license GNU AGPL version 3 or any later version
-
Expand All @@ -23,37 +24,35 @@
<template>
<NcActions :title="tooltip"
class="entry-list-action entry-action"
role="menu"
v-bind="state"
:container="menuIDSelector"
:aria-label="actionEntry.label"
:aria-pressed="state.active"
:aria-label="labelWithSelected"
:type="state.active ? 'primary': 'tertiary'"
:aria-activedescendant="currentChild ? `${$menuID}-child-${currentChild.key}` : null"
:force-menu="true"
:name="actionEntry.label"
:data-text-action-entry="actionEntry.key"
:data-text-action-active="activeKey"
@update:open="onOpenChange">
<template #icon>
<component :is="icon" :key="iconKey" />
</template>
<ActionSingle v-for="child in children"
:id="`${$menuID}-child-${child.key}`"
:key="`child-${child.key}`"
:active="currentChild?.key === child.key"
is-item
:action-entry="child"
v-on="$listeners"
@trigged="onTrigger" />
<template v-for="child in children">
<NcActionSeparator v-if="child.isSeparator" :key="`child-${child.key}`" />
<ActionListItem v-else
:key="`child-${child.key}`"
:active="currentChild?.key === child.key"
is-item
:action-entry="child"
v-on="$listeners"
@trigged="onTrigger" />
</template>
<slot v-bind="{ visible }" name="lastAction" />
</NcActions>
</template>
<script>
import { NcActions } from '@nextcloud/vue'
import { NcActions, NcActionSeparator } from '@nextcloud/vue'
import { BaseActionEntry } from './BaseActionEntry.js'
import ActionSingle from './ActionSingle.vue'
import ActionListItem from './ActionListItem.vue'
import { getIsActive } from './utils.js'
import { useOutlineStateMixin } from '../Editor/Wrapper.provider.js'
import useStore from '../../mixins/store.js'
Expand All @@ -63,7 +62,8 @@ export default {
name: 'ActionList',
components: {
NcActions,
ActionSingle,
NcActionSeparator,
ActionListItem,
},
extends: BaseActionEntry,
mixins: [useStore, useOutlineStateMixin, useMenuIDMixin],
Expand Down Expand Up @@ -110,6 +110,17 @@ export default {
: visible
})
},
labelWithSelected() {
if (this.currentChild) {
// TRANSLATORS: examples - Headings, "Heading 1" is selected - Callouts, "Info" is selected
return t('text', '{menuItemName}, "{selectedSubMenuItemName}" is selected', {
menuItemName: this.actionEntry.label,
selectedSubMenuItemName: this.currentChild.label,
})
}
return this.actionEntry.label
},
},
methods: {
onOpenChange(val) {
Expand Down
82 changes: 82 additions & 0 deletions src/components/Menu/ActionListItem.vue
@@ -0,0 +1,82 @@
<!--
- @copyright Copyright (c) 2022 Vinicius Reis <vinicius@nextcloud.com>
-
- @author Vinicius Reis <vinicius@nextcloud.com>
- @author Grigorii K. Shartsev <me@shgk.me>
-
- @license GNU AGPL version 3 or any later version
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-->

<template>
<NextcloudVueNcActionButton class="entry-single-action entry-action entry-action-item"
:class="state.class"
:disabled="state.disabled"
:aria-keyshortcuts="keyshortcuts || undefined"
:data-text-action-entry="actionEntry.key"
:type="state.type"
:model-value="state.type !== 'button' ? state.active : undefined"
close-after-click
v-on="$listeners"
@click="runAction">
<template #icon>
<component :is="icon" />
</template>
{{ label }}
</NextcloudVueNcActionButton>
</template>

<script>
import { NcActionButton as NextcloudVueNcActionButton } from '@nextcloud/vue'
import { BaseActionEntry } from './BaseActionEntry.js'
export default {
// This component is used as a direct child of NcActions.
// Even if it actually renders NcActionButton, NcActions cannot see it due to rendering limitations in Vue.
// Though it works in general, NcActions doesn't handle it correctly. See NcActions docs for details.
// Hotfix - rename the component to NcActionButton because it represents and renders it.
// eslint-disable-next-line vue/match-component-file-name
name: 'NcActionButton',
components: {
NextcloudVueNcActionButton,
},
extends: BaseActionEntry,
mounted() {
this.$editor.on('transaction', () => this.updateState())
},
methods: {
runAction() {
const { actionEntry } = this
if (actionEntry.click) {
actionEntry.click(this)
} else {
// Some actions run themselves.
// others still need to have .run() called upon them.
actionEntry.action(this.$editor.chain().focus())?.run()
}
this.$nextTick(() => {
this.$emit('trigged', { ...actionEntry })
})
},
},
}
</script>

0 comments on commit e4c8c73

Please sign in to comment.