Skip to content

Commit

Permalink
Merge pull request #5000 from owncloud/file-sidebar-a11y
Browse files Browse the repository at this point in the history
Improve accessibility for the files sidebar
  • Loading branch information
kulmann authored Apr 26, 2021
2 parents 3ab1852 + e9e9334 commit 93e37df
Show file tree
Hide file tree
Showing 19 changed files with 180 additions and 58 deletions.
13 changes: 13 additions & 0 deletions changelog/unreleased/enhancement-files-sidebar-accessibility
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Enhancement: Improve accessibility for the files sidebar

We've did several improvements to enhance the accessibility on the files sidebar:
- Transformed the file name to a h2 element
- Transformed the "Open folder"-action to a link instead of a button
- Transformed the favorite-star to a button-element
- Adjusted aria-label of the favorite-star to describe what it does instead of its current state
- Added a more descriptive close button label
- Clicking outside of the sidebar now closes it
- Removed the aria-label on the action buttons as they already include proper labels
- Added a hint for screen readers if an action opens a new window/tab

https://github.com/owncloud/web/pull/5000
2 changes: 1 addition & 1 deletion packages/web-app-files/src/components/AppBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
@error="onFileError"
@progress="onFileProgress"
/>
<div>
<div class="files-topbar">
<oc-breadcrumb
v-if="showBreadcrumb"
id="files-breadcrumb"
Expand Down
39 changes: 30 additions & 9 deletions packages/web-app-files/src/components/Sidebar.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<template>
<oc-app-side-bar
:key="highlightedFile.id"
v-click-outside="onClickOutside"
class="files-sidebar oc-p-s oc-border-l"
:disable-action="false"
:close-button-label="$gettext('Close file sidebar')"
@close="close()"
>
<template v-if="highlightedFile" slot="title">
Expand All @@ -11,25 +13,28 @@
</div>
<div class="uk-inline">
<div class="uk-flex uk-flex-middle">
<span
<h2
id="files-sidebar-item-name"
class="oc-mr-s oc-text-bold"
class="oc-text-initial oc-mr-s oc-text-bold uk-margin-remove"
tabindex="-1"
v-text="highlightedFile.name"
/>
</div>
<div class="uk-flex uk-flex-middle">
<oc-icon
<oc-button
v-if="!publicPage() && isFavoritesEnabled"
id="files-sidebar-star-icon"
:class="['uk-inline', 'oc-mr-xs', favoriteIconClass]"
name="star"
:accessible-label="
:aria-label="
highlightedFile.starred
? $gettext('File is marked as favorite')
: $gettext('File is not marked as favorite')
? $gettext('Click to remove this file from your favorites')
: $gettext('Click to mark this file as favorite')
"
appearance="raw"
class="oc-mr-xs"
@click.native.stop="toggleFileFavorite(highlightedFile)"
/>
>
<oc-icon :class="favoriteIconClass" name="star" />
</oc-button>
<template v-if="highlightedFile.size > -1">
{{ getResourceSize(highlightedFile.size) }},
</template>
Expand Down Expand Up @@ -202,6 +207,22 @@ export default {
expandActionsAccordion() {
this.SET_APP_SIDEBAR_EXPANDED_ACCORDION('files-actions')
},
onClickOutside(event) {
/*
* We need to go for this opt-out solution because under circumstances a modal will be rendered,
* for example if we click rename, clicking in this modal would otherwise falsy close the sidebar.
*/
if (
document.querySelector('.files-topbar').contains(event.target) ||
document.querySelector('.oc-topbar').contains(event.target) ||
document.querySelector('.oc-app-navigation').contains(event.target) ||
event.target.id === 'files-view'
) {
this.close()
}
}
}
}
Expand Down
54 changes: 46 additions & 8 deletions packages/web-app-files/src/components/Sidebar/ActionsAccordion.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
<template>
<ul id="oc-files-actions-sidebar" class="uk-list oc-mt-s">
<li v-for="action in actions" :key="action.ariaLabel(highlightedFile)" class="oc-py-xs">
<oc-button
:aria-Label="action.ariaLabel(highlightedFile)"
appearance="raw"
class="oc-text-bold"
<ul id="oc-files-actions-sidebar" class="uk-list oc-mt-s oc-files-actions-sidebar-actions">
<li v-for="(action, index) in actions" :key="`action-${index}`" class="oc-py-xs">
<component
:is="action.componentType"
v-bind="getComponentProps(action, highlightedFile)"
:class="['oc-text-bold', action.class]"
@click.stop="action.handler(highlightedFile, action.handlerData)"
>
<oc-icon :name="action.icon" size="medium" />
{{ action.ariaLabel(highlightedFile) }}
</oc-button>
<span class="oc-files-actions-sidebar-action-label">{{
action.label(highlightedFile)
}}</span>
<span
v-if="action.opensInNewWindow"
class="oc-invisible-sr"
v-text="$gettext('(Opens in new window)')"
/>
</component>
</li>
</ul>
</template>
Expand Down Expand Up @@ -38,6 +45,37 @@ export default {
})
)
}
},
methods: {
getComponentProps(action, highlightedFile) {
if (action.componentType === 'router-link' && action.route) {
return {
to: {
name: action.route,
params: {
item: highlightedFile.path
}
}
}
}
return {
appearance: 'raw'
}
}
}
}
</script>

