$npx -y skills add bitjaru/styleseed --skill ss-feedbackAdd appropriate user feedback states (loading, success, error, empty) to a component or page
| 1 | # UX Feedback States Generator |
| 2 | |
| 3 | ## When NOT to use |
| 4 | |
| 5 | - For only the words inside a state → use `/ss-copy` |
| 6 | - For accessibility issues in existing states → use `/ss-a11y` |
| 7 | - For brand-new component creation → use `/ss-component` |
| 8 | - For analytics or error-logging plumbing — UI presentation only |
| 9 | |
| 10 | Target: **$ARGUMENTS** |
| 11 | |
| 12 | ## Instructions |
| 13 | |
| 14 | 1. Read the target file and identify all data-dependent areas. |
| 15 | |
| 16 | 2. Read the design language reference: |
| 17 | - `DESIGN-LANGUAGE.md` sections on Loading States (Skeleton), Empty States, Error States |
| 18 | |
| 19 | 3. For each data-dependent area, implement ALL 4 states: |
| 20 | |
| 21 | ### State 1: Loading (Skeleton) |
| 22 | ```tsx |
| 23 | // Skeleton must match the final layout shape |
| 24 | <div className="bg-card rounded-2xl p-6 shadow-[var(--shadow-card)]"> |
| 25 | <div className="flex items-center gap-2 mb-3"> |
| 26 | <div className="size-7 bg-surface-muted rounded-lg animate-pulse" /> |
| 27 | <div className="h-3 w-16 bg-surface-muted rounded animate-pulse" /> |
| 28 | </div> |
| 29 | <div className="h-9 w-24 bg-surface-muted rounded-lg animate-pulse mb-3" /> |
| 30 | <div className="h-3 w-12 bg-surface-muted rounded animate-pulse" /> |
| 31 | </div> |
| 32 | ``` |
| 33 | Rules: |
| 34 | - Show skeleton for 300ms minimum (prevent flash) |
| 35 | - Delay skeleton display by 300ms (fast loads skip skeleton entirely) |
| 36 | - Use `animate-pulse` (1.5s cycle) |
| 37 | - Match skeleton shapes to real content dimensions |
| 38 | - Never use spinners inside cards |
| 39 | |
| 40 | ### State 2: Empty (Zero Data) |
| 41 | ```tsx |
| 42 | <EmptyState |
| 43 | icon={PackageIcon} |
| 44 | title="No activity yet" |
| 45 | description="Create your first project to get started." |
| 46 | action={<Button>Create Project</Button>} |
| 47 | /> |
| 48 | ``` |
| 49 | Rules: |
| 50 | - Center-aligned in the card |
| 51 | - Icon: 32px, `text-text-tertiary` |
| 52 | - Title: 14px, `text-text-secondary` |
| 53 | - Always suggest a next action |
| 54 | - Zero values show as "0" (don't hide or dash) |
| 55 | |
| 56 | ### State 3: Error (Load Failed) |
| 57 | ```tsx |
| 58 | <div className="flex flex-col items-center justify-center py-8 text-center"> |
| 59 | <AlertCircle className="size-8 text-destructive mb-3" /> |
| 60 | <p className="text-[14px] text-text-secondary mb-4">Couldn't load the data</p> |
| 61 | <Button variant="brandGhost" size="sm" onClick={retry}>Try again</Button> |
| 62 | </div> |
| 63 | ``` |
| 64 | Rules: |
| 65 | - Partial failure: only affected card shows error, rest loads normally |
| 66 | - Full page failure: full-screen EmptyState with retry |
| 67 | - Error message: plain language, blame the system |
| 68 | - Always provide retry button |
| 69 | |
| 70 | ### State 4: Success (Action Feedback) |
| 71 | ```tsx |
| 72 | // Toast notification for action confirmations |
| 73 | toast("Changes saved") |
| 74 | |
| 75 | // With undo for destructive actions |
| 76 | toast("Item deleted", { action: { label: "Undo", onClick: handleUndo } }) |
| 77 | ``` |
| 78 | Rules: |
| 79 | - Info toast: 3s display |
| 80 | - Action toast (with undo): 5s display |
| 81 | - Toast position: above BottomNav |
| 82 | - One toast at a time (new replaces old) |
| 83 | |
| 84 | 4. Implementation pattern: |
| 85 | ```tsx |
| 86 | function DataCard({ data, isLoading, error }) { |
| 87 | if (isLoading) return <DataCardSkeleton /> |
| 88 | if (error) return <DataCardError onRetry={refetch} /> |
| 89 | if (!data || data.length === 0) return <DataCardEmpty /> |
| 90 | return <DataCardContent data={data} /> |
| 91 | } |
| 92 | ``` |
| 93 | |
| 94 | 5. Check `prefers-reduced-motion` — disable `animate-pulse` when reduced motion is preferred. |