Componentsv2.189.0
Iconsv1.19.0
MCPv0.8.61
Tokensv0.34.3

States

Guidelines for every state a screen can be across Customer.io interfaces.


Loading

Use SkeletonShape and SkeletonText as the default loading pattern. Use Spinner for inline actions. Use PageLoader for full-page transitions.

  • Skeleton shape should match the eventual content.
  • Add a brief delay before showing skeletons to avoid flicker on fast connections.
  • For long-running operations, show a progress indicator or status message, not just animation.
  • For progressive loading, render sections as they resolve.

Empty: First Use

The person has never used this feature and has no data yet. Use EmptyState with a single primary CTA.

table
VariantWhen to use
defaultBasic functionality. Lead with the noun ("No segments yet") and an action-oriented CTA ("Create your first segment").
promotionFeature discovery. Designed for highlighting features or capabilities, featuring a more prominent layout with the graphic at the bottom. The title can include an eyebrow badge for additional emphasis.

Empty: No Results

The person had data, but a search or filter returned nothing. Use EmptyState.

  • Acknowledge the search: "No segments match your filters".
  • CTA suggests adjusting: "Clear filters" or "Try a different search".
  • Never leave blank or vague: "Nothing to show".

Partial

Some data loaded successfully, some didn't. Or a bulk operation partially completed.

  • Lead with what succeeded: "8,556 of 12,403 rows imported".
  • Then name the gap and the recovery action.
  • Use Banner with the caution variant to surface partial failures alongside the successfully loaded content.

Error

Something failed. The approach depends on where the failure happened. Always provide a recovery path when one exists. For copy guidance, see Content — Errors and system feedback.

table
ScopeComponentExample
Page failed to loadBannerFull-page error with retry action
Action failedSnackbar with the error variant"Campaign couldn't be saved" with recovery path
Field validationInline error on the form control"Enter a valid email address"

Success

Confirm what happened, then get out of the way. For copy guidance, see Content — Success messages.

table
PatternWhen to use
Snackbar with the success variantEphemeral confirmations (3s auto-dismiss)
Inline checkmarkIn-place edits

Disabled

An action exists but can't be taken right now.

  • Use the isDisabled prop on the component (Button, TextField, Select, etc.).
  • Always pair with an explanation. Use a Tooltip or helper text to describe why it's disabled and what would enable it.
  • Don't hide the action. Showing a disabled control with an explanation is more useful than hiding it entirely.

Permission-denied

The feature exists but the person's role doesn't allow access.

  • Show the feature disabled with a Tooltip naming the specific permission required.
  • Don't hide the feature. Make the path to access discoverable.

Offline

The network connection is unavailable or unreliable.

  • Show the last-known data with a Snackbar indicating the data may be stale.
  • Disable actions that require a connection and explain why.
  • When the connection returns, refresh automatically and dismiss the banner.

Other

One item

The first item has been added. The screen is no longer empty but may look sparse.

  • Ensure the layout doesn't break with a single row or card.
  • Consider whether this is a milestone worth a brief success moment (first campaign, first segment).

Overflow

More data than the screen can show at once.

  • Use Pagination for discrete pages of results.
  • Use Truncated for text that doesn't fit.
  • For counts, use "and X more" patterns rather than hiding the overflow silently.