Feed Status
- Stable
- WCAG 2.2 evidence
- RTL
The status line at the bottom of an infinite feed or a lazy list: "Loading more", "You have reached
the end" or "Could not load more" with a retry action. A polite status region (role="status") whose text is announced
when it changes (WCAG 4.1.3); the state is text with an icon, and the error colour is never the only cue (1.4.1). The
spinner is decorative and stops under reduced motion (2.3.3). Presentational: renders in React Server Components; the
retry button is a small client island. Consumer duties: render it for the whole life of the feed and change status, because a live region only announces
changes to a region that is already in the page; set aria-busy="true" on your list while it loads (this component does
not know your list); show loading only after about 300 ms to avoid flicker; and manage focus when items are appended
or Retry succeeds. Use Pagination for paged tables and CursorPager for logs.
import { FeedStatus } from "@nexera-ui/react";- 8
- examples
- 5
- props
- 2
- live controls
- 1
- platform
- 12
- WCAG criteria
- 3
- blocks use it
Try every prop. Copy the code.
Change the props and the code updates. Check light and dark, LTR and RTL, and phone width.
import { FeedStatus } from "@nexera-ui/react";
<FeedStatus />Examples 7
The same examples as Storybook, rendered live. Open Code to copy one.
End
Figma State=End: a check and the closing line; add what was loaded.
import { FeedStatus } from "@nexera-ui/react";
<FeedStatus status="end">You have reached the end · 128 employees</FeedStatus>;
Error with retry
Figma State=Error: an alert icon, the message in the danger colour and the Retry button.
import { FeedStatus } from "@nexera-ui/react";
<FeedStatus status="error" onRetry={() => undefined} />;
Cycle
The feed cycle in one place: the region stays mounted while the status changes, so each change is announced.
import { useState } from "react";
import { FeedStatus } from "@nexera-ui/react";
export function Cycle() {
function Feed() {
const [status, setStatus] = useState<FeedStatusState>("loading");
return (
<div className="flex max-w-md flex-col gap-3">
<FeedStatus
status={status}
onRetry={() => {
setStatus("loading");
}}
>
{status === "end" ? "You have reached the end · 128 employees" : undefined}
</FeedStatus>
<div className="flex flex-wrap gap-2">
{(["loading", "end", "error"] as const).map((next) => (
<button
key={next}
type="button"
className="rounded-md border border-input-border bg-surface px-3 py-1 text-body-small text-primary"
onClick={() => {
setStatus(next);
}}
>
{next}
</button>
))}
</div>
</div>
);
}
return <Feed />;
}
Custom action
A custom next step instead of the retry button.
import { FeedStatus } from "@nexera-ui/react";
<FeedStatus
status="error"
action={
<a href="#status" className="text-body-strong text-brand-text">
Open status page
</a>
}
>
Could not load more. The service is unavailable.
</FeedStatus>;
Narrow width
A 320 px column: the message wraps and Retry drops below it.
import { FeedStatus } from "@nexera-ui/react";
export function NarrowWidth() {
return (
<div className="max-w-xs">
<FeedStatus status="error" onRetry={() => undefined}>
Could not load more employees. Check your connection and try again.
</FeedStatus>
</div>
);
}
Long labels
Long translated texts wrap and are never truncated.
import { FeedStatus } from "@nexera-ui/react";
export function LongLabels() {
return (
<div className="flex max-w-sm flex-col">
<FeedStatus status="loading">
Weitere Mitarbeitende aus allen Standorten werden geladen
</FeedStatus>
<FeedStatus status="error" onRetry={() => undefined} retryLabel="Erneut versuchen">
Weitere Mitarbeitende konnten nicht geladen werden
</FeedStatus>
</div>
);
}
Right to left
Right to left: the spinner or icon starts at the right of the message.
import { FeedStatus } from "@nexera-ui/react";
export function RightToLeft() {
return (
<div className="flex max-w-md flex-col">
<FeedStatus status="loading">جارٍ تحميل المزيد</FeedStatus>
<FeedStatus status="end">وصلت إلى النهاية · ١٢٨ موظفًا</FeedStatus>
<FeedStatus status="error" onRetry={() => undefined} retryLabel="إعادة المحاولة">
تعذّر تحميل المزيد
</FeedStatus>
</div>
);
}
Props 5
Press "Try it" on a card to load that prop into the playground.
5 props shown
statusNexera"loading" | "end" | "error"What the feed is doing. The Figma property is a visual state; it is named status
here because it is semantic: loading shows a spinner, end a check and error an alert icon with the retry action.
childrenNexeraReactNodeThe message. Say what happened and what to do next. For end you can add what was loaded:
"You have reached the end · 128 employees". It wraps and is never truncated. Translate the defaults.
onRetryNexera() => voiderror only: called when Retry is pressed. Shows the Figma Retry button. Accepts a Server Action. Retrying usually
replaces this message with the loading state, so the button disappears: move keyboard focus to the new items when
they arrive.
retryLabelNexerastringVisible text and name of the retry button. Translate it.
actionNexeraReactNodeerror only: your own next step instead of the retry button, for example a link to the status page. It replaces
onRetry's button.
* Required. React Aria props shown are the ones most apps use; the component accepts the rest of its React Aria props too.
Accessible by default.
Built on React Aria, and covered by the WCAG 2.2 evidence generated on every build.
WCAG 2.2 evidence
6 direct · 6 supporting- 1.1.1Non-text ContentLevel A · tested directly
- 1.3.1Info and RelationshipsLevel A · tested directly
- 1.4.1Use of ColorLevel A · supporting test
- 1.4.3Contrast (Minimum)Level AA · supporting test
- 1.4.10ReflowLevel AA · supporting test
- 1.4.12Text SpacingLevel AA · supporting test
- 2.1.1KeyboardLevel A · tested directly
- 2.3.3Animation from InteractionsLevel AAA · supporting test
- 2.4.7Focus VisibleLevel AA · tested directly
- 2.5.8Target Size (Minimum)Level AA · supporting test
- 4.1.2Name, Role, ValueLevel A · tested directly
- 4.1.3Status MessagesLevel AA · tested directly
Fits any width.
Nexera components respond to the space they are given. Drag the corner of the frame, or pick a width.
Styling hooks
Pass className to add Tailwind classes (merged last). State is exposed as data attributes, so you can style it with variants like data-pressed:.
data-disableddata-hovereddata-pressed
<FeedStatus className="data-disabled:opacity-90 shadow-sm" />Used in blocks
- Live status boardDashboards and analytics
- Activity feedLists, tables and records
- Pull to refresh feedMobile patterns
Related components
- BreadcrumbShows where the current page sits in the hierarchy and links back to each level.
- BreadcrumbItemOne level of a `Breadcrumb` trail; use it only inside `Breadcrumb`.
- CursorPagerA previous and next pair for data without stable page numbers, such as an activity log or a cursor API.
- FABThe main action of a mobile screen: a floating button with a `nav/active-bg` fill and a large shadow.
- JumpToPageA small "Go to page [48] of 120" control for long paged lists.
- NavigationBarThe bottom bar of a mobile layout: a named `nav` landmark with a list of three to five `NavItem`s.
- NavItemOne destination or action of a `NavigationBar`.
- PageButtonOne page number of a `Pagination` or `TableFooter`.