feat(member): make overview columns sortable through accessible sort headers
This commit is contained in:
parent
dfc616257d
commit
0c375234c8
9 changed files with 350 additions and 51 deletions
|
|
@ -6,44 +6,57 @@ defmodule MvWeb.Components.SortHeaderComponent do
|
|||
- label: string() # Column Heading (can be an heex template)
|
||||
- sort_field: atom() | nil # current sort field from parent liveview
|
||||
- sort_order: :asc | :desc | nil # current sorting order
|
||||
- sort_hint: string() | nil # optional; overrides the generic "click
|
||||
# to sort" tooltip/aria-label for columns
|
||||
# whose sort key is non-obvious (e.g. the
|
||||
# Name column sorts by last name)
|
||||
"""
|
||||
use MvWeb, :live_component
|
||||
|
||||
@impl true
|
||||
def update(assigns, socket) do
|
||||
{:ok, assign(socket, assigns)}
|
||||
{:ok, socket |> assign(assigns) |> assign_new(:sort_hint, fn -> nil end)}
|
||||
end
|
||||
|
||||
# Check if we can add the aria-sort label directly to the daisyUI header
|
||||
# aria-sort={aria_sort(@field, @sort_field, @sort_order)}
|
||||
@impl true
|
||||
def render(assigns) do
|
||||
assigns =
|
||||
assigns
|
||||
|> assign(:tooltip_id, "sort-tooltip-#{assigns.field}")
|
||||
|> assign(:hint, assigns.sort_hint || gettext("Click to sort"))
|
||||
|
||||
~H"""
|
||||
<div>
|
||||
<.tooltip content={aria_sort(@field, @sort_field, @sort_order)} position="bottom">
|
||||
<.button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
aria-label={aria_sort(@field, @sort_field, @sort_order)}
|
||||
class="select-none"
|
||||
phx-click="sort"
|
||||
phx-value-field={@field}
|
||||
data-testid={@field}
|
||||
>
|
||||
{@label}
|
||||
<%= if @sort_field == @field do %>
|
||||
<.icon
|
||||
name={if @sort_order == :asc, do: "hero-chevron-up", else: "hero-chevron-down"}
|
||||
class="sort-icon"
|
||||
/>
|
||||
<% else %>
|
||||
<.icon
|
||||
name="hero-chevron-up-down"
|
||||
class="sort-icon opacity-40"
|
||||
/>
|
||||
<% end %>
|
||||
</.button>
|
||||
</.tooltip>
|
||||
<button
|
||||
id={"sort-btn-#{@field}"}
|
||||
type="button"
|
||||
aria-label={aria_sort(@field, @sort_field, @sort_order, @hint)}
|
||||
aria-describedby={@tooltip_id}
|
||||
class="link link-hover no-underline w-full flex items-center gap-1 text-left text-current select-none"
|
||||
phx-click="sort"
|
||||
phx-value-field={@field}
|
||||
phx-hook="SortTooltip"
|
||||
data-tooltip-id={@tooltip_id}
|
||||
data-testid={@field}
|
||||
>
|
||||
{@label}
|
||||
<%= if @sort_field == @field do %>
|
||||
<.icon
|
||||
name={if @sort_order == :asc, do: "hero-chevron-up", else: "hero-chevron-down"}
|
||||
class="sort-icon"
|
||||
/>
|
||||
<% else %>
|
||||
<.icon
|
||||
name="hero-chevron-up-down"
|
||||
class="sort-icon opacity-40"
|
||||
/>
|
||||
<% end %>
|
||||
</button>
|
||||
<div id={@tooltip_id} popover="manual" role="tooltip" class="sort-tooltip">
|
||||
{aria_sort(@field, @sort_field, @sort_order, @hint)}
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
|
@ -51,13 +64,13 @@ defmodule MvWeb.Components.SortHeaderComponent do
|
|||
# -------------------------------------------------
|
||||
# Hilfsfunktionen für ARIA Attribute & Icon SVG
|
||||
# -------------------------------------------------
|
||||
defp aria_sort(field, sort_field, dir) when field == sort_field do
|
||||
defp aria_sort(field, sort_field, dir, hint) when field == sort_field do
|
||||
case dir do
|
||||
:asc -> gettext("ascending")
|
||||
:desc -> gettext("descending")
|
||||
nil -> gettext("Click to sort")
|
||||
nil -> hint
|
||||
end
|
||||
end
|
||||
|
||||
defp aria_sort(_, _, _), do: gettext("Click to sort")
|
||||
defp aria_sort(_, _, _, hint), do: hint
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue