Skip to content

fix: show the X in the mail search field once it has focus, and let it close the search #127 - #136

Merged
rathlinus merged 2 commits into
bulwarkmail:mainfrom
wmcparla:fix/search-cancel-127
Nov 15, 2026
Merged

rathlinus merged 2 commits into
bulwarkmail:mainfrom
wmcparla:fix/search-cancel-127

Conversation

@wmcparla

@wmcparla wmcparla commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Summary

#127: tapping the mail list's search field opens a panel ("Search everything", recent searches) over the list, and the only control to leave it was the X in the field, which showed only once something was typed and only cleared the text. On Android the back button closes it, but iOS has none, so an empty, focused field could only be left by tapping elsewhere. This shows the X as soon as the field has focus: with text in it, it clears the text and keeps the keyboard up, as before; on an empty field it closes the field, the keyboard and the panel.

Changes

  • EmailListScreen.tsx: the X shows while the field has focus as well as while it holds text, and calls clearOrCloseSearch, which clears typed text, or on an empty field drops the focus state and blurs the input. Its accessibility label follows what it does: "Clear search" with text, "Close" (common.close) on an empty field (Warden's point below).
  • search-close-wiring.test.ts: checks that wiring, the label included.

Related issues

Closes #127

Type of change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Refactor / code quality improvement
  • Chore / dependency update / CI change

Checklist

  • I have read the Contributing Guide
  • My code follows the project's code style and conventions
  • I have run npm run typecheck and there are no errors (native has no lint script)
  • The build passes (no npm run build in native; an x86_64 release APK, assembleGithubRelease -PallowDebugSignedRelease=true, builds and runs)
  • I have tested my changes locally
  • I have added or updated documentation if needed (none needed)
  • I have updated translations (locales/) if my changes affect user-facing text (no new text: the labels are the existing contacts.clear_search and common.close, both in every locale; npm run i18n:check passes)
  • I have included screenshots or a screen recording for UI changes

Tests: npx vitest run: 7105 passed, 163 skipped (the live Stalwart suites), 0 failed.

Tested by hand on the Android 16 emulator (1080x2424, 420 dpi), upstream b3b4230 against this branch, never pressing Android's back (to stand in for iOS), reading the view hierarchy and the keyboard state after each step:

Step Before After
Tap the empty field keyboard and panel, no X keyboard and panel, X read out as "Close"
Tap the X field, keyboard and panel close
Type "Test", tap the X text cleared, keyboard stays, X gone X read out as "Clear search"; text cleared, keyboard stays, X stays as "Close"
Tap the X again field, keyboard and panel close
Submit "Seed", tap the X search cleared, list back the same

Not tested: iOS itself, a tablet (the header search bar goes through the same renderSearchBar).

Screenshots / demo

Empty field with focus, before after after tapping the X
Search panel open, no X in the field Search panel open, an X at the end of the field Mail list, no keyboard, no panel

Notes for reviewers

  • The X on an empty field leaves the filters alone, unlike Android's back, which clears the search and the filters (clearSearchAndFilters). The filters keep their own chips.
  • The unified views' search (UnifiedInboxScreen) has no panel under its field, so it has no such trap and is left as it is.

🤖 Generated with Claude Code

@wmcparla
wmcparla marked this pull request as ready for review November 13, 2026 20:41
@bulwark-warden

Copy link
Copy Markdown

The test check passes, and I found nothing blocking in the change.

One thing to consider: on an empty, focused field the X now closes the search, but it keeps the label from t('contacts.clear_search', 'Clear search'). VoiceOver and TalkBack users will hear "Clear search" on an empty field, and tapping it closes the field instead. I searched the repository for a close_search or cancel_search key and found none.

Bulwark Warden is an AI assistant and can be wrong. It answers from the docs, the code and earlier issues, and links its sources.

@rathlinus
rathlinus merged commit aa0bd85 into bulwarkmail:main Nov 15, 2026
1 check passed
@rathlinus

Copy link
Copy Markdown
Member

Thanks, merged. I loosened the label check in the test a bit; it failed on a checkout with CRLF line endings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: when opening search bar, there is no intuitive way to cancel

2 participants