From c566acbd7e885c75e5c9363accb51c7624ea20b5 Mon Sep 17 00:00:00 2001
From: Eric Eastwood <contact@ericeastwood.com>
Date: Thu, 12 Jan 2017 12:24:33 -0500
Subject: [PATCH] Improve button accessibility on pipelines page

---
 .../pipeline_actions.js.es6                   | 47 +++++++++++--------
 .../vue_pipelines_index/stage.js.es6          |  7 +--
 app/assets/stylesheets/pages/pipelines.scss   |  4 ++
 .../projects/ci/pipelines/_pipeline.html.haml |  8 ++--
 .../26445-accessible-piplelines-buttons.yml   |  4 ++
 5 files changed, 44 insertions(+), 26 deletions(-)
 create mode 100644 changelogs/unreleased/26445-accessible-piplelines-buttons.yml

diff --git a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6 b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6
index ad5cb30cc42..b195b0ef3ba 100644
--- a/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6
+++ b/app/assets/javascripts/vue_pipelines_index/pipeline_actions.js.es6
@@ -22,47 +22,51 @@
         <div class="controls pull-right">
           <div class="btn-group inline">
             <div class="btn-group">
-              <a
+              <button
                 v-if='actions'
-                class="dropdown-toggle btn btn-default js-pipeline-dropdown-manual-actions"
+                class="dropdown-toggle btn btn-default has-tooltip js-pipeline-dropdown-manual-actions"
                 data-toggle="dropdown"
                 title="Manual build"
-                alt="Manual Build"
+                data-placement="top"
+                data-toggle="dropdown"
+                aria-label="Manual build"
               >
-                <span v-html='svgs.iconPlay'></span>
-                <i class="fa fa-caret-down"></i>
-              </a>
+                <span v-html='svgs.iconPlay' aria-hidden="true"></span>
+                <i class="fa fa-caret-down" aria-hidden="true"></i>
+              </button>
               <ul class="dropdown-menu dropdown-menu-align-right">
                 <li v-for='action in pipeline.details.manual_actions'>
                   <a
                     rel="nofollow"
                     data-method="post"
                     :href='action.path'
-                    title="Manual build"
                   >
-                    <span v-html='svgs.iconPlay'></span>
-                    <span title="Manual build">{{action.name}}</span>
+                    <span v-html='svgs.iconPlay' aria-hidden="true"></span>
+                    <span>{{action.name}}</span>
                   </a>
                 </li>
               </ul>
             </div>
             <div class="btn-group">
-              <a
+              <button
                 v-if='artifacts'
-                class="dropdown-toggle btn btn-default build-artifacts js-pipeline-dropdown-download"
+                class="dropdown-toggle btn btn-default build-artifacts has-tooltip js-pipeline-dropdown-download"
+                data-toggle="dropdown"
+                title="Artifacts"
+                data-placement="top"
                 data-toggle="dropdown"
-                type="button"
+                aria-label="Artifacts"
               >
-                <i class="fa fa-download"></i>
-                <i class="fa fa-caret-down"></i>
-              </a>
+                <i class="fa fa-download" aria-hidden="true"></i>
+                <i class="fa fa-caret-down" aria-hidden="true"></i>
+              </button>
               <ul class="dropdown-menu dropdown-menu-align-right">
                 <li v-for='artifact in pipeline.details.artifacts'>
                   <a
                     rel="nofollow"
                     :href='artifact.path'
                   >
-                    <i class="fa fa-download"></i>
+                    <i class="fa fa-download" aria-hidden="true"></i>
                     <span>{{download(artifact.name)}}</span>
                   </a>
                 </li>
@@ -76,9 +80,12 @@
               title="Retry"
               rel="nofollow"
               data-method="post"
+              data-placement="top"
+              data-toggle="dropdown"
               :href='pipeline.retry_path'
+              aria-label="Retry"
             >
-              <i class="fa fa-repeat"></i>
+              <i class="fa fa-repeat" aria-hidden="true"></i>
             </a>
             <a
               v-if='pipeline.flags.cancelable'
@@ -86,10 +93,12 @@
               title="Cancel"
               rel="nofollow"
               data-method="post"
+              data-placement="top"
+              data-toggle="dropdown"
               :href='pipeline.cancel_path'
-              data-original-title="Cancel"
+              aria-label="Cancel"
             >
