feat(floating-3d-particles): add canvas-based 3d particle background - #1002
feat(floating-3d-particles): add canvas-based 3d particle background#1002Max-Samson wants to merge 3 commits into
Conversation
Add a pseudo-3D floating particle background component, rebuilt from the classic GitMind hero effect as a reusable, configurable UI component.
- Perspective-projected particle field with continuous rotation, vertical floating and depth-based scaling
- 22 props: particle counts, color, size/opacity ranges, rotation/float speed, perspective (fov, distance, depth), mouse interaction, DPI scaling, pause-when-hidden and reduced-motion support
- Mouse rotation listens on window so the canvas stays pointer-events-none and never blocks clicks; disable with mouseInteraction={false}
- Responsive particle count based on the viewport breakpoint
- Default demo and hero-content demo, docs page and registry artifacts
|
@Max-Samson is attempting to deploy a commit to the product-studio Team on Vercel. A member of the Team first needs to authorize it. |
|
Hi @Yeom-JinHo ! Just wanted to check if there’s anything else needed from my side for this PR. I noticed the Vercel preview may still require team authorization. Happy to make any changes or updates if needed. Thanks! |
Yeom-JinHo
left a comment
There was a problem hiding this comment.
Thanks for the contribution — this is a genuinely lovely component. The perspective projection reads beautifully behind hero content, and shipping it with zero dependencies plus aria-hidden, pointer-events-none and a reduced-motion path is more care than most background components get.
That said, I'm hesitant to merge as-is. I ran it locally against apps/www and hit following:
-
prefers-reduced-motion renders an empty canvas. The reduced-motion branch in render() draws one static frame and returns without re-queueing rAF, so the loop dies. resize() then reassigns canvas.width, which clears it — and ResizeObserver always fires an initial callback after the first rAF, so the canvas ends up blank from the very first frame. Verified: 0 painted pixels vs ~37k in the normal path. Same on every resize, and it never recovers if the user turns reduced motion off.
-
icon-cloud registry metadata changed, unrelated to this PR. registry-ui.ts adds dependencies: ["lucide-react"] and registryDependencies: ["button"] to icon-cloud, but that component imports neither.
-
22 props is the highest in the registry, and prop removal becomes breaking after release. background/zIndex are already reachable via style; smoothMouse folds into
mouseSmoothing={0}; highDpi into maxDpr={1}. Also worth clamping fov/perspectiveDistance/depthRange — some combinations make the projection divide by zero.
Minor: the two demo descriptions in registry-examples.ts look swapped, and mobileBreakpoint's JSDoc says "container width" where the code reads ``window.innerWidth`.
Could you take a pass at these and re-request review when you're ready?
|
Visual notes, separate from the review above:
|
Hi @Yeom-JinHo , thank you so much for the thorough review and for taking the time to test the component locally. I really appreciate the detailed feedback. I’ve gone through your comments and tested the issues you pointed out on my side. I agree with your suggestions, and I’ll take a pass at the component and make the necessary adjustments, including the reduced-motion behavior, registry metadata, prop surface, projection safety, visual contrast, mobile behavior, and the demo/documentation details. I’ll make sure to test the changes locally and verify everything before pushing the update. Once the changes are ready, I’ll update the PR and re-request your review. Thanks again for the thoughtful review — it’s really helpful for improving the component and making it a better fit for Magic UI. |
- fix(a11y): keep rAF loop running in reduced-motion mode - fix(registry): remove unrelated deps from icon-cloud metadata - refactor(props): streamline prop surface to 6 core visual props - fix(projection): clamp parameters and prevent divide-by-zero - fix(render): eliminate secondary alpha decay for proper contrast - fix(responsive): scale orbit radius with max(width, height) - perf: remove pointer listeners for pure auto-rotating 3D field - docs: update MDX props table, usage guidelines, and demos
Add a pseudo-3D floating particle background component, rebuilt from the classic GitMind hero effect as a reusable, configurable UI component.
Description
Changes
Motivation
Breaking Changes
Screenshots
Checklist
pnpm checkpasses locallypnpm buildpasses locallypnpm build:registrywas run and the generated files are committed (if you changedregistry/orconfig/site.ts— CI verifies this on every PR)feat(marquee): add reverse prop)