# Tasks: enterprise-react-skeleton **Change ID**: enterprise-react-skeleton **Package**: `@suaveplan/react-skeleton` **Target path**: `react/ui/react-skeleton` **Prerequisite packages on Verdaccio**: `@suaveplan/react-translate` --- ## 0. Pre-flight (non-negotiable) - [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each) - [ ] 0.2 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - [ ] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest. ## 1. Scaffold - [ ] Create directory tree per proposal layout. - [ ] Write `package.json` at `0.1.0` with `"sideEffects": ["**/*.css"]`, exports map (barrel + per-component subpaths + `./styles/skeleton.css`). - [ ] Dependencies: `@suaveplan/react-translate workspace:^`, `clsx catalog:ui`, `tailwind-merge catalog:ui`, `zod catalog:forms`, `tslib catalog:build`. - [ ] Write `tsconfig.json`, `vitest.config.ts`, scripts. --- ## 2. Utilities - [ ] `src/utils/cn.ts` — `cn` helper (`clsx` + `twMerge`). - [ ] `src/styles/skeleton.css` — `@keyframes shimmer` + `.skeleton-animate` class; `@media (prefers-reduced-motion: reduce) { .skeleton-animate { animation: none; } }`. --- ## 3. Hook — `useSkeleton` - [ ] Implement `useSkeleton(options: UseSkeletonOptions): UseSkeletonReturn` — manages `isLoading` state with optional `minDisplayMs` (prevents flash), exposes `startLoading()`, `stopLoading()`, `isLoading`. - [ ] Write `UseSkeletonOptionsSchema` Zod schema. - [ ] Write `use-skeleton.test.ts`: initial state, `startLoading`, `stopLoading`, `minDisplayMs` delay, SSR safety. `{ timeout: 5000 }`. - [ ] Write `use-skeleton.stories.tsx`: `default`, `playground` (toggle isLoading), `with-min-display`. - [ ] Write `use-skeleton.md` (≥200 words). --- ## 4. Components ### `Skeleton` - [ ] Base shimmer block: `width`, `height`, `borderRadius` props, `cn` for class merge, `aria-hidden="true"`. Write test, stories (default, custom-size, rounded, playground), md. ### `SkeletonText` - [ ] N-line text shimmer: `lines`, `lastLineWidth` props. Write test, stories, md. ### `SkeletonAvatar` - [ ] Circle/rect avatar placeholder with `shape: 'circle' | 'square'`, `size: 'xs' | 'sm' | 'md' | 'lg' | 'xl'`. Write test, stories, md. ### `SkeletonCard` - [ ] Card with image placeholder + 3-line text placeholder. Write test, stories, md. ### `SkeletonTable` - [ ] Table grid placeholder: `rows`, `columns` props. Write test, stories, md. --- ## 5. E2E - [ ] `e2e/skeleton.spec.ts` — Playwright: render each component, take screenshot snapshot (loading state); compare with baseline. Also render with `prefers-reduced-motion: reduce` and assert no `animation` style is applied. --- ## 6. Docs - [ ] All co-located `.md` files per component and hook. - [ ] Root `README.md`: purpose, install, CSS import note, component inventory, API summary. --- ## 7. Verify and publish - [ ] `bunx turbo lint typecheck test --filter=@suaveplan/react-skeleton` — green. - [ ] `bunx turbo test:coverage --filter=@suaveplan/react-skeleton` — 100%. - [ ] `bun scripts/publish.ts --package @suaveplan/react-skeleton`. - [ ] Archive change folder.