AsyncState
A data-library-agnostic boundary that makes loading, recovery, empty, offline, permission, and background-refresh behavior explicit.
Installation
The CLI copies editable source into your project. Elsecase does not add a proprietary runtime package.
pnpm dlx shadcn@latest add https://elsecase.vercel.app/r/async-state.jsonBasic usage
import { AsyncState } from "@/components/async-state"
<AsyncState
status={status}
errorValue={error}
onRetry={refetch}
>
<UserList users={users} />
</AsyncState>API reference
| Prop | Purpose | Default |
|---|---|---|
status | The active asynchronous state. | Required |
children | Successful or idle content. | Required |
loading, empty | Custom loading and empty views. | Built-in views |
error | A node or renderer receiving errorValue. | Built-in error |
offline, forbidden | Custom connection and permission views. | Built-in views |
onRetry | Synchronous or asynchronous recovery callback. | None |
preserveContentWhileRefreshing | Keeps stale successful content mounted during refresh. | true |
States and edge cases
The simulator covers initial and slow loading, success, empty results, failed requests, retry success or failure, offline and forbidden views, stale-content refreshes, narrow viewports, and extreme content length. Its query string makes each configuration shareable.
Accessibility behavior
Loading and refreshing use polite live regions and aria-busy. Errors, offline states, and permission failures use assertive alerts. Decorative skeletons are hidden from assistive technology, and retry is natively disabled while its promise is pending.
Responsive behavior
AsyncState does not impose a content width. Its defaults work at 320px, and preserved content remains controlled by the consumer layout.
Testing example
render(<AsyncState status="error" onRetry={retry}>Content</AsyncState>)
fireEvent.click(screen.getByRole("button", { name: "Try again" }))
expect(retry).toHaveBeenCalledOnce()Customization
<AsyncState
status="empty"
empty={<EmptySearchResults clearFilters={clearFilters} />}
>
<Results />
</AsyncState>Dependencies
React only. Default styling uses semantic Tailwind tokens created by shadcn initialization; there is no runtime dependency on Elsecase.
Known limitations
AsyncState does not fetch data, classify network errors, or manage cache state. Consumers map their data library’s state into the status union.
Source
Review the implementation in the public GitHub repository:
github.com/heysinghaaa/Elsecase/tree/main/registry/async-state