Documentation menu

AsyncState

A data-library-agnostic boundary that makes loading, recovery, empty, offline, permission, and background-refresh behavior explicit.

Loading preview…

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.json

Basic usage

import { AsyncState } from "@/components/async-state"

<AsyncState
  status={status}
  errorValue={error}
  onRetry={refetch}
>
  <UserList users={users} />
</AsyncState>

API reference

PropPurposeDefault
statusThe active asynchronous state.Required
childrenSuccessful or idle content.Required
loading, emptyCustom loading and empty views.Built-in views
errorA node or renderer receiving errorValue.Built-in error
offline, forbiddenCustom connection and permission views.Built-in views
onRetrySynchronous or asynchronous recovery callback.None
preserveContentWhileRefreshingKeeps 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