Loading states
The three states of the loading prop (skeleton viewport, slim indeterminate bar, and the ordinary empty state).
One prop, loading, plus whether rows exist, covers all three states. The demo's two switches
(loading, rows present) reach each one live.
Toggle both switches: Loading with no rows shows a viewport-filling skeleton, Loading with rows present shows a slim bar under the header instead, and rows-off + loading-off is the ordinary empty state.
pnpm dlx shadcn@latest add @gridcn/data-grid-loading-demo
| Rows | loading | What renders |
|---|---|---|
| none | true | A viewport-filling skeleton: pulsing rows in place of the empty grid. |
| present | true | A slim indeterminate bar under the header while the existing rows stay on screen. |
| none | false | The ordinary empty state (the labels.grid.emptyState string). |
Where the data comes from
loading only controls rendering. Pass it from whatever owns your request
state (isPending from React Query, isLoading from SWR, your own flag). The data-fetching
patterns it pairs with are on the
Data & Integrations pages.
Customizing the look
loadingState replaces the skeleton (zero rows) or the indeterminate bar (rows present) while
loading is true. It accepts a plain node or a function receiving { reason }: "no-data"
or "rows-present". The replacement renders directly under the header at full width, and the
node owns its own accessibility.
emptyState takes the same two forms. Its reason is "no-data" when the data array is empty
and "filtered" when rows exist but none are in view.
Related
- Lazy loading: skeleton rows for per-range fetching instead of
the grid-level
loadingprop - Styling: theming the skeleton via shadcn tokens