StateLine
One centred line with a glyph in front of it, drawn wherever a data widget has no rows to show.
Install
Section titled “Install”pnpm dlx shadcn@latest add https://sg-widgets.vercel.app/r/react/state-line.jsonpnpm dlx shadcn-svelte@latest add https://sg-widgets.vercel.app/r/svelte/state-line.jsonReact
Loading the React demo…
Svelte
Loading the Svelte demo…
The three states
Section titled “The three states”A data widget shows one of three things in place of its rows.
A read that returned nothing is the empty line, muted. A read that failed is the error line, in the destructive tone. A read in flight is neither: it is skeletons shaped like the rows they stand in for, so a list holds its place when the data lands. That shape belongs to the widget that knows it, so this line covers the other two.
The label is the caller’s. Core settles the defaults, and an error falls back to what the read said and then to a fixed line, so a failure is never a blank block. The line truncates and carries the whole label as its title.
Anything passed after the line sits beside it, which is where a failed page puts its retry control.
The root carries the state as a data attribute, and the data-slot name the widget gives it, so one
widget’s empty line is addressable on its own.
Padding
Section titled “Padding”pad is the room the line takes.
popover is the inset of a popup list, table the inset of a table or a grid body, and none is
for a line under rows already drawn, where the block around it owns the inset. The three match
design rule 5, so every widget on a page leaves the same room around the same line.
The live region beside it
Section titled “The live region beside it”A popup list carries a live region of its own, saying what the list is doing: the read in flight, the count it answered, the empty line, or what a failed read said. That is what a reader hears, and this line is what a reader sees. The two are never the same element (design rule 9), so a screen reader is told about a list that answered as well as one that did not.
| prop | type | default | meaning |
|---|---|---|---|
state | 'empty' | 'error' | required | Which state this is. An error is destructive, an empty state muted. |
label | string | required | The line to show. It truncates, and carries itself as a title. |
icon | LucideIcon | null / Component | LucideIcon | null | null | The glyph in front of the line, drawn at size-4. |
pad | 'popover' | 'table' | 'none' | 'popover' | The room around the line: py-6 in a popup list, py-10 in a body, and none under rows already drawn. |
slotName | string | 'state-line' | The data-slot this block carries. |
Events
Section titled “Events”None.
None.
Keyboard
Section titled “Keyboard”Not focusable. The live region beside it is what a screen reader hears.
Where it is drawn
Section titled “Where it is drawn”Every widget in this registry that reads rows draws this line: the popup of a picker and of a search, the body of a table and of a grid, a tree, a grouped list, a card, and the field and column pickers. A widget passes its own label, its own glyph and the padding its surface asks for, and nothing else changes between them.