Skeleton or progress
Use a skeleton for a known content layout. Use meaningful progress for a measurable operation.
Reserve space, explain progress, and make the next action clear.
Use for records, dashboards and detail views that load asynchronously. Distinguish a request in progress from an empty result or an operation that failed.
Select a state to see what the interface should communicate. These are illustrative snapshots; try the live component below.
The request region is busy.
Wait for the resultUse shapes that resemble the expected content. Mark the region busy and keep loading placeholders out of the reading order.
Try the working example ↓3 requests loaded
Replace the placeholders, clear the busy state and announce the result without moving focus unexpectedly.
Try the working example ↓Loading finished. There are no requests to display.
Create a requestExplain the empty state and offer the first useful action. Avoid an indefinite skeleton when the result is simply empty.
Try the working example ↓The service did not return a result. Your work is unchanged.
Try againShow an actionable error and retry. If refreshing existing data fails, consider keeping the last result visible with its age.
Try the working example ↓Choose Show content to replace the skeleton with the loaded workspace. Choose Show skeleton to return to the loading state. The state reference above also shows empty and failed outcomes.
Use a skeleton for a known content layout. Use meaningful progress for a measurable operation.
Keep a field error near the field and a loading state near its region. Use a notification for a result that needs broader attention.
Announce meaningful state changes. Avoid announcing every placeholder or each animation cycle.
The examples demonstrate interaction using sample data. Your application owns the real records, permissions and persistence.