AppSkeleton
The first-load shimmer that holds a component's shape while its data is still arriving.
<app-skeleton width="60%" />A skeleton is a grey shimmer shaped like the content that is loading — a line of text, a table row, a card. It reserves the layout so nothing jumps when the real data lands. <app-skeleton> is a single bar; stack a few in a table cell to sketch a loading row.
Its look comes entirely from the shared @webority/theme, so the Razor <app-skeleton> and the React <AppSkeleton> shimmer identically — the same placeholder on every Webority surface.
Playground
Every attribute, live. Each change re-renders the real tag helper on the server, so the markup underneath is the exact call that produced the bar above it.
Placeholder bars
Each bar takes a width and a height so it can mimic a heading, a paragraph line, or a chip. Stack a few to sketch the shape of the content underneath.
Show code
<app-skeleton width="80%" height="16px"></app-skeleton> <app-skeleton width="100%" height="12px"></app-skeleton> <app-skeleton width="60%" height="12px"></app-skeleton>
Table rows
Fill a table body with placeholder cells while the first page of data loads — one bar per cell, same column count as the real table, so the layout is stable before and after load.
Show code
<table class="table table-ledger">
<tbody>
<tr>
<td><app-skeleton width="70%" height="12px" /></td>
<td><app-skeleton width="50%" height="12px" /></td>
<td><app-skeleton width="50%" height="12px" /></td>
<td><app-skeleton width="50%" height="12px" /></td>
</tr>
</tbody>
</table>
When to use
Use it when
- A component is loading its first data — the classic loading && data.length === 0 case.
- You want the page layout to hold its shape so content doesn't jump on arrival.
- A table or list is fetching its first page and you want per-row placeholders.
Reach for something else when
- The data loaded but the result set is empty. → AppEmptyState
- A table query returned no rows. → AppTableEmptyState
- A short, indeterminate action is running (a button submit). → AppButton loading
- The whole page is blocked on a single request. → a page-level spinner
Best practices
Every option
The whole surface of the tag helper, one cell per value — width, height, radius, class/style passthrough, and hand-authored row/column counts (Razor has no AppSkeletonRows equivalent).
width
width="100%"
width="50%"
width="200px"
width="2rem"
height
height="8"
height="14"
height="24"
height="2rem"
radius
radius="0"
radius="6"
radius="12"
radius="50%"
class and style passthrough
class="kpi-skel" — appended to the base skeleton classstyle="margin-top:8px" — merged with the computed width/height/radiusstyle="width:300px" — an authored style wins over the width attributetable skeleton rows — rows × cols
2 rows × 3 cols
1 row × 1 col
AppSkeletonRows loops rows/cols into <tr>/<td> for you; Razor has no equivalent tag helper, so hand-author one <app-skeleton> per <td>, as shown here and in "Table rows" above.Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
| width | string | 100% | Bar width — any CSS length (e.g. "80%", "120px"). A bare number is not auto-converted to px — pass a full CSS length. |
| height | string | 14px | Bar height — any CSS length. A bare number (e.g. "12") is treated as px, matching React's numeric height prop. |
| radius | string | 6px | Corner radius (React radius). A bare number is treated as px, matching React's numeric radius prop. |
There is no Razor tag helper for a whole placeholder row — hand-author one <app-skeleton> per <td>, as shown above. React's AppSkeletonRows takes rows (default 4) and cols (default 5).