<style lang="scss">
.oc-files-actions-sidebar-actions {
> li a,
> li a:hover {
text-decoration: none;
color: var(--oc-color-swatch-passive-default);
display: inline-flex;
gap: 10px;
vertical-align: top;
}
}
</style>
6 changes: 4 additions & 2 deletions packages/web-app-files/src/mixins/actions/copy.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default {
{
icon: 'file_copy',
handler: this.$_copy_trigger,
ariaLabel: () => this.$gettext('Copy'),
label: () => this.$gettext('Copy'),
isEnabled: () => {
if (
!checkRoute(
Expand All @@ -27,7 +27,9 @@ export default {
}

return true
}
},
componentType: 'oc-button',
class: 'oc-files-actions-sidebar-copy-trigger'
}
]
}
Expand Down
12 changes: 8 additions & 4 deletions packages/web-app-files/src/mixins/actions/delete.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default {
return [
{
icon: 'delete',
ariaLabel: () => {
label: () => {
return this.$gettext('Delete')
},
handler: this.$_delete_trigger,
Expand All @@ -18,13 +18,17 @@ export default {
}

return resource.canBeDeleted()
}
},
componentType: 'oc-button',
class: 'oc-files-actions-sidebar-delete-trigger'
},
{
icon: 'delete',
ariaLabel: () => this.$gettext('Delete'),
label: () => this.$gettext('Delete'),
handler: this.$_delete_trigger,
isEnabled: () => checkRoute(['files-trashbin'], this.$route.name)
isEnabled: () => checkRoute(['files-trashbin'], this.$route.name),
componentType: 'oc-button',
class: 'oc-files-actions-sidebar-delete-trigger'
}
]
}
Expand Down
6 changes: 4 additions & 2 deletions packages/web-app-files/src/mixins/actions/download.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default {
{
icon: 'file_download',
handler: this.$_download_trigger,
ariaLabel: () => {
label: () => {
return this.$gettext('Download')
},
isEnabled: ({ resource }) => {
Expand All @@ -17,7 +17,9 @@ export default {

return resource.canDownload()
},
canBeDefault: true
canBeDefault: true,
componentType: 'oc-button',
class: 'oc-files-actions-sidebar-download-trigger'
}
]
}
Expand Down
6 changes: 4 additions & 2 deletions packages/web-app-files/src/mixins/actions/favorite.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default {
{
icon: 'star',
handler: this.$_favorite_trigger,
ariaLabel: item => {
label: item => {
if (item.starred) {
return this.$gettext('Unmark as favorite')
}
Expand All @@ -27,7 +27,9 @@ export default {
this.capabilities.files.favorites &&
isRouteAllowed
)
}
},
componentType: 'oc-button',
class: 'oc-files-actions-sidebar-favorite-trigger'
}
]
}
Expand Down
7 changes: 5 additions & 2 deletions packages/web-app-files/src/mixins/actions/fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default {
{
icon: 'remove_red_eye',
handler: file => this.$_fetch_trigger(file, 'application/pdf', this.isPublicFilesRoute),
ariaLabel: () => {
label: () => {
return this.$gettext('Open in browser')
},
isEnabled: ({ resource }) => {
Expand All @@ -20,7 +20,10 @@ export default {

return resource.extension === 'pdf'
},
canBeDefault: true
canBeDefault: true,
componentType: 'oc-button',
class: 'oc-files-actions-sidebar-fetch-trigger',
opensInNewWindow: true
}
]
}
Expand Down
6 changes: 4 additions & 2 deletions packages/web-app-files/src/mixins/actions/move.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default {
{
icon: 'folder-move',
handler: resource => this.$_move_trigger(resource),
ariaLabel: () =>
label: () =>
this.$pgettext(
'Action in the files list row to initiate move of a single resource',
'Move'
Expand All @@ -32,7 +32,9 @@ export default {
}

return canBeMoved(resource, this.currentFolder.path)
}
},
componentType: 'oc-button',
class: 'oc-files-actions-sidebar-move-trigger'
}
]
}
Expand Down
22 changes: 15 additions & 7 deletions packages/web-app-files/src/mixins/actions/navigate.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default {
{
icon: 'folder-open',
handler: resource => this.$_navigate_trigger(resource),
ariaLabel: () =>
label: () =>
this.$pgettext('Action in the files list row to open a folder', 'Open folder'),
isEnabled: ({ resource }) => {
if (checkRoute(['files-trashbin'], this.$route.name)) {
Expand All @@ -18,9 +18,20 @@ export default {

return resource.type === 'folder'
},
canBeDefault: true
canBeDefault: true,
componentType: 'router-link',
route: this.route,
class: 'oc-files-actions-sidebar-navigate'
}
]
},
route() {
let route = 'files-personal'
if (this.publicPage()) {
route = 'files-public-list'
}

return route
}
},
methods: {
Expand All @@ -30,12 +41,9 @@ export default {
if (this.searchTerm !== '' && this.$route.params.item === folder.path) {
this.resetSearch()
}
let route = 'files-personal'
if (this.publicPage()) {
route = 'files-public-list'
}

this.$router.push({
name: route,
name: this.route,
params: {
item: folder.path
}
Expand Down
6 changes: 4 additions & 2 deletions packages/web-app-files/src/mixins/actions/rename.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default {
return [
{
icon: 'edit',
ariaLabel: () => {
label: () => {
return this.$gettext('Rename')
},
handler: this.$_rename_trigger,
Expand All @@ -20,7 +20,9 @@ export default {
}

return resource.canRename()
}
},
componentType: 'oc-button',
class: 'oc-files-actions-sidebar-rename-trigger'
}
]
}
Expand Down
6 changes: 4 additions & 2 deletions packages/web-app-files/src/mixins/actions/restore.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ export default {
return [
{
icon: 'restore',
ariaLabel: () => this.$gettext('Restore'),
label: () => this.$gettext('Restore'),
handler: this.$_restore_trigger,
isEnabled: () => checkRoute(['files-trashbin'], this.$route.name)
isEnabled: () => checkRoute(['files-trashbin'], this.$route.name),
componentType: 'oc-button',
class: 'oc-files-actions-sidebar-restore-trigger'
}
]
}
Expand Down
Loading

0 comments on commit 93e37df

Please sign in to comment.