]> BookStack Code Mirror - bookstack/commitdiff
Improved accessibility for many editor page components
authorDan Brown <redacted>
Mon, 26 Aug 2019 11:47:04 +0000 (12:47 +0100)
committerDan Brown <redacted>
Mon, 26 Aug 2019 11:47:04 +0000 (12:47 +0100)
Related to #1320

resources/assets/js/components/dropdown.js
resources/assets/js/components/editor-toolbox.js
resources/assets/js/vues/components/dropzone.js
resources/assets/sass/_pages.scss
resources/views/pages/attachment-manager.blade.php
resources/views/pages/editor-toolbox.blade.php
resources/views/pages/form.blade.php
resources/views/pages/template-manager-list.blade.php

index d2fca055654d5b065b2d404bed7c82944e1cb81b..4de1e239b93b3747bd7474ad188d7684b62dfb9e 100644 (file)
@@ -118,8 +118,8 @@ class DropDown {
             }
         });
 
-        // Arrow navigation
-        this.container.addEventListener('keydown', event => {
+        // Keyboard navigation
+        const keyboardNavigation = event => {
             if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {
                 this.focusNext();
                 event.preventDefault();
@@ -128,9 +128,14 @@ class DropDown {
                 event.preventDefault();
             } else if (event.key === 'Escape') {
                 this.hide();
+                this.toggle.focus();
                 event.stopPropagation();
             }
-        });
+        };
+        this.container.addEventListener('keydown', keyboardNavigation);
+        if (this.moveMenu) {
+            this.menu.addEventListener('keydown', keyboardNavigation);
+        }
 
         // Hide menu on enter press or escape
         this.menu.addEventListener('keydown ', event => {
index 10678edfaa4e880c5d3f076b061fd968abdb54a0..354bf0a86b3262f4a5e14a9e446ea87ee9405c65 100644 (file)
@@ -23,6 +23,8 @@ class EditorToolbox {
 
     toggle() {
         this.elem.classList.toggle('open');
+        const expanded = this.elem.classList.contains('open') ? 'true' : 'false';
+        this.toggleButton.setAttribute('aria-expanded', expanded);
     }
 
     setActiveTab(tabName, openToolbox = false) {
index 751cca330020c8d3cf3ffeba6e70e84d33774779..1c045727f842686ebbcb690ced96307c56b1017f 100644 (file)
@@ -2,8 +2,8 @@ import DropZone from "dropzone";
 import { fadeOut } from "../../services/animations";
 
 const template = `
-    <div class="dropzone-container">
-        <div class="dz-message">{{placeholder}}</div>
+    <div class="dropzone-container text-center">
+        <button type="button" class="dz-message">{{placeholder}}</button>
     </div>
 `;
 
index be0cc381c828cca940afb1f505937763f08a5f7a..86db8782eef67db74471780a4e3259ac85579759 100755 (executable)
@@ -258,7 +258,7 @@ body.mce-fullscreen .page-editor .edit-area {
     padding: 0;
     margin: 0;
   }
-  .tabs > span {
+  .tabs > button {
     display: block;
     cursor: pointer;
     padding: $-s $-m;
@@ -266,7 +266,7 @@ body.mce-fullscreen .page-editor .edit-area {
     line-height: 1.6;
     border-bottom: 1px solid rgba(255, 255, 255, 0.3);
   }
-  &.open .tabs > span.active {
+  &.open .tabs > button.active {
     fill: #444;
     background-color: rgba(0, 0, 0, 0.1);
   }
index e362b95d503fea50d8959ef1a39c1194e249e5d5..dd00678043c065602adfb58e8960fe357bed9b28 100644 (file)
 
             <div class="tab-container">
                 <div class="nav-tabs">
-                    <div @click="tab = 'list'" :class="{selected: tab === 'list'}" class="tab-item">{{ trans('entities.attachments_items') }}</div>
-                    <div @click="tab = 'file'" :class="{selected: tab === 'file'}" class="tab-item">{{ trans('entities.attachments_upload') }}</div>
-                    <div @click="tab = 'link'" :class="{selected: tab === 'link'}" class="tab-item">{{ trans('entities.attachments_link') }}</div>
+                    <button type="button" @click="tab = 'list'" :class="{selected: tab === 'list'}"
+                            class="tab-item">{{ trans('entities.attachments_items') }}</button>
+                    <button type="button" @click="tab = 'file'" :class="{selected: tab === 'file'}"
+                            class="tab-item">{{ trans('entities.attachments_upload') }}</button>
+                    <button type="button" @click="tab = 'link'" :class="{selected: tab === 'link'}"
+                            class="tab-item">{{ trans('entities.attachments_link') }}</button>
                 </div>
                 <div v-show="tab === 'list'">
                     <draggable style="width: 100%;" :options="{handle: '.handle'}" @change="fileSortUpdate" :list="files" element="div">
                                 <div v-if="file.deleting">
                                     <span class="text-neg small">{{ trans('entities.attachments_delete_confirm') }}</span>
                                     <br>
-                                    <span class="text-primary small" @click="file.deleting = false;">{{ trans('common.cancel') }}</span>
+                                    <button type="button" class="text-primary small" @click="file.deleting = false;">{{ trans('common.cancel') }}</button>
                                 </div>
                             </div>
-                            <div @click="startEdit(file)" class="drag-card-action text-center text-primary">@icon('edit')</div>
-                            <div @click="deleteFile(file)" class="drag-card-action text-center text-neg">@icon('close')</div>
+                            <button type="button" @click="startEdit(file)" class="drag-card-action text-center text-primary">@icon('edit')</button>
+                            <button type="button" @click="deleteFile(file)" class="drag-card-action text-center text-neg">@icon('close')</button>
                         </div>
                     </draggable>
                     <p class="small text-muted" v-if="files.length === 0">
@@ -75,8 +78,8 @@
 
             <div class="tab-container">
                 <div class="nav-tabs">
-                    <div @click="editTab = 'file'" :class="{selected: editTab === 'file'}" class="tab-item">{{ trans('entities.attachments_upload') }}</div>
-                    <div @click="editTab = 'link'" :class="{selected: editTab === 'link'}" class="tab-item">{{ trans('entities.attachments_set_link') }}</div>
+                    <button type="button" @click="editTab = 'file'" :class="{selected: editTab === 'file'}" class="tab-item">{{ trans('entities.attachments_upload') }}</button>
+                    <button type="button" @click="editTab = 'link'" :class="{selected: editTab === 'link'}" class="tab-item">{{ trans('entities.attachments_set_link') }}</button>
                 </div>
                 <div v-if="editTab === 'file'">
                     <dropzone :upload-url="getUploadUrl(fileToEdit)" :uploaded-to="pageId" placeholder="{{ trans('entities.attachments_edit_drop_upload') }}" @success="uploadSuccessUpdate"></dropzone>
index 3ce4cfbf3f02632ff736d7983df2125c74386f2c..6ea651820ef8f46f437f35a635b20712606847ce 100644 (file)
@@ -1,12 +1,12 @@
 <div editor-toolbox class="floating-toolbox">
 
     <div class="tabs primary-background-light">
-        <span toolbox-toggle>@icon('caret-left-circle')</span>
-        <span toolbox-tab-button="tags" title="{{ trans('entities.page_tags') }}" class="active">@icon('tag')</span>
+        <button type="button" toolbox-toggle aria-expanded="false">@icon('caret-left-circle')</button>
+        <button type="button" toolbox-tab-button="tags" title="{{ trans('entities.page_tags') }}" class="active">@icon('tag')</button>
         @if(userCan('attachment-create-all'))
-            <span toolbox-tab-button="files" title="{{ trans('entities.attachments') }}">@icon('attach')</span>
+            <button type="button" toolbox-tab-button="files" title="{{ trans('entities.attachments') }}">@icon('attach')</button>
         @endif
-        <span toolbox-tab-button="templates" title="{{ trans('entities.templates') }}">@icon('template')</span>
+        <button type="button" toolbox-tab-button="templates" title="{{ trans('entities.templates') }}">@icon('template')</button>
     </div>
 
     <div toolbox-tab-content="tags">
index 0d5411e6ccab2e4b245957df904be96fd24ae136..ffc286c2cadadc32f3f9834dfd72ffb6be54ee3c 100644 (file)
 
             <div class="text-center px-m py-xs">
                 <div v-show="draftsEnabled" dropdown dropdown-move-menu class="dropdown-container draft-display text">
-                    <a dropdown-toggle aria-haspopup="true" aria-expanded="false" title="{{ trans('entities.pages_edit_draft_options') }}" class="text-primary text-button"><span class="faded-text" v-text="draftText"></span>&nbsp; @icon('more')</a>
+                    <button type="button" dropdown-toggle aria-haspopup="true" aria-expanded="false" title="{{ trans('entities.pages_edit_draft_options') }}" class="text-primary text-button"><span class="faded-text" v-text="draftText"></span>&nbsp; @icon('more')</button>
                     @icon('check-circle', ['class' => 'text-pos draft-notification svg-icon', ':class' => '{visible: draftUpdated}'])
                     <ul class="dropdown-menu" role="menu">
                         <li>
-                            <a @click="saveDraft()" class="text-pos">@icon('save'){{ trans('entities.pages_edit_save_draft') }}</a>
+                            <button type="button" @click="saveDraft()" class="text-pos">@icon('save'){{ trans('entities.pages_edit_save_draft') }}</button>
                         </li>
                         <li v-if="isNewDraft">
                             <a href="{{ $model->getUrl('/delete') }}" class="text-neg">@icon('delete'){{ trans('entities.pages_edit_delete_draft') }}</a>
                         </li>
                         <li v-if="isUpdateDraft">
-                            <a type="button" @click="discardDraft" class="text-neg">@icon('cancel'){{ trans('entities.pages_edit_discard_draft') }}</a>
+                            <button type="button" @click="discardDraft" class="text-neg">@icon('cancel'){{ trans('entities.pages_edit_discard_draft') }}</button>
                         </li>
                     </ul>
                 </div>
@@ -44,7 +44,7 @@
 
             <div class="action-buttons px-m py-xs" v-cloak>
                 <div dropdown dropdown-move-menu class="dropdown-container">
-                    <a dropdown-toggle class="text-primary text-button">@icon('edit') <span v-text="changeSummaryShort"></span></a>
+                    <button type="button" dropdown-toggle aria-haspopup="true" aria-expanded="false" class="text-primary text-button">@icon('edit') <span v-text="changeSummaryShort"></span></button>
                     <ul class="wide dropdown-menu">
                         <li class="px-l py-m">
                             <p class="text-muted pb-s">{{ trans('entities.pages_edit_enter_changelog_desc') }}</p>
index 68899c8a58212f269cc9d75c7c48ae5141a2e951..f2f70c14221b26d67e90aa9358ebbc7257547538 100644 (file)
@@ -1,7 +1,9 @@
 {{ $templates->links() }}
 
 @foreach($templates as $template)
-    <div class="card template-item border-card p-m mb-m" draggable="true" template-id="{{ $template->id }}">
+    <div class="card template-item border-card p-m mb-m" tabindex="0"
+         aria-label="{{ trans('entities.templates_replace_content') }} - {{ $template->name }}"
+         draggable="true" template-id="{{ $template->id }}">
         <div class="template-item-content" title="{{ trans('entities.templates_replace_content') }}">
             <div>{{ $template->name }}</div>
             <div class="text-muted">{{ trans('entities.meta_updated', ['timeLength' => $template->updated_at->diffForHumans()]) }}</div>
@@ -9,9 +11,11 @@
         <div class="template-item-actions">
             <button type="button"
                     title="{{ trans('entities.templates_prepend_content') }}"
+                    aria-label="{{ trans('entities.templates_prepend_content') }} - {{ $template->name }}"
                     template-action="prepend">@icon('chevron-up')</button>
             <button type="button"
                     title="{{ trans('entities.templates_append_content') }}"
+                    aria-label="{{ trans('entities.templates_append_content') }} -- {{ $template->name }}"
                     template-action="append">@icon('chevron-down')</button>
         </div>
     </div>