Chart State
- Stable
- WCAG 2.2 evidence
- RTL
What a chart shows instead of its plot while it loads, when there is nothing to plot, or when loading failed. Presentational: renders in React
Server Components; the action slot takes a client component such as Button. Accessibility: the state is a live region, role="status" for loading and empty (polite) and role="alert" for an error
(assertive), so it is announced once when it appears (WCAG 4.1.3). Render it when the state begins, or keep it mounted and
change status; a state already on the page at load is not announced. Meaning is never colour alone: the loading card is
announced as text, the empty and error states have a heading-sized title and an icon (a chart glyph, or a warning circle
with the danger tint) (1.4.1, 1.1.1). The skeleton pulses only without a reduced-motion preference (2.3.3, 2.2.2: it is a
loading indicator that ends when the data arrives). The retry or clear action is a normal button in tab order (2.1.1).
Pass role="status" to soften an error that is not urgent. Consumer duties: the wording ("say what happened and what to do next"), the urgency (an error that appears in many charts
at once should not each interrupt the user), and moving focus sensibly after a retry.
import { ChartState } from "@nexera-ui/react";- 6
- examples
- 5
- props
- 4
- live controls
- 1
- platform
- 10
- WCAG criteria
- 1
- block uses 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 { ChartState } from "@nexera-ui/react";
<ChartState />Examples 5
The same examples as Storybook, rendered live. Open Code to copy one.
Empty
Chart/State/Empty: there is nothing to plot for these filters. Say what happened and what to do next.
import { Button, ChartState } from "@nexera-ui/react";
<ChartState
status="empty"
title="No hires in this period"
description="Try a longer period or clear the department filter."
action={
<Button variant="secondary" size="sm">
Clear filter
</Button>
}
/>;
Error state
Chart/State/Error: loading failed. An assertive alert with a retry action.
import { Button, ChartState } from "@nexera-ui/react";
const retry = (
<Button variant="secondary" size="sm">
Try again
</Button>
);
<ChartState
status="error"
title="Couldn't load attendance"
description="Check your connection and try again. Your filters are kept."
action={retry}
/>;
In chart frame
Inside a ChartFrame (isEmbedded): the frame keeps its card, title, legend and actions, the state replaces only the plot, without a second card.
import { ChartState, LegendItem } from "@nexera-ui/react";
const statuses = ["loading", "empty", "error"] as const satisfies readonly ChartStateStatus[];
export function InChartFrame() {
return (
<div className="flex flex-col gap-6">
{statuses.map((status) => (
<ChartFrame
key={status}
title="Attendance"
description="Last 30 days"
legend={[<LegendItem key="a" seriesIndex={0} shape="line" label="Present" />]}
>
<ChartState
isEmbedded
status={status}
title={
status === "empty"
? "No attendance in this period"
: status === "error"
? "Couldn't load attendance"
: undefined
}
description={status === "loading" ? undefined : "Try again in a moment."}
action={status === "error" ? retry : undefined}
/>
</ChartFrame>
))}
</div>
);
}
Long content
Long titles and descriptions wrap inside the card (translation adds 30 to 40 %); nothing is truncated.
import { Button, ChartState } from "@nexera-ui/react";
const retry = (
<Button variant="secondary" size="sm">
Try again
</Button>
);
<div className="max-w-xs">
<ChartState
status="error"
title="Couldn't load the attendance and overtime report for the Lisbon and Porto offices"
description="Check your connection and try again. If the problem continues, ask an administrator to check that you can see both locations."
action={retry}
/>
</div>;
Right to left
Right-to-left: the content stays centred; the card and the action mirror with the page.
import { Button, ChartState } from "@nexera-ui/react";
<ChartState
status="error"
title="تعذر تحميل بيانات الحضور"
description="تحقق من اتصالك وحاول مرة أخرى. تم الاحتفاظ بالمرشحات."
action={
<Button variant="secondary" size="sm">
أعد المحاولة
</Button>
}
/>;
Props 5
Press "Try it" on a card to load that prop into the playground.
5 props shown
status*Nexera"loading" | "empty" | "error"Which state to show: loading, empty (Chart/State/Empty,
the query succeeded but there is nothing to plot) or error (Chart/State/Error, the data could not be loaded).
Figma has three separate components and no property; this one prop merges them. A loading state is announced politely
(role="status"), an empty one too, an error assertively (role="alert").
titleNexeraReactNodeWhat happened. Say what happened, in words of the user's task. For loading it is not drawn: it is the text announced
to assistive technology. Wraps, never truncated. Translate the defaults.
descriptionNexeraReactNodeWhat to do next. Shown when provided, for
empty and error only.
actionNexeraReactNodeAction under the text: the retry button of an error
(<Button variant="secondary" size="sm" onPress={refetch}>Try again</Button>), or "Clear filters" for an empty chart.
Shown when provided, for empty and error only. Not drawn for loading.
isEmbeddedNexerabooleanDraw the state without its own card (no border, fill, radius or side padding, and for loading only the plot skeleton,
not the header skeleton). Use it inside a ChartFrame, whose card and header are still there. Figma draws the states as
stand-alone cards, so the default is the card.
* 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 · 4 supporting- 1.1.1Non-text ContentLevel A · tested directly
- 1.3.1Info and RelationshipsLevel A · tested directly
- 1.3.2Meaningful SequenceLevel A · supporting test
- 1.4.1Use of ColorLevel A · tested directly
- 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
- 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:.
<ChartState className="shadow-sm" />Used in blocks
Related components
- AccordionItemOne collapsible section of an FAQ or settings page.
- AreaChartA stacked area chart: layers piled up over time with the title, range switch, actions and legend of the card.
- AvailabilityRowOne person's availability across a window of the day: an avatar with initials and the name, and a timeline with the busy periods drawn as bars.
- AvatarA person or organisation shown as a photo, initials or an icon.
- AvatarGroupA row of overlapping avatars with a "+N" chip for the rest.
- AvatarLabelAn avatar with a name and an optional subtitle beside it, for a person in a list, a header or a mention.
- BadgeShort status or category label: `Tone` x `Variant` x `Size`, with an optional dot, leading icon and remove button.
- BadgeGroupA pill that pairs a small badge with a short message, for an announcement or a status line.