尚未收集仓库信息。
尚未检测到更新。GitHub 发布版本后会显示在这里。
Animated React components with sound. Install with the shadcn CLI.
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Animated React components for shadcn projects. Install with the shadcn CLI or copy the source.
purrfectui.com · Components · Follow on X
purrfect ui is a shadcn registry built with Next.js, Tailwind CSS and TypeScript. Every component is animated (Motion, or GSAP for Magnetic, or plain CSS and rAF), honors prefers-reduced-motion and installs straight into your codebase. You own the code: no package to depend on, restyle anything. The site itself plays synthesized sound cues; the installed components stay silent. The components are extracted from my own projects (Poinu, Mapinly, Bountydesk, portfolio).
npx shadcn@latest init first. The components use its tokens (background, foreground, primary, muted, border, input, ...) and its cn() from @/lib/utils, so they follow your theme in light and dark.className (merged with cn(), so your classes win) and passes the rest of its props (id, style, aria-*, data-*, handlers) to its root element.Renamed so they no longer overwrite shadcn's own files: button is now roll-button, tabs is glide-tabs, toggle is stretch-switch (old URLs redirect).
Install any component with the shadcn CLI:
npx shadcn@latest add https://purrfectui.com/r/<component>.json
For example:
npx shadcn@latest add https://purrfectui.com/r/roll-button.json
Browse every component with a live preview (installable ones also show their source and props) at purrfectui.com/components.
Not tested end to end yet; tracked in #1.
In your project, add this to components.json:
{
"registries": {
"@purrfectui": "https://purrfectui.com/r/{name}.json"
}
}
Then:
npx shadcn@latest mcp init --client claude
# or: --client cursor | vscode
Ask: add @purrfectui/roll-button
Not add roll-button on its own. That looks in the default shadcn registry.
git clone https://github.com/Vaibhav91one/purrfect-ui.git
cd purrfect-ui
pnpm install
pnpm dev # http://localhost:3000
pnpm registry:build # after changing a component or registry.json
pnpm build
app/ the platform: the home page and the /components gallery (a component opens in a dialog, ?c=<slug>)registry/<slug>/ one folder per installable component: <slug>.tsx (the installable file) and demo.tsxlib/components-data.ts the gallery list (name, category, description); a component counts as installable once it is in registry.jsonlib/component-docs.ts usage snippet, props and behaviours shown in the dialogregistry.json lists every installable item; pnpm registry:build writes public/r/*.json (also runs before pnpm build)Next 16: read node_modules/next/dist/docs/ before relying on older Next APIs (see AGENTS.md).
Every interaction has a cue, synthesized live by Cuelume (no audio files). components/providers/sound-provider.tsx owns it: on by default, the saved choice lives in localStorage (sound), and the first pointerdown/keydown unlocks audio (browsers block it before a gesture). lib/sound.ts is the only file that imports Cuelume.
Two ways to add a sound:
data-cuelume-tap | toggle | open | close | navigate | select | type on the element. bind() (called by the provider) listens once for the whole page.const { play } = useSound(); play("success", { emphasis: "subtle" }).Where sound is wired today:
| Where | Cue |
|---|---|
| Notch open / close / menu rows / search | open, close, navigate |
| Notch theme and sound toggles | toggle, tap |
| Hero "Browse components" link | navigate (data-cuelume-navigate) |
| Copy buttons (the whole hero install pill, path view, component sheet) | success, subtle, only after the copy worked |
Pick the cue by the job (copy = success subtle, route change = navigate, switch = toggle). Cat sounds (purr, meow, steps) are parked in lib/cat-sounds.ts, not wired in.
Copying shows a toast. The host is one shared sonner <Toaster /> in components/ui/sonner.tsx, mounted in app/layout.tsx; call toast.success(...) etc. from sonner for anything new.
A component that came from a real site can show a short clip of it running there: the hero, a scroll to the component, a camera push-in, one interaction, then back to the hero so the loop has no seam. It plays on card hover and in the dialog's "In the wild" tab. Add an entry (target is a CSS selector on the live page) to scripts/capture/clips.mjs, then run pnpm capture <slug> (or all, --base http://localhost:3000 for a local copy of the site). The capture renders frame by frame in virtual time, so it is a true 60fps (960x600) however slow the machine is; it needs Chrome and system ffmpeg. The files land in public/previews/ and the slug is listed in lib/clips.json; without a clip nothing extra shows.
Every component has to pass the same gate before it goes in registry.json. The rules come from CLAUDE.md and the animate, review-animations, apple-design and break-ui skills.
pnpm check <slug> # static rules + eslint + tsc; exit 1 on any FAIL (pnpm check all, --fast skips eslint/tsc)
pnpm check --rules # every rule and why it exists
pnpm check:selftest # proves each rule fires on bad code
pnpm check <slug> --install # scaffolds a throwaway Next app, shadcn-adds the component from :3120/r, tsc + next build
pnpm check:perf <slug|all> # runtime gate on /dev fixtures (dev server on :3120): long tasks, layout shift, console errors, with and without reduced motion
pnpm check:budget # page weight on a production server (pnpm build && pnpm start; --base, default :3000): gzipped first-load JS per route, long tasks and CLS scrolling /components
CI runs the static gate and pnpm build on every push, then the install smoke test for every component in parallel.
A deliberate exception is a comment on the same or previous line: check-ignore: <rule-id> <reason>. A WARN needs a one-line reason in the PR; a FAIL blocks.
Port checklist, in order:
registry/<slug>/<slug>.tsx, strip site-only imports so it is one self-contained file (only react, declared dependencies, @/lib/utils).registry.json (with dependencies), item() in lib/components-data.ts, DOCS in lib/component-docs.ts (end behaviors with the Reduced-motion line), DEMOS in components/gallery/demos/demos.tsx.pnpm check <slug> has no FAIL.registry/<slug>/worst-case.tsx (long and unbreakable labels, 0/1/1000 items, missing optional props, RTL, non-Latin text, huge numbers), list it in app/dev/fixtures.ts, open /dev?c=<slug> (dev only; width and RTL toggles) and fix what breaks (/break-ui)./review-animations then /animate for its fixes; /apple-design for anything gesture or spring (interruptible, velocity handoff, press feedback on pointer-down, rubber-banding).pnpm check <slug> --install passes.scripts/capture/clips.mjs, pnpm capture <slug>). The same recorded clip (public/previews/<slug>.mp4, 60fps) is what gets posted.Issues and pull requests are welcome. See CONTRIBUTING.md for how to add a component and the quality gate it has to pass.
MIT. Use, modify and ship the components in anything you build, personal or commercial.