feat: add TubesBackground component and types#927
feat: add TubesBackground component and types#927AshishDev-16 wants to merge 7 commits intomagicuidesign:mainfrom
Conversation
|
@AshishDev-16 is attempting to deploy a commit to the product-studio Team on Vercel. A member of the Team first needs to authorize it. |
Yeom-JinHo
left a comment
There was a problem hiding this comment.
@AshishDev-16
Tysm for the contribution — the effect looks really cool!!
I don't think we're in a place to merge this as-is. It still feels too tightly coupled to threejs-components, so right now it reads more like a thin wrapper around that package than a standalone Magic UI component.
Third-party usage isn't the issue by itself, but I'm not yet convinced this adds enough Magic UI-specific value to justify bringing in another dependency. Also, since threejs-components is sponsors-only, it makes long-term maintenance and debugging harder for contributors.
Happy to take another look if you want to explore a more self-contained version. The comments in my review may be a helpful starting point.
| @@ -0,0 +1,4 @@ | |||
| declare module "threejs-components/build/cursors/tubes1.min.js" { | |||
There was a problem hiding this comment.
This deep import still breaks strict TS consumers. The local declaration fixes the docs app, but it isn’t shipped, so could we handle it inline?
There was a problem hiding this comment.
Thanks for the feedback! You bring up a great point about the dependency and maintenance issues. I completely agree. I'll rewrite this component using vanilla Three.js directly. This makes it a standalone, 0-dependency (other than three) Magic UI component
|
|
||
| try { | ||
| const threeModule = | ||
| await import("threejs-components/build/cursors/tubes1.min.js") |
There was a problem hiding this comment.
This deep import feels too brittle for a registry component: it relies on an internal build/... path, and combined with the missing shipped typings it makes the integration fragile for consumers. If threejs-components ever reorganizes or renames files under build/, this would break immediately. Can we avoid depending on this internal file path?
There was a problem hiding this comment.
With the vanilla Three.js approach, we won't need this deep import at all, solving the brittleness issue.
| cleanup = () => { | ||
| window.removeEventListener("resize", handleResize) | ||
| if (app && app.destroy) { | ||
| app.destroy() |
There was a problem hiding this comment.
The integration is assuming resize() / destroy() on the returned object, but the published Tubes cursor API returns dispose() instead. As written, we never call the real cleanup path on unmount, which can leave the renderer and global listeners alive after the component is removed. Could we switch this to the actual dispose() API?
There was a problem hiding this comment.
I will ensure the new implementation handles proper Three.js memory management, explicitly disposing of the renderer, scenes, geometries, and materials within the useEffect cleanup return block.
|
If there's a way to achieve this without relying on |
|
Tysm! This looks much closer now. The shipped registry/docs outputs are still on the old |
|
@AshishDev-16 I think there are still 2 implementation issues to fix before this is ready:
Happy to take another look once those are updated. |
…ctivity - Throttle TubeGeometry rebuilds to fix memory leaks and frame drops - Change material to MeshStandardMaterial to respect point lighting - Scope pointer and resize observers locally to container logic - Use constrained HSL values for random colors to fix readability - Restore pointer-events for nested React children - Guard empty vector arrays and zero-dimension DOMRect accesses - Rebuild magicui registry artifacts
|
Thanks for the detailed review🙌 I've pushed an update addressing all the remaining issues. Here's what was fixed:
I've also run |
|
@AshishDev-16 Before merge, could we expose The thing I’m most unsure about before moving forward is how we want to handle mobile devices. The effect feels pretty heavy in practice, and with Three.js being a fairly large dependency too, I’m still thinking about whether this is the right fit for the library as-is. If you already have a direction in mind for mobile, performance tradeoffs, or a graceful fallback, I’d be very happy to hear it. I think those changes would make the component more reusable while also helping us evaluate whether it fits Magic UI well. |
|
@Yeom-JinHo Totally agree on the props. I'll get On the mobile and bundle concerns, you're right to flag this, and I've been thinking about it too. Here's what I'm planning: Bundle size: I'll move Three.js to a peer dependency rather than bundling it. Consumers who never use this component pay zero cost, and those who do can lazy-load it however fits their setup. I'll add a clear, friendly error if Three.js isn't installed so it doesn't fail silently. Universal win first: IntersectionObserver. Regardless of device, I'll pause the Mobile scaling: on viewports under 768 px, the component will automatically drop Graceful fallback: I'll add a Does that feel like the right balance? Happy to adjust any of it before I start building. |
|
@AshishDev-16 To keep this PR scoped, I think we can skip the mobile-optimized WebGL path for now. If That said, I still want a bit more time to think about whether bringing Three.js into Magic UI, even as a peer dependency, is the right long-term fit. Let me get back to you on that. |
This PR introduces a brand new, highly interactive 3D animated
TubesBackgroundcomponent to the MagicUI library usingthreejs-components.Changes
TubesBackgroundfor gorgeous, customizable, animated 3D background effects.tubes-background-demo.tsx) and successfully registered the component for the CLI.tubes-background.mdx) with clear usage instructions and configured it in the docs sidebar.threejs-components.d.ts).Motivation
MagicUI aims to provide the best modern, dynamic web interface components out there. Adding this abstract geometric 3D background gives users a premium, high-end aesthetic option right out of the box. It feels completely alive and responsive to clicks, giving any landing page or hero section an immediate "wow" factor.
Breaking Changes
None! This is purely a neat, backwards-compatible new component addition.
Screenshots / Videos
Screen.Recording.2026-03-18.141843.mp4