feat(desktop): searchable timezone picker in Settings → Chat (salvage #68969) - #73505
Merged
Conversation
The timezone field was a free-text input with no guidance on format. Users had to know the exact IANA identifier (e.g. America/New_York) to configure it. Replace it with a searchable combobox built on Popover + cmdk Command — the same stack as Shadcn's Combobox. Backend: - Add `_timezone_options()` to web_server.py (cached at import time, returns sorted zoneinfo.available_timezones() — ~598 identifiers) - Add `"timezone"` to `_SCHEMA_OVERRIDES` with `type: "select"`, `options`, and `searchable: true` Frontend: - New `SearchableSelect` component (Popover + cmdk Command) — closed-world filterable dropdown for large option lists - `ConfigField` routes to `SearchableSelect` when `schema.searchable === true` (explicit opt-in, no threshold) - Add `searchable?: boolean` to `ConfigFieldSchema` type - Add i18n keys: `searchPlaceholder`, `noResults` The `searchable` flag is deterministic — no existing field is affected unless explicitly opted in. Future large-list fields can adopt the same pattern by adding `searchable: true` to their schema override.
- Fix focus: use autoFocus on CommandInput instead of e.preventDefault() - Fix filter: prioritize city segment match (return 2 for slash match) - Fix handleSelect: always select, don't toggle-deselect - Add aria-haspopup to trigger button - Use defensive placeholder logic
…, UTC fallback - Add 'System default' clear option to SearchableSelect via clearLabel prop - Add clearable flag to ConfigFieldSchema (schema-driven, not hardcoded) - Add clearable: true to timezone schema override in web_server.py - Fix CommandItem value for clear item: use clearLabel instead of '' so cmdk can match it during search - Fix backend: or ['UTC'] fallback for hosts without tzdata where available_timezones() returns an empty set (not an exception) - Add systemDefault i18n key (en, types, zh)
- Extract the cmdk filter into exported rankSearchOption and cover it, SearchableSelect selection/clear/placeholder, and ConfigField searchable-schema routing with 12 vitest cases (sabotage-verified: the backend schema test fails on unfixed main). - Add searchPlaceholder/noResults/systemDefault strings to ja/ar/zh-hant (zh + en came with the salvaged commits; defineLocale would have fallen back to English otherwise). - Add a backend invariant test: timezone ships as a searchable, clearable select of sorted IANA ids with a UTC fallback.
Contributor
૮ >ﻌ< ა ci reviewran on 8b11503 ℹ️ InfoDesktop E2E visual evidence · View test artifacts · View job1 visual diff. inline evidence is publishing... |
8 tasks
Contributor
|
Thanks for salvaging this! I've closed #68969 as superseded by this PR. |
This was referenced Jul 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Desktop Settings → Chat → Timezone is now a searchable, validated IANA timezone picker instead of a free-text input that accepted any string. Salvages PR #68969 by @DavidMetcalfe onto current main with authorship preserved, plus follow-up tests and locale coverage. Closes #68970.
Root cause of the report ("I can type anything in it"):
timezonehad no schema override, soConfigFieldfell through to the generic free-text<Input>branch — the backend fails safe on invalid values (falls back to server-local with a log warning), but the UI validated nothing.Changes
hermes_cli/web_server.py:timezoneschema override —selectwith sortedzoneinfo.available_timezones()(UTC fallback), new genericsearchable+clearableschema flags.apps/desktop/.../searchable-select.tsx: newSearchableSelect(Popover + cmdk) with segment-ranked filtering ("york" →America/New_York) and a "System default" clear item; filter extracted to exportedrankSearchOption.apps/desktop/.../config-field.tsx: routesschema.searchable === truetoSearchableSelect.searchPlaceholder/noResults/systemDefaultin en + zh (contributor) and ja + ar + zh-hant (follow-up).ConfigFieldrouting) + backend invariant test intests/hermes_cli/test_web_server.py(sabotage-verified: fails on unfixed main).Validation
searchable-select.test.tsxpytest test_web_server.py -k timezone/Schemanpm run typecheck, eslint, prettierCredit
Original implementation by @DavidMetcalfe (#68969), cherry-picked with authorship preserved. Supersedes #38607 by @CyrisXD — the earlier attempt at the same feature.
Infographic