Problem/Motivation

Since Drupal 10.2 (#1038316), the table rendered for multi-value field widgets has a column for the per-item "Remove" button. The header cell for that column is an empty array, so it renders as an empty <th></th>.

In 11.x this is in \Drupal\Core\Field\FieldPreprocess::preprocessFieldMultipleValueForm() (previously template_preprocess_field_multiple_value_form()):

$header = [
  [
    'data' => [ /* h4 field label */ ],
    'colspan' => 2,
    'class' => ['field-label'],
  ],
  [],
  $this->t('Order', [], ['context' => 'Sort order']),
];

Accessibility checkers report an empty table header on every form with an unlimited/multi-value field: axe-core's empty-table-header rule and Editoria11y's "Empty table header" check. Screen reader users get no name for the column that holds the Remove buttons. This relates to WCAG 1.3.1 Info and Relationships.

#3587682 reported an empty table header from an automated scan, but it was closed as "cannot reproduce". That report pointed at a different page. This issue is the reproducible case in the field widget table.

Steps to reproduce

  1. Install Drupal with the Standard profile (Claro as the admin theme).
  2. Add a reference field (paragraph reference) with unlimited cardinality to the Article content type.
  3. Go to /node/add/article.
  4. Inspect the field's table header: the third <th> is empty.
  5. Run axe DevTools or Editoria11y on the page: it reports an empty table header.

Proposed resolution

Give the actions column header a visually hidden label so it has an accessible name without changing the visual design:

[
  'data' => [
    '#type' => 'html_tag',
    '#tag' => 'span',
    '#value' => $this->t('Operations'),
    '#attributes' => ['class' => ['visually-hidden']],
  ],
],

"Operations" matches the label core already uses for action columns elsewhere, such as entity list builders. Claro's preprocess_field_multiple_value_form keeps working: for disabled widgets, its loop adds the is-disabled class to header cells that have a data key.

Alternative: only output the column (header and cells) when at least one item has _actions. That also fixes the empty body cells contrib widgets get (see Paragraphs #3418303). It is a larger change and could be a follow-up.

Remaining tasks

  • Review the approach and the label wording.
  • Add test coverage that the header cell is not empty, e.g. in an existing multi-value widget functional test.
  • Convert to an MR.

User interface changes

No visual change. Screen readers announce the actions column header as "Operations".

API changes

None.

Data model changes

None.

Release notes snippet

N/A

Issue fork drupal-3630425

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

chamilsanjeewa created an issue. See original summary.

chamilsanjeewa’s picture

StatusFileSize
new829 bytes

Opened MR !17421 with the fix, and attached a static patch of the same change for use with composer-patches.

The header cell for the actions (Remove) column in the multi-value widget table was an empty array, which renders as an empty <th></th>. It now holds a visually hidden "Operations" label, so the column has an accessible name and nothing changes visually.

Claro's preprocess_field_multiple_value_form still works: for disabled widgets, its loop adds the is-disabled class to header cells that have a data key, so this cell gets it like the others.

Testing steps:

  1. Add an unlimited-cardinality plain text field to Article.
  2. Go to /node/add/article and inspect the field's table header: the third <th> now contains <span class="visually-hidden">Operations</span>.
  3. Run axe DevTools or Editoria11y: the empty table header warning is gone.

Still needs tests, so leaving this at Needs work / Needs tests.

chamilsanjeewa’s picture

StatusFileSize
new829 bytes
chamilsanjeewa’s picture

Issue summary: View changes
chamilsanjeewa’s picture

Issue summary: View changes
quietone’s picture

Status: Active » Postponed (maintainer needs more info)

Does this happen on the main branch with the Default Admin theme?

chamilsanjeewa’s picture

StatusFileSize
new36.6 KB

Yes, on the main branch.
Only local images are allowed.

mgifford’s picture

Status: Postponed (maintainer needs more info) » Needs review
StatusFileSize
new148.22 KB

Yes, this still exists. In the Default Admin Theme it is:

<thead>
      <tr>
                            <th colspan="2" class="field-label"><h4 class="form-item__label form-item__label--multiple-value-form">Lab multi-value text</h4>
</th>
                            <th></th>
                            <th class="tabledrag-hide" style="display: none;">Order</th>
              </tr>
    </thead>

With an updated (D11 to D12) patch it is:

<tr>
                            <th colspan="2" class="field-label"><h4 class="form-item__label form-item__label--multiple-value-form">Lab multi-value text</h4>
</th>
                            <th><span class="visually-hidden">Operations</span>
</th>
                            <th class="tabledrag-hide" style="display: none;">Order</th>
              </tr>

No difference in before/after visual appearance

Update done with AI.

I will update the MR, but the details behind this are here https://github.com/mgifford/drupal-core-lab/blob/main/reports/issues/363...

smustgrave’s picture

Version: 11.4.x-dev » main
Status: Needs review » Needs work

MR needs to be updated for main then and test coverage.

Thanks