feat(combobox): built-in error state for async dropdowns#389
Conversation
Combobox.Async, Autocomplete.Async, and Select.Async now render an inline error state (message + Retry) in the popover when the fetcher throws/rejects, instead of silently falling back to the misleading "No results." empty state. - Shared useAsyncItems hook gains retry() and an onFetchError option that fires once per outage; aborted/superseded requests are ignored centrally. - New AsyncErrorState component + resolveAsyncContent helper. - New props on each .Async component: errorText, retryText, onFetchError. - Select.useAsync (separate impl) gets matching retry/onFetchError plumbing. - Docs, tests, changeset, and an example in the nextjs demo app. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@copilot can you do a review of this PR and let me know if you find any gaps? |
…Error test Co-authored-by: erickteowarang <30395423+erickteowarang@users.noreply.github.com>
Overall the implementation is solid — the hook logic, per-component wiring, docs, and changeset all look consistent. I ran type-check, lint, and 1363 existing tests (all green). Here's what I found and fixed: Fixed (commit
Observations (no changes needed)
|
|
/review |
|
✅ API Design Review completed successfully! API design review complete for PR #389 — no issues to flag. All new public props (errorText, retryText, onFetchError) are optional with defaults; AsyncFetcher type union was pre-existing; return type additions (retry) are purely additive. Verdict: Approve. |
Summary
Implements a first-class error state for
Combobox.Async,Autocomplete.Async, andSelect.Async, closing tailor-inc/platform-planning#1491.Previously a failed fetch rendered identically to a successful empty fetch ("No results."), so users couldn't tell "nothing matches" from "the request failed" — and the documented contract pushed ~15 lines of fiddly toast/abort/de-dupe boilerplate onto every consumer.
Now, when a fetcher throws/rejects, the component renders an inline error state in the popover — "Couldn't load results." + a Retry button that re-runs the last fetch — instead of the misleading empty state. No consumer code required.
Screencaps
Combobox/Autocomplete
Select
What changed
useAsyncItemshook (Combobox + Autocomplete): addsretry()(re-runs the last query, no debounce) and anonFetchErroroption. The two sharp edges are handled centrally — aborted/superseded requests are ignored, andonFetchErrorfires once per outage (on entry into the error state, re-arming after the next success) so typing during an outage doesn't stack announcements.AsyncErrorStatecomponent +resolveAsyncContenthelper — the shared inline error UI (focus-preserving Retry click) and the loading→error→default content picker..Asynccomponent:errorText(default"Couldn't load results."),retryText(default"Retry"),onFetchError.Select.useAsyncis a separate implementation, so it got matchingretry/onFetchError/ once-per-outage plumbing.Partsconsumers (Combobox.useAsyncetc.) also gainerror+retryand acceptonFetchError.minor), and an "Error + retry" example added to each async card in the nextjs demo app.Testing
type-check,lint,fmt:checkclean across core + example.🤖 Generated with Claude Code