List toolbars, empty states and accessible orderable lists #632

Open
opened 2026-10-30 14:48:01 +01:00 by simon · 0 comments
Owner

Motivation

All list building blocks (search, sort headers, filters) exist only on the member overview; users, groups and join requests have no search, the users sort is not in the URL, and three sort-header implementations exist (one without a visible focus). Join requests are split into two tables instead of a status filter. Five raw <table>s bypass <.table>. Empty states come in five variants or are missing; numbers are not consistently right-aligned; booleans appear as text and badges in the same table. The orderable join-form table has no move buttons and (before U1) no locked rows; data fields have no position attribute, so their order is alphabetical in three places. Making that order configurable is #15; this issue prepares the building blocks for it but does not implement it. DESIGN_GUIDELINES §7.3, §7.4, §8.8–§8.11 and §4.2 define the target.

Visible improvement

Users, groups and join requests can be searched and sorted like members; empty lists say what to do; tables align numbers and show booleans one way; reordering works with buttons, not only by dragging.

Scope (ordered steps, just ci-dev green after each)

  1. One shared sort header (button in <th>, aria-sort, focus ring, URL state); migrate the three implementations.
  2. Toolbars per §7.3: users and groups (search + URL sort); join requests (search + URL sort + status filter replacing the two tables).
  3. <.empty_state>; migrate all empty states; “No results” + “Clear filters” for filtered lists.
  4. Raw tables to <.table>: group members, statistics (2), import preview, fees tab. Decide whether <.table> renders the row-click cell's content as a real link to the row target instead of today's role="button" cell (DESIGN_GUIDELINES §8.8); either way no link or control sits inside the row-click cell (no nested interactive elements, one Tab stop per row).
  5. Numbers right-aligned with tabular figures; decide one read-only boolean presentation and apply it; maybe-value placeholders (“No description”, “-”) to <.maybe_value>.
  6. Harden <.sortable_table> (it already has locked_ids): the reorder handler rejects moves of locked rows, visible move up/down buttons with row-specific names, gettext announcements, Escape undo.
  7. Data field order, prepared for #15: the three places that list data fields (overview columns, member form, data field settings) take their order from one shared sort helper, still alphabetical. No position attribute, no migration, no order editing here: #15 later switches that one helper to a stored order and reuses the hardened sortable table from step 6. Check the helper against #15's acceptance criteria (same order in overview and edit form; member fields and custom fields orderable) so #15 needs no second refactor.
  8. Showcase sections: sort header, empty state, sortable table.

