mirror of
https://github.com/opf/openproject.git
synced 2026-06-13 19:20:00 +00:00
Set accessible names on table column headers
capybara_accessible_selectors 0.16 resolves role selectors such as
`:columnheader` by the computed accessible name. In a browser that name
folds in the CSS `text-transform: uppercase` styling and the column
action-menu trigger text, so `have_columnheader("Subject")` no longer
matches a header whose accessible name resolves to "SUBJECT Open menu".
Sets an explicit `aria-label` equal to the plain caption on each header
cell, in both the server-rendered tables and the work package table, so
the accessible name is the column title alone. This also improves screen
reader output, which previously announced the uppercased text and the
menu label.
This commit is contained in:
@@ -42,7 +42,7 @@ See COPYRIGHT and LICENSE files for more details.
|
||||
<% if sortable_column?(name) %>
|
||||
<%= helpers.sort_header_tag(name, **options) %>
|
||||
<% else %>
|
||||
<th>
|
||||
<th aria-label="<%= options[:caption] %>">
|
||||
<div class="generic-table--sort-header-outer">
|
||||
<div class="generic-table--sort-header">
|
||||
<span>
|
||||
|
||||
@@ -338,7 +338,7 @@ module SortHelper
|
||||
|
||||
# Extracts the given `options` and provides them to a block.
|
||||
# See #sort_header_tag and #sort_header_with_action_menu for usage examples.
|
||||
def with_sort_header_options(column, allowed_params: nil, with_title: false, **options)
|
||||
def with_sort_header_options(column, allowed_params: nil, with_title: false, **options) # rubocop:disable Metrics/AbcSize
|
||||
caption = get_caption(column, options)
|
||||
|
||||
default_order = options.delete(:default_order) || "asc"
|
||||
@@ -349,6 +349,12 @@ module SortHelper
|
||||
options[:title] = sort_header_title(column, caption, options) if with_title
|
||||
options[:icon_only_header] = column == :favorited
|
||||
|
||||
# Give the header cell an explicit accessible name equal to the plain caption.
|
||||
# Without it, the column header's accessible name is derived from its contents,
|
||||
# which can include the action menu trigger text and is uppercased by the
|
||||
# `text-transform` styling, neither of which should be part of the name.
|
||||
options[:"aria-label"] = caption if caption.present?
|
||||
|
||||
within_sort_header_tag_hierarchy(options, sort_class(column)) do
|
||||
yield(column, caption, default_order, allowed_params:, param:, lang:, title: options[:title],
|
||||
sortable: options.fetch(:sortable, false), data:)
|
||||
|
||||
@@ -45,7 +45,7 @@ See COPYRIGHT and LICENSE files for more details.
|
||||
<tr>
|
||||
<th><div class="generic-table--empty-header"></div></th>
|
||||
<% @roles.each do |role| %>
|
||||
<th>
|
||||
<th aria-label="<%= role.name %>">
|
||||
<div class="generic-table--sort-header-outer">
|
||||
<div class="generic-table--sort-header">
|
||||
<%= content_tag(role.builtin? ? "em" : "span", h(role.name)) %>
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
}
|
||||
@for (column of columns; track column.href) {
|
||||
<th
|
||||
[attr.aria-label]="column.name"
|
||||
[ngClass]="{'-max': column.id === 'subject', '-min-200': ['estimatedTime', 'remainingTime'].includes(column.id) }"
|
||||
class="wp-table--table-header">
|
||||
<sortHeader [headerColumn]="column"
|
||||
|
||||
@@ -145,7 +145,7 @@ RSpec.describe SortHelper do
|
||||
|
||||
it "renders a th with a sort link" do
|
||||
expect(output).to be_html_eql(<<-HTML)
|
||||
<th title="Sort by "Id"">
|
||||
<th title="Sort by "Id"" aria-label="Id">
|
||||
<div class="generic-table--sort-header-outer">
|
||||
<div class="generic-table--sort-header">
|
||||
<span>
|
||||
@@ -165,7 +165,7 @@ RSpec.describe SortHelper do
|
||||
|
||||
it "adds the sort class" do
|
||||
expect(output).to be_html_eql(<<-HTML)
|
||||
<th title="Ascending sorted by "Id"">
|
||||
<th title="Ascending sorted by "Id"" aria-label="Id">
|
||||
<div class="generic-table--sort-header-outer">
|
||||
<div class="generic-table--sort-header">
|
||||
<span class="sort asc">
|
||||
@@ -187,7 +187,7 @@ RSpec.describe SortHelper do
|
||||
|
||||
it "adds the sort class" do
|
||||
expect(output).to be_html_eql(<<-HTML)
|
||||
<th title="Descending sorted by "Id"">
|
||||
<th title="Descending sorted by "Id"" aria-label="Id">
|
||||
<div class="generic-table--sort-header-outer">
|
||||
<div class="generic-table--sort-header">
|
||||
<span class="sort desc">
|
||||
@@ -219,7 +219,7 @@ RSpec.describe SortHelper do
|
||||
context "when not given allowed parameters" do
|
||||
it "copies default ones to the link" do
|
||||
expect(output).to be_html_eql(<<-HTML)
|
||||
<th title="Sort by "Id"">
|
||||
<th title="Sort by "Id"" aria-label="Id">
|
||||
<div class="generic-table--sort-header-outer">
|
||||
<div class="generic-table--sort-header">
|
||||
<span>
|
||||
@@ -240,7 +240,7 @@ RSpec.describe SortHelper do
|
||||
|
||||
it "copies them to the link" do
|
||||
expect(output).to be_html_eql(<<-HTML)
|
||||
<th title="Sort by "Id"">
|
||||
<th title="Sort by "Id"" aria-label="Id">
|
||||
<div class="generic-table--sort-header-outer">
|
||||
<div class="generic-table--sort-header">
|
||||
<span>
|
||||
@@ -262,7 +262,7 @@ RSpec.describe SortHelper do
|
||||
|
||||
it "includes the passed data param in the link" do
|
||||
expect(output).to be_html_eql(<<~HTML)
|
||||
<th title="Sort by "Id"">
|
||||
<th title="Sort by "Id"" aria-label="Id">
|
||||
<div class="generic-table--sort-header-outer">
|
||||
<div class="generic-table--sort-header">
|
||||
<span>
|
||||
|
||||
Reference in New Issue
Block a user