Use this skill when you need add appropriate user feedback states (loading, success, error, empty) to a component or page.
/ss-copy
/ss-a11y
/ss-component
Target: $ARGUMENTS
Read the target file and identify all data-dependent areas.
Read the design language reference:
DESIGN-LANGUAGE.md sections on Loading States (Skeleton), Empty States, Error StatesFor each data-dependent area, implement ALL 4 states:
// Skeleton must match the final layout shape
<div className="bg-card rounded-2xl p-6 shadow-[var(--shadow-card)]">
<div className="flex items-center gap-2 mb-3">
<div className="size-7 bg-surface-muted rounded-lg animate-pulse" />
<div className="h-3 w-16 bg-surface-muted rounded animate-pulse" />
</div>
<div className="h-9 w-24 bg-surface-muted rounded-lg animate-pulse mb-3" />
<div className="h-3 w-12 bg-surface-muted rounded animate-pulse" />
</div>
Rules:
animate-pulse (1.5s cycle)<EmptyState
icon={PackageIcon}
title="No activity yet"
description="Create your first project to get started."
action={<Button>Create Project</Button>}
/>
Rules:
text-text-tertiary
text-text-secondary
<div className="flex flex-col items-center justify-center py-8 text-center">
<AlertCircle className="size-8 text-destructive mb-3" />
<p className="text-[14px] text-text-secondary mb-4">Couldn't load the data</p>
<Button variant="brandGhost" size="sm" onClick={retry}>Try again</Button>
</div>
Rules:
// Toast notification for action confirmations
toast("Changes saved")
// With undo for destructive actions
toast("Item deleted", { action: { label: "Undo", onClick: handleUndo } })
Rules:
function DataCard({ data, isLoading, error }) {
if (isLoading) return <DataCardSkeleton />
if (error) return <DataCardError onRetry={refetch} />
if (!data || data.length === 0) return <DataCardEmpty />
return <DataCardContent data={data} />
}
prefers-reduced-motion — disable animate-pulse when reduced motion is preferred.