Out of scope

  • Server-side pagination and new list features beyond the toolbar.
  • Saved views (#549, runs after this issue).
  • Configurable field order (#15): position attribute, migration and admin ordering of member and custom fields. This issue only keeps the order in one place and hardens the sortable table that #15 will use.

Acceptance criteria

  • DESIGN_GUIDELINES §4.2, §7.1, §7.3, §7.4, §8.6, §8.8–§8.11 are met; no raw <table> in views.
  • Tests: search and sort state in the URL for each list; status filter for join requests; empty state and “No results”; move up/down and locked rows; overview columns, member form and data field settings list data fields in the same order, taken from one helper.
  • Before/after screenshots: users list, join requests, an empty list, the join-form field order.
  • Accessibility: sort buttons with visible focus and aria-sort; move buttons as dragging alternative (WCAG 2.5.7); announcements translated.
  • Showcase sections added.
  • just ci-dev green after every step.

Dependencies

  • Consider #174 (aria-sort in table headers): the shared sort header (step 1) fixes it; close #174 with a reference to this issue.
  • U7 (<.search_input>), U9 (row rules, edit routes).
  • #549 (saved views) builds on these toolbars.

Anchors (verified against main @ d9093a1f, re-check before filing)

  • Users sort button: lib/mv_web/components/table_components.ex:24; other sort headers: lib/mv_web/components/sort_header_component.ex, lib/mv_web/components/member_name_sort_header.ex
  • Raw tables: lib/mv_web/live/group_live/show.ex:295, lib/mv_web/live/statistics_live.ex:225,377, lib/mv_web/live/import_live/components.ex:146, lib/mv_web/live/member_live/show/membership_fees_component.ex:94
  • Join requests (two tables): lib/mv_web/live/join_request_live/index.ex
  • Orderable table: lib/mv_web/live/global_settings_live.ex:270, <.sortable_table> in lib/mv_web/components/core_components.ex:1398

Caution

  • Keep #15 in mind but do not solve it: no data-model change in this issue. The shared sort helper and the hardened sortable table are what #15 builds on; link #15 in the PR.
  • The statistics tables become <.table> before the refined-statistics feature adds charts (DESIGN_GUIDELINES §22.5).
## Motivation All list building blocks (search, sort headers, filters) exist only on the member overview; users, groups and join requests have no search, the users sort is not in the URL, and three sort-header implementations exist (one without a visible focus). Join requests are split into two tables instead of a status filter. Five raw `<table>`s bypass `<.table>`. Empty states come in five variants or are missing; numbers are not consistently right-aligned; booleans appear as text and badges in the same table. The orderable join-form table has no move buttons and (before U1) no locked rows; data fields have no position attribute, so their order is alphabetical in three places. Making that order configurable is #15; this issue prepares the building blocks for it but does not implement it. DESIGN_GUIDELINES §7.3, §7.4, §8.8–§8.11 and §4.2 define the target. ## Visible improvement Users, groups and join requests can be searched and sorted like members; empty lists say what to do; tables align numbers and show booleans one way; reordering works with buttons, not only by dragging. ## Scope (ordered steps, `just ci-dev` green after each) 1. One shared sort header (button in `<th>`, `aria-sort`, focus ring, URL state); migrate the three implementations. 2. Toolbars per §7.3: users and groups (search + URL sort); join requests (search + URL sort + status filter replacing the two tables). 3. `<.empty_state>`; migrate all empty states; “No results” + “Clear filters” for filtered lists. 4. Raw tables to `<.table>`: group members, statistics (2), import preview, fees tab. Decide whether `<.table>` renders the row-click cell's content as a real link to the row target instead of today's `role="button"` cell (DESIGN_GUIDELINES §8.8); either way no link or control sits inside the row-click cell (no nested interactive elements, one Tab stop per row). 5. Numbers right-aligned with tabular figures; decide one read-only boolean presentation and apply it; maybe-value placeholders (“No description”, “-”) to `<.maybe_value>`. 6. Harden `<.sortable_table>` (it already has `locked_ids`): the reorder handler rejects moves of locked rows, visible move up/down buttons with row-specific names, gettext announcements, Escape undo. 7. Data field order, prepared for #15: the three places that list data fields (overview columns, member form, data field settings) take their order from one shared sort helper, still alphabetical. No position attribute, no migration, no order editing here: #15 later switches that one helper to a stored order and reuses the hardened sortable table from step 6. Check the helper against #15's acceptance criteria (same order in overview and edit form; member fields and custom fields orderable) so #15 needs no second refactor. 8. Showcase sections: sort header, empty state, sortable table. ## Out of scope - Server-side pagination and new list features beyond the toolbar. - Saved views (#549, runs after this issue). - Configurable field order (#15): position attribute, migration and admin ordering of member and custom fields. This issue only keeps the order in one place and hardens the sortable table that #15 will use. ## Acceptance criteria - DESIGN_GUIDELINES §4.2, §7.1, §7.3, §7.4, §8.6, §8.8–§8.11 are met; no raw `<table>` in views. - Tests: search and sort state in the URL for each list; status filter for join requests; empty state and “No results”; move up/down and locked rows; overview columns, member form and data field settings list data fields in the same order, taken from one helper. - Before/after screenshots: users list, join requests, an empty list, the join-form field order. - Accessibility: sort buttons with visible focus and `aria-sort`; move buttons as dragging alternative (WCAG 2.5.7); announcements translated. - Showcase sections added. - `just ci-dev` green after every step. ## Dependencies - Consider #174 (`aria-sort` in table headers): the shared sort header (step 1) fixes it; close #174 with a reference to this issue. - U7 (`<.search_input>`), U9 (row rules, edit routes). - #549 (saved views) builds on these toolbars. ## Anchors (verified against `main` @ `d9093a1f`, re-check before filing) - Users sort button: `lib/mv_web/components/table_components.ex:24`; other sort headers: `lib/mv_web/components/sort_header_component.ex`, `lib/mv_web/components/member_name_sort_header.ex` - Raw tables: `lib/mv_web/live/group_live/show.ex:295`, `lib/mv_web/live/statistics_live.ex:225,377`, `lib/mv_web/live/import_live/components.ex:146`, `lib/mv_web/live/member_live/show/membership_fees_component.ex:94` - Join requests (two tables): `lib/mv_web/live/join_request_live/index.ex` - Orderable table: `lib/mv_web/live/global_settings_live.ex:270`, `<.sortable_table>` in `lib/mv_web/components/core_components.ex:1398` ## Caution - Keep #15 in mind but do not solve it: no data-model change in this issue. The shared sort helper and the hardened sortable table are what #15 builds on; link #15 in the PR. - The statistics tables become `<.table>` before the refined-statistics feature adds charts (DESIGN_GUIDELINES §22.5).
Sign in to join this conversation.
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
local-it/mitgliederverwaltung#632
No description provided.