feat(contacts): search, sort, keyboard nav, contrast + Z/T badges

Phase 0d — the accessibility pass on the Contacts tab.

- Search box filters by label/address/notes (case-insensitive); a distinct
  "no matching contacts" empty state.
- Sortable columns (ImGuiTableFlags_Sortable) — click a header to sort the
  view by label/address/notes, ascending or descending.
- Keyboard nav (when the tab owns focus, no field/modal active): Up/Down move
  the selection through the *visible* order, Enter edits, Delete deletes
  (feeding the two-click confirm), Ctrl+C copies.
- Contrast: the address is no longer rendered as muted TextDisabled (it's the
  row's key data) — normal legible text, with a coloured Z/T type badge.
  Notes are legible too.
- The add/edit form focuses its first field on open (SetKeyboardFocusHere).
- The delete confirm is now visible: the Delete button relabels to
  "Confirm delete?" while armed, instead of a transient toast.

Correctness: selection is tracked by STORAGE index, decoupled from the
filtered/sorted visible order, so edit/delete/copy always target the right
entry. (ImGui renders to a canvas with no OS accessibility tree, so this is a
keyboard/contrast/findability pass, not screen-reader support.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-05 17:10:24 -05:00
parent ddd53dc006
commit 0ff56bf5a4
2 changed files with 152 additions and 44 deletions

View File

@@ -211,6 +211,9 @@ void I18n::loadBuiltinEnglish()
strings_["transactions"] = "Transactions";
strings_["history"] = "History";
strings_["contacts"] = "Contacts";
strings_["contacts_search_placeholder"] = "Search contacts...";
strings_["contacts_search_no_match"] = "No matching contacts";
strings_["address_book_confirm_delete"] = "Confirm delete?";
strings_["mining"] = "Mining";
strings_["peers"] = "Peers";
strings_["market"] = "Market";