Search field, combobox (single and multi) and file input components #625
Labels
No labels
bug
duplicate
enhancement
help wanted
high priority
invalid
L
low priority
M
medium priority
needs refinement
optional
question
S
security
technical improvement
UX Improvement
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
local-it/mitgliederverwaltung#625
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Motivation
The member search (magnifier, clear button, live filter, URL sync) and the group's “Add members” picker (chips, no icon, no clear, list vanishes without results) share nothing; Escape behaves differently in each. There are three combobox implementations (two copies), with options wrongly in the Tab order, no “No results”, four placeholder wordings, and in the user form a page-wide key listener with a database read per change (fixed minimally in U1). The global-settings “Add field” list is semantically a menu button. The CSV upload has no proper component. DESIGN_GUIDELINES §19 and §18.3 define the target.
Visible improvement
Searching and picking feel the same everywhere: one look, Escape and “×” clear, a clear “No results” message, full keyboard support.
Scope (ordered steps,
just ci-devgreen after each)<.search_input>: magnifier, one clear button (native search cancel suppressed), Escape clears, focus stays, 300 ms debounce, URL sync, translated accessible name. Migrate the member overview's search bar (incl. its inline SVG).<.combobox>single and multi, APG combobox with a listbox popup: focus in input,aria-activedescendant, options not tabbable, keyboard navigation in a colocated hook on the client (no roundtrip per key), active option reset when the options change, Enter never selects from a stale result while a debounced search is pending (decide: wait for the result or ignore Enter), “No results for “‹query›””, result count announced, chips withxsremove buttons (≥ 24 px target), Backspace removes the last chip, “Add N” commit for multi; server-side filtering with debounce; no page-wide key listener. The server accepts a selection only if its id is among the options it rendered (loaded with the actor), and the commit handler re-checks the relation permission with the actor before saving (asGroupLive.Showdoes today: lookup inavailable_members, thencan?(actor, :update, group); DESIGN_GUIDELINES §19.2). Use Doggo's combobox as the reference implementation (MIT, attribution in the moduledoc).<.menu_button>mechanism.<.file_input>: label bound to the real input, help text (types, max size), file name, upload errors witharia-invalid, hover state; migrate the CSV import.Out of scope
Acceptance criteria
phx-window-keydownin pickers.ui-tagged browser test); combobox selection, chip removal, commit, “No results”; a forged select event with an id outside the rendered options selects nothing; a forged commit from an actor without update permission saves nothing; no database read on keys that do not change the query.just ci-devgreen after every step.Dependencies
<.search_input>answer it; close #188 with a reference to this issue.<.search_input>on more index pages.Anchors (verified against
main@d9093a1f, re-check before filing)lib/mv_web/components/search_bar_component.exlib/mv_web/live/user_live/form.ex:232,816lib/mv_web/live/group_live/show.exlib/mv_web/components/add_filter_builder_component.exlib/mv_web/live/global_settings_live.ex:226lib/mv_web/live/import_live/components.ex:79,90Known constraint: debounce vs. keyboard (from #593)
Phoenix LiveView routes every
phx-*event of an element through the element's singlephx-debouncetimer, focus included (only blur/focusout are exempt). An input therefore cannot have a debouncedphx-change(search) and undelayedphx-keydown/phx-focus(arrow keys, Enter, Escape, open-on-focus) at the same time. Today the two pickers make opposite trade-offs: the user form member picker (#member-search-input) has no debounce, so every keystroke runs one:available_for_linkingread;group_live/show.exputs the keys behind a 300 ms debounce (delayed or dropped arrow keys). #593 tried a hook variant (theComboBoxhook pushes navigation keys whilephx-changestays debounced) and reverted it: a debounced search arriving after an immediate Enter/Escape reopened the dropdown and reset the highlight. The<.combobox>in step 2 must order events so that a late search never reopens a list already closed by Enter/Escape and never resets the highlight (e.g. send the current input value with each key and apply a pending search first, or ignore searches for an already-applied query). Additional acceptance:Caution
/solutions, not mid-run.has_element?; cover keyboard behavior in aui-tagged browser test.Related: date range input (from #548 FU-1, regrouped 2026-10-25)
The filter builder's date values use the #548 stopgap: a native
<input type="date">in a daisyUI.inputplus relative presets andtype=month(add_filter_builder_component.ex:493-496). If U7 or U10 builds a shared date-range control, the requirements are: from–to range across months and years, quick year and decade jump, typed input (year + localized month name), month-only view for birthdays, WCAG 2.2 AA, dd.MM.yyyy with Monday start, a LiveView hook or web component withphx-update="ignore", vendorable offline (single-file ESM, no npm). Candidates: native-first (today) vs. vanilla-calendar-pro vs. a custom year+month select; research in.pipeline/research/mitgliederverwaltung-548-datepicker-options.md. Optional for U7; decide in its /clarify whether it belongs here or in U10 (list toolbars).