feat: adds keyboard accessibility to tabs

This commit is contained in:
carla 2026-02-26 10:37:57 +01:00
parent 615b4b866b
commit 2922a4d1ee
11 changed files with 680 additions and 613 deletions

View file

@ -765,6 +765,8 @@ defmodule MvWeb.CoreComponents do
When `row_click` is set, clicking a row (or a data cell) triggers the handler.
Rows with `row_click` get a subtle hover and focus-within outline (theme-friendly ring).
For keyboard accessibility (WCAG 2.1.1), the first column without `col_click` gets
`tabindex="0"` and `role="button"`; the TableRowKeydown hook triggers the row action on Enter/Space.
When `selected_row_id` is set and matches a row's id (via `row_value_id` or `row_item.(row).id`),
that row gets a stronger selected outline (ring-primary) for accessibility (not color-only).
@ -847,8 +849,22 @@ defmodule MvWeb.CoreComponents do
assigns = assign(assigns, :row_value_id_fn, row_value_id_fn)
# WCAG 2.1.1: when row_click is set, first column without col_click gets tabindex="0"
# so rows are reachable via Tab; TableRowKeydown hook triggers click on Enter/Space
first_row_click_col_idx =
if assigns[:row_click] do
Enum.find_index(assigns[:col] || [], fn c -> !c[:col_click] end)
end
assigns =
assign(assigns, :first_row_click_col_idx, first_row_click_col_idx)
~H"""
<div class="overflow-auto">
<div
id={@row_click && "#{@id}-keyboard"}
class="overflow-auto"
phx-hook={@row_click && "TableRowKeydown"}
>
<table class="table table-zebra">
<thead>
<tr>
@ -884,6 +900,11 @@ defmodule MvWeb.CoreComponents do
>
<td
:for={{col, col_idx} <- Enum.with_index(@col)}
tabindex={if @row_click && @first_row_click_col_idx == col_idx, do: 0, else: nil}
role={if @row_click && @first_row_click_col_idx == col_idx, do: "button", else: nil}
data-row-clickable={
if @row_click && @first_row_click_col_idx == col_idx, do: "true", else: nil
}
phx-click={
(col[:col_click] && col[:col_click].(@row_item.(row))) ||
(@row_click && @row_click.(row))
@ -907,6 +928,19 @@ defmodule MvWeb.CoreComponents do
classes
end
# WCAG: no focus ring on the cell itself; row shows focus via focus-within
classes =
if @row_click && @first_row_click_col_idx == col_idx do
[
"focus:outline-none",
"focus-visible:outline-none",
"focus:ring-0",
"focus-visible:ring-0" | classes
]
else
classes
end
classes =
if col_class do
[col_class | classes]