-              <i class="fa fa-remove"></i>
+              <i class="fa fa-remove" aria-hidden="true"></i>
             </a>
           </div>
         </div>
diff --git a/app/assets/javascripts/vue_pipelines_index/stage.js.es6 b/app/assets/javascripts/vue_pipelines_index/stage.js.es6
index 4e85f16ebc5..496df9aaced 100644
--- a/app/assets/javascripts/vue_pipelines_index/stage.js.es6
+++ b/app/assets/javascripts/vue_pipelines_index/stage.js.es6
@@ -82,12 +82,13 @@
           data-placement="top"
           data-toggle="dropdown"
           type="button"
+          :aria-label='stage.title'
         >
-          <span v-html="svg"></span>
-          <i class="fa fa-caret-down "></i>
+          <span v-html="svg" aria-hidden="true"></span>
+          <i class="fa fa-caret-down" aria-hidden="true"></i>
         </button>
         <ul class="dropdown-menu mini-pipeline-graph-dropdown-menu js-builds-dropdown-container">
-          <div class="arrow-up"></div>
+          <div class="arrow-up" aria-hidden="true"></div>
           <div
             @click='keepGraph($event)'
             :class="dropdownClass"
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index 8dff22e32bd..5d4bd091a6b 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -288,6 +288,10 @@
         }
       }
     }
+
+    .tooltip {
+      white-space: nowrap;
+    }
   }
 
   .build-link {
diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml
index 990bfbcf951..dfdaeb04869 100644
--- a/app/views/projects/ci/pipelines/_pipeline.html.haml
+++ b/app/views/projects/ci/pipelines/_pipeline.html.haml
@@ -78,7 +78,7 @@
         .btn-group.inline
           - if actions.any?
             .btn-group
-              %button.dropdown-toggle.btn.btn-default.js-pipeline-dropdown-manual-actions{ type: 'button', 'data-toggle' => 'dropdown' }
+              %button.dropdown-toggle.btn.btn-default.has-tooltip.js-pipeline-dropdown-manual-actions{ type: 'button', title: 'Manual build', data: { toggle: 'dropdown', placement: 'top' }, 'aria-label': 'Manual build' }
                 = custom_icon('icon_play')
                 = icon('caret-down', 'aria-hidden' => 'true')
               %ul.dropdown-menu.dropdown-menu-align-right
@@ -89,7 +89,7 @@
                       %span= build.name
           - if artifacts.present?
             .btn-group
-              %button.dropdown-toggle.btn.btn-default.build-artifacts.js-pipeline-dropdown-download{ type: 'button', 'data-toggle' => 'dropdown' }
+              %button.dropdown-toggle.btn.btn-default.build-artifacts.has-tooltip.js-pipeline-dropdown-download{ type: 'button', title: 'Artifacts', data: { toggle: 'dropdown', placement: 'top' }, 'aria-label': 'Artifacts' }
                 = icon("download")
                 = icon('caret-down')
               %ul.dropdown-menu.dropdown-menu-align-right
@@ -102,8 +102,8 @@
       - if can?(current_user, :update_pipeline, pipeline.project)
         .cancel-retry-btns.inline
           - if pipeline.retryable?
-            = link_to retry_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), class: 'btn has-tooltip', title: "Retry", method: :post do
+            = link_to retry_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), class: 'btn has-tooltip', title: 'Retry', data: { toggle: 'dropdown', placement: 'top' }, 'aria-label': 'Retry' , method: :post do
               = icon("repeat")
           - if pipeline.cancelable?
-            = link_to cancel_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), class: 'btn btn-remove has-tooltip', title: "Cancel", method: :post do
+            = link_to cancel_namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), class: 'btn btn-remove has-tooltip', title: 'Cancel', data: { toggle: 'dropdown', placement: 'top' }, 'aria-label': 'Cancel' , method: :post do
               = icon("remove")
diff --git a/changelogs/unreleased/26445-accessible-piplelines-buttons.yml b/changelogs/unreleased/26445-accessible-piplelines-buttons.yml
new file mode 100644
index 00000000000..fb5274e5253
--- /dev/null
+++ b/changelogs/unreleased/26445-accessible-piplelines-buttons.yml
@@ -0,0 +1,4 @@
+---
+title: Improve button accessibility on pipelines page
+merge_request: 8561
+author:
-- 
GitLab