npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

vue3-bits

v0.1.2

Published

Vue3 + TresJS reusable 3D components (ModelViewer first).

Readme

vue3-bits

A small, publishable Vue 3 + TypeScript component library built on TresJS v5 (declarative Three.js for Vue). Components include ModelViewer — a faithful Vue port of the react-bits ModelViewer, with drag-to-rotate, inertia, mouse parallax, hover rotation, auto-rotate, auto-framing, fade-in, environment lighting, contact shadows, and PNG screenshot export — and Lightfall, a shader light-streak background built on ogl, and TextType, a typewriter text animation (react-bits port, no extra dependencies). It also ships six text-animation components ported 1:1 from react-bitsShinyText, CurvedLoop, FuzzyText, GradientText, LineSidebar and AnimatedList — all reimplemented with native requestAnimationFrame / IntersectionObserver / Canvas 2D / SVG, with zero new runtime or peer dependencies. It now also ships seven interaction / 3D components ported from react-bits — SpotlightCard, BorderGlow, Dock, ScrollStack, CircularGallery, MagicBento and FluidGlass. Six are zero-dependency DOM + CSS ports; CircularGallery reuses the already-bundled ogl engine, MagicBento adds gsap as a bundled runtime dependency, and FluidGlass is built on the peer @tresjs/core + three (no @react-three/*, drei, maath or external GLB assets — programmatic geometry + MeshPhysicalMaterial transmission replace them).

Single package, multiple components. More components will land under src/components/ following the same structure.


Components

| Component | Category | Runtime deps | Notes | | --- | --- | --- | --- | | SpotlightCard | Interaction | none | Mouse-following radial spotlight (CSS ::before). | | BorderGlow | Interaction | none | Mesh-gradient border + edge-proximity glow. | | Dock | Interaction | none | macOS dock magnification (hand-rolled rAF spring). | | ScrollStack | Interaction | none | Scroll-pinned stacking cards (native scroll, no Lenis). | | CircularGallery | 3D | ogl (bundled) | WebGL plane ring; engine in gallery.ts. | | MagicBento | Interaction | gsap (bundled) | Tilt / magnetism / particles / spotlight. | | FluidGlass | 3D | @tresjs/core + three (peer) | MeshPhysicalMaterial transmission; no GLB/drei. |


Install

npm install vue3-bits
# peer deps (provided by the host app)
npm install vue@^3.4 three @tresjs/core@^5 @tresjs/cientos@^5

vue, three, @tresjs/core and @tresjs/cientos are peer dependencies and are kept external in the build — your app controls their versions. three is allowed at >=0.166.0, so newer releases (e.g. [email protected]) install cleanly without --legacy-peer-deps.


Usage

<script setup lang="ts">
import { ModelViewer } from 'vue3-bits';
</script>

<template>
  <ModelViewer
    url="https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/main/2.0/ToyCar/glTF-Binary/ToyCar.glb"
    :width="480"
    :height="480"
    environment-preset="forest"
  />
</template>

Screenshot / capture programmatically

<script setup lang="ts">
import { ref } from 'vue';
import { ModelViewer } from 'vue3-bits';
import type { ModelViewerExpose } from 'vue3-bits';

const viewer = ref<ModelViewerExpose | null>(null);
</script>

<template>
  <ModelViewer ref="viewer" url="model.glb" :show-screenshot-button="false" />
  <button @click="viewer?.capture()">Download PNG</button>
</template>

Note: preserveDrawingBuffer is enabled on the canvas, so the screenshot button / capture() works without a manual re-render. The screenshot downloads as model.png.


Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | url | string | — (required) | Model URL. Supports .glb, .gltf, .fbx, .obj. | | width | number \| string | 400 | Canvas width (number → px). | | height | number \| string | 400 | Canvas height (number → px). | | modelXOffset | number | 0 | Billboard horizontal NDC offset. | | modelYOffset | number | 0 | Billboard vertical NDC offset. | | defaultRotationX | number | -50 | Initial X rotation (degrees). | | defaultRotationY | number | 20 | Initial Y rotation (degrees). | | defaultZoom | number | 0.5 | Initial camera Z (clamped to [min,max]). | | minZoomDistance | number | 0.5 | Min zoom distance. | | maxZoomDistance | number | 10 | Max zoom distance. | | enableMouseParallax | boolean | true | Mouse parallax (non-touch). | | enableManualRotation | boolean | true | Drag to rotate. | | enableHoverRotation | boolean | true | Hover rotation (non-touch). | | enableManualZoom | boolean | true | Zoom (OrbitControls + pinch). | | ambientIntensity | number | 0.3 | Ambient light intensity. | | keyLightIntensity | number | 1 | Key (top-right) light intensity. | | fillLightIntensity | number | 0.5 | Fill (left) light intensity. | | rimLightIntensity | number | 0.8 | Rim (back) light intensity. | | environmentPreset | EnvironmentPreset | 'forest' | cientos <Environment> preset. 'none' disables it. | | autoFrame | boolean | false | Auto-compute camera distance from fov. | | placeholderSrc | string | '' | Blurred image shown while loading. | | showScreenshotButton | boolean | true | Show the screenshot button. | | fadeIn | boolean | false | Fade material opacity 0→1 on load. | | autoRotate | boolean | false | Continuously auto-rotate. | | autoRotateSpeed | number | 0.35 | Auto-rotate speed (rad/s). | | onModelLoaded | () => void | — | Called once the model is loaded & normalized. |

EnvironmentPreset

Aligned to the presets shipped by @tresjs/[email protected]. 'none' disables the environment. (Earlier docs suggested apartment/lobby/park/warehouse, but those are not present in cientos v5 and would throw at runtime, so they are omitted.)

'none' | 'city' | 'dawn' | 'forest' | 'hangar' | 'modern' | 'night' | 'shangai' | 'snow' | 'studio' | 'sunset' | 'umbrellas' | 'urban'

Exposed method

capture(): void — render the current frame and download a PNG. Available via ref on <ModelViewer>.


Lightfall

A shader-driven light-streak background. It renders via ogl, which is a bundled runtime dependencynpm install vue3-bits is enough, no separate npm install ogl required.

<script setup lang="ts">
import { Lightfall } from 'vue3-bits';
</script>

<template>
  <Lightfall :speed="0.6" background-color="#0A29FF" />
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | color1 / color2 / color3 | string | — | Beam colors (override colors). | | colors | string[] | ['#A6C8FF', ...] | Color palette. | | backgroundColor | string | '#0A29FF' | Background color. | | speed | number | 0.5 | Animation speed. | | streakCount | number | 2 | Number of beams (1–16). | | streakWidth | number | 1 | Beam width. | | streakLength | number | 1 | Beam length. | | glow | number | 1 | Glow intensity. | | density | number | 0.6 | Density. | | zoom | number | 3 | Zoom. | | mouseInteraction | boolean | true | Mouse interaction. | | opacity | number | 1 | Opacity. | | paused | boolean | false | Pause animation. |

Full prop list with live controls is in src/play/demos/LightfallDemo.vue.


TextType

A typewriter text animation — a faithful Vue port of the react-bits TextType. It types out one or more phrases (looping, with an optional blinking cursor) using only Vue + CSS — no extra runtime dependencies (the cursor blink is a plain CSS @keyframes, not GSAP).

<script setup lang="ts">
import { TextType } from 'vue3-bits';
</script>

<template>
  <TextType
    :text="['Hello world', 'Built with Vue 3', 'Happy coding!']"
    :typing-speed="50"
    :pause-duration="2000"
    :show-cursor="true"
  />
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | text | string \| string[] | — (required) | Phrase(s) typed in rotation. A string is treated as a single-element array. | | texts | string \| string[] | — | Alias of text, used only when text is omitted. | | tag | string | 'div' | Root element tag name. | | typingSpeed | number | 50 | Milliseconds per typed character. | | initialDelay | number | 0 | Delay before typing starts (ms). | | pauseDuration | number | 2000 | Pause after a phrase completes (ms). | | deletingSpeed | number | 30 | Milliseconds per deleted character. | | loop | boolean | true | Cycle through phrases indefinitely. | | showCursor | boolean | true | Show the blinking cursor. | | cursorCharacter | string | '\|' | Cursor character. | | cursorBlinkDuration | number | 0.5 | Cursor blink period (seconds). | | textColors | string[] | [] | Per-phrase text colors, cycled by index. |

Full prop list with live controls is in src/play/demos/TextTypeDemo.vue. Emits sentence-complete (payload: [text, index]) after each phrase finishes typing.


ShinyText

A shiny / flowing-gradient text effect — a Vue port of the react-bits ShinyText. The shine travels across the text via an animated background-position, driven by a native requestAnimationFrame loop (no motion/framer-motion dependency).

<script setup lang="ts">
import { ShinyText } from 'vue3-bits';
</script>

<template>
  <ShinyText
    text="Just shuffle!"
    :speed="2"
    :shine-color="'#ffffff'"
    :color="'#b5b5b5'"
    :spread="120"
  />
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | text | string | '' | Text content (rendered inside the shine <span>). | | disabled | boolean | false | Stop the rAF animation loop. | | speed | number | 2 | Animation duration (seconds). | | className | string | '' | Extra class merged onto the root <span>. | | color | string | '#b5b5b5' | Base text color. | | shineColor | string | '#ffffff' | Highlight color that sweeps across. | | spread | number | 120 | Gradient angle (degrees). | | yoyo | boolean | false | 4-phase ping-pong (forward → hold → reverse → hold). | | pauseOnHover | boolean | false | Pause animation while hovered. | | direction | 'left' \| 'right' | 'left' | Sweep direction (symbol-flipped internally). | | delay | number | 0 | Hold delay at each end (seconds). |

Full prop list with live controls is in src/play/demos/ShinyTextDemo.vue.


CurvedLoop

A curved marquee that flows text along an SVG arc — a Vue port of the react-bits CurvedLoop. The text rides an SVG <textPath>; a single rAF advances the startOffset and wraps at the measured spacing. Pointer drag scrubs the offset. Unique DOM ids use a module-level counter (not useId(), for vue <3.5 safety).

<script setup lang="ts">
import { CurvedLoop } from 'vue3-bits';
</script>

<template>
  <CurvedLoop
    marquee-text="REACT BITS • VUE3 BITS • "
    :speed="2"
    :curve-amount="400"
    :direction="'left'"
    :interactive="true"
  />
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | marqueeText | string | '' | Text to flow; a trailing non-breaking space is appended automatically. | | speed | number | 2 | startOffset step per frame. | | className | string | '' | Extra class merged onto the <text> element. | | curveAmount | number | 400 | Bézier control-point offset (arc curvature). | | direction | 'left' \| 'right' | 'left' | Flow direction. | | interactive | boolean | true | Enable pointer-drag scrubbing. |

Full prop list with live controls is in src/play/demos/CurvedLoopDemo.vue.


FuzzyText

A fuzzy / glitchy text effect rendered on a <canvas> — a Vue port of the react-bits FuzzyText. Each row of the text is drawn onto an offscreen canvas then re-blitted with per-frame jitter. When text is empty it falls back to the default slot content (decision 1); in jsdom (and SSR) getContext('2d') returns null and the effect early-returns without throwing.

<script setup lang="ts">
import { FuzzyText } from 'vue3-bits';
</script>

<template>
  <!-- Option A: text prop -->
  <FuzzyText text="Fuzzy" :base-intensity="0.18" :hover-intensity="0.5" />

  <!-- Option B: default slot (probe fallback) -->
  <FuzzyText>Fuzzy</FuzzyText>
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | text | string | '' | Primary text source; falls back to the default slot if empty. | | fontSize | number \| string | 'clamp(2rem, 8vw, 8rem)' | Canvas font size. | | fontWeight | string \| number | 900 | Canvas font weight. | | fontFamily | string | 'inherit' | Canvas font family. | | color | string | '#fff' | Text fill color. | | enableHover | boolean | true | Intensify jitter on hover. | | baseIntensity | number | 0.18 | Idle jitter intensity. | | hoverIntensity | number | 0.5 | Hover jitter intensity. | | fuzzRange | number | 30 | Max jitter amplitude (px). | | fps | number | 60 | Frame rate cap. | | direction | 'horizontal' \| 'vertical' \| 'both' | 'horizontal' | Jitter direction. | | transitionDuration | number | 0 | Step transition duration (seconds). | | clickEffect | boolean | false | Burst on click. | | glitchMode | boolean | false | Periodic glitch bursts. | | glitchInterval | number | 2000 | Glitch interval (ms). | | glitchDuration | number | 200 | Glitch duration (ms). | | gradient | string[] \| null | null | Optional multi-stop canvas gradient (else solid color). | | letterSpacing | number | 0 | Per-glyph spacing (canvas units). | | className | string | '' | Extra class merged onto the <canvas>. |

Full prop list with live controls is in src/play/demos/FuzzyTextDemo.vue.


GradientText

Animated multi-color gradient text — a Vue port of the react-bits GradientText. Content is passed via the default slot; the gradient flows via an animated background-position driven by the shared useRafProgress rAF engine (no motion dependency). showBorder renders a masked outline.

<script setup lang="ts">
import { GradientText } from 'vue3-bits';
</script>

<template>
  <GradientText
    :colors="['#5227FF', '#FF9FFC', '#B497CF']"
    :animation-speed="8"
    :show-border="false"
    :direction="'horizontal'"
    :yoyo="true"
  >
    Gradient Text
  </GradientText>
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | (default slot) | — | — | Text content (replaces react children). | | className | string | '' | Extra class merged onto the root element. | | colors | string[] | ['#5227FF','#FF9FFC','#B497CF'] | Gradient stops; first color is duplicated at the end for a seamless loop. | | animationSpeed | number | 8 | Loop duration (seconds). | | showBorder | boolean | false | Render a masked gradient outline. | | direction | 'horizontal' \| 'vertical' \| 'diagonal' | 'horizontal' | Flow direction. | | pauseOnHover | boolean | false | Pause animation while hovered. | | yoyo | boolean | true | 2-phase ping-pong (forward → reverse). |

Full prop list with live controls is in src/play/demos/GradientTextDemo.vue.


LineSidebar

A sidebar navigation whose items light up with proximity to the pointer — a Vue port of the react-bits LineSidebar. A single rAF eases a shared --effect CSS variable (frame-rate-independent exponential smoothing), and color-mix / translateX / scaleX all read that one variable so there is no CSS-transition desync.

<script setup lang="ts">
import { LineSidebar } from 'vue3-bits';

const items = ['Home', 'Projects', 'About', 'Contact'];
function onItemClick(index: number, label: string) {
  console.log(index, label);
}
</script>

<template>
  <LineSidebar :items="items" falloff="smooth" @item-click="onItemClick" />
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | items | string[] | 12-item default list | Nav labels. | | accentColor | string | '#A855F7' | Active accent color. | | textColor | string | '#c4c4c4' | Idle text color. | | markerColor | string | '#6c6c6c' | Marker / tick color. | | showIndex | boolean | true | Show the numeric index prefix. | | showMarker | boolean | true | Show the side marker line. | | proximityRadius | number | 100 | Pointer influence radius (px). | | maxShift | number | 30 | Max horizontal shift (px). | | falloff | 'linear' \| 'smooth' \| 'sharp' | 'smooth' | Proximity→effect curve (exported as Falloff). | | markerLength | number | 60 | Marker length (px). | | markerGap | number | 0 | Gap before the marker (px). | | tickScale | number | 0.5 | Tick scale factor. | | scaleTick | boolean | true | Scale the tick with effect. | | itemGap | number | 20 | Gap between items (px). | | fontSize | number | 1.1 | Font size (rem). | | smoothing | number | 100 | Easing time constant (ms). | | defaultActive | number \| null | null | Index of the pre-activated item (null = none). | | className | string | '' | Extra class merged onto the root <nav>. |

Emits itemClick (payload: [index, label]). Full prop list with live controls is in src/play/demos/LineSidebarDemo.vue.


AnimatedList

A scroll-reveal list whose items fade & scale in when they enter the viewport — a Vue port of the react-bits AnimatedList. Reveal is driven by a native IntersectionObserver (root = the list container, threshold = 0.5, once = false) toggling a .in-view class; a CSS transition completes the scale .7→1 / opacity 0→1. Keyboard arrow navigation is supported.

<script setup lang="ts">
import { AnimatedList } from 'vue3-bits';

const items = ['Item 1', 'Item 2', 'Item 3'];
function onItemSelect(item: string, index: number) {
  console.log(item, index);
}
</script>

<template>
  <AnimatedList :items="items" @item-select="onItemSelect" />
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | items | string[] | 15-item default list | List entries. | | className | string | '' | Extra class merged onto the root container. | | itemClassName | string | '' | Extra class merged onto each item. | | showGradients | boolean | true | Render top/bottom fade masks. | | enableArrowNavigation | boolean | true | Arrow-up/down + Tab + Enter keyboard selection. | | displayScrollbar | boolean | true | Show the scrollbar. | | initialSelectedIndex | number | -1 | Pre-selected index (-1 = none). |

Emits itemSelect (payload: [item, index]). Full prop list with live controls is in src/play/demos/AnimatedListDemo.vue.


SpotlightCard

Mouse-following radial spotlight rendered with a CSS ::before layer.

<script setup lang="ts">
import { SpotlightCard } from 'vue3-bits';
</script>

<template>
  <SpotlightCard spotlight-color="rgba(0, 229, 255, 0.2)">
    <h2>Spotlight Card</h2>
  </SpotlightCard>
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | className | string | '' | Extra class on the root. | | spotlightColor | string | 'rgba(255,255,255,0.25)' | Spotlight radial-gradient color. |


BorderGlow

Mesh-gradient border + outer glow that intensifies as the pointer nears the edge.

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | className | string | '' | Extra class. | | edgeSensitivity | number | 120 | Edge distance (px) where glow starts. | | glowColor | string | '40 80 80' | Inner glow HSL triplet. | | backgroundColor | string | '#120F17' | Card background. | | borderRadius | number | 16 | Corner radius (px). | | glowRadius | number | 12 | Outer glow spread (px). | | glowIntensity | number | 1 | Opacity multiplier. | | coneSpread | number | 180 | Half-angle of cursor cone. | | animated | boolean | false | Run idle sweep on mount. | | colors | string[] | ['40 80 80', ...] | Mesh-gradient stops. | | fillOpacity | number | 0.1 | Inner fill opacity. |


Dock

macOS-style dock that springs the pointer-proximity item larger (hand-rolled rAF spring, no framer-motion).

<script setup lang="ts">
import { Dock } from 'vue3-bits';
</script>

<template>
  <Dock :items="[{ icon: MyIcon, label: 'Home' }]" :magnification="64" />
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | items | DockItemData[] | [] | { icon, label, onClick, className }. | | className | string | '' | Extra class on panel. | | spring | SpringOptions | { mass: 1, stiffness: 150, damping: 15 } | Magnification spring. | | magnification | number | 64 | Max item size (px). | | distance | number | 120 | Falloff distance (px). | | panelHeight | number | 64 | Resting panel height (px). | | dockHeight | number | paddleHeight + 24 | Outer wrapper height. | | baseItemSize | number | 48 | Resting item size (px). |


ScrollStack

Scroll-pinned stacking cards. Drives the same pin / scale / rotation / blur math as react-bits from native scroll events (no lenis).

<script setup lang="ts">
import { ScrollStack, ScrollStackItem } from 'vue3-bits';
</script>

<template>
  <div style="height: 360px">
    <ScrollStack :blur-amount="4">
      <ScrollStackItem><h2>Card 1</h2></ScrollStackItem>
    </ScrollStack>
  </div>
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | className | string | '' | Extra class on scroller. | | itemDistance | number | 100 | Gap between cards (px). | | itemScale | number | 0.03 | Per-index scale increment. | | itemStackDistance | number | 30 | Extra stack offset (px). | | stackPosition | string | '20%' | Pin start position. | | scaleEndPosition | string | '10%' | Base-scale position. | | baseScale | number | 0.85 | Top card scale when stacked. | | scaleDuration | number | 0.5 | (API parity; unused). | | rotationAmount | number | 0 | Max rotation (deg). | | blurAmount | number | 0 | Buried-card blur (px). | | useWindowScroll | boolean | false | Use window as scroller. | | onStackComplete | () => void | — | Emitted when last card stacks. |


CircularGallery

WebGL plane ring built on the bundled ogl engine (gallery.ts).

<script setup lang="ts">
import { CircularGallery } from 'vue3-bits';
</script>

<template>
  <div style="height: 420px">
    <CircularGallery :items="[{ image: '/a.jpg', text: 'A' }]" :bend="3" />
  </div>
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | items | GalleryItem[] | built-in set | { image, text }. | | bend | number | 3 | Curvature (0 = flat). | | textColor | string | '#ffffff' | Caption color. | | borderRadius | number | 0.05 | Plane corner radius (0..1). | | font | string | 'bold 30px Figtree' | Canvas font string. | | fontUrl | string | undefined | Optional font URL. | | scrollSpeed | number | 2 | Scroll sensitivity. | | scrollEase | number | 0.05 | Scroll easing (0..1). |


MagicBento

Magnetic bento grid: gsap drives tilt / magnetism / particles / ripples and a section spotlight. CSS is a 1:1 port of react-bits MagicBento.css.

<script setup lang="ts">
import { MagicBento } from 'vue3-bits';
</script>

<template>
  <MagicBento :enable-spotlight="true" :enable-border-glow="true" glow-color="132, 0, 255" />
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | items | BentoCardProps[] | 6-card demo set | { color, title, description, label, textAutoHide, disableAnimations }. | | textAutoHide | boolean | true | Hide title/desc until hover. | | enableStars | boolean | false | Floating star particles. | | enableSpotlight | boolean | false | Section-following spotlight. | | enableBorderGlow | boolean | false | Glowing border per card. | | disableAnimations | boolean | false | Force-off animations. | | spotlightRadius | number | 300 | Spotlight radius (px). | | particleCount | number | 12 | Particles per card on hover. | | enableTilt | boolean | true | 3D tilt on pointer move. | | glowColor | string | '132, 0, 255' | Glow RGB triplet. | | clickEffect | boolean | false | Ripple on click. | | enableMagnetism | boolean | false | Magnetic pull to pointer. |


FluidGlass

Fluid glass — a faithful 1:1 port of react-bits FluidGlass, built on the peer @tresjs/core + three. An offscreen FBO (a THREE.Scene rendered into a WebGLRenderTarget every frame) provides the refracted content — the "React Bits" wordmark, demo images and coloured shapes — while a real THREE.MeshPhysicalMaterial (transmission) is the glass. Geometry is loaded from GLB (lens.glb→Cylinder, bar.glb/cube.glb→Cube) via three's built-in GLTFLoader, with a programmatic fallback when the asset is missing.

<script setup lang="ts">
import { FluidGlass } from 'vue3-bits';
</script>

<template>
  <div style="position: relative; height: 400px">
    <FluidGlass mode="lens" :lens-props="{ scale: 0.25, ior: 1.15, thickness: 5, chromaticAberration: 0.1, anisotropy: 0.01 }" />
  </div>
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | mode | 'lens' \| 'bar' \| 'cube' | 'lens' | Glass geometry / behaviour. | | lensProps | FluidGlassModeProps | {} | lens overrides (scale/ior/thickness/roughness/transmission/chromaticAberration/anisotropy/color/attenuationColor/attenuationDistance). | | barProps | FluidGlassModeProps | {} | bar overrides (carries navItems). | | cubeProps | FluidGlassModeProps | {} | cube overrides. | | className | string | '' | Class on root wrapper. | | width | number \| string | 400 | Canvas width. | | height | number \| string | 400 | Canvas height. |

Note: CircularGallery needs ogl (bundled). MagicBento needs gsap (bundled). FluidGlass needs the peer @tresjs/core + three already present in the host app — npm install vue3-bits @tresjs/core three. The transmission material is intentionally not transparent (red line 34). GLB geometry (public/assets/3d/*.glb) and demo images (public/assets/demo/*.webp) are optional — missing files fall back to programmatic geometry / gradients so the component never crashes. Scroll the canvas with the mouse wheel (3 pages).


LiquidEther

WebGL fluid simulation built on three — multiple WebGLRenderTarget ping-pong plus advection / pressure / viscous / divergence shaders, with a pointer force and an auto-pilot driver. The component fills its parent, so wrap it in a sized container.

<script setup lang="ts">
import { LiquidEther } from 'vue3-bits';
</script>

<template>
  <div style="position: relative; height: 400px">
    <LiquidEther :mouse-force="20" :colors="['#5227FF', '#FF9FFC', '#B497CF']" />
  </div>
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | colors | string[] | ['#5227FF','#FF9FFC','#B497CF'] | Palette (builds a DataTexture). | | mouseForce | number | 20 | Pointer force strength. | | cursorSize | number | 100 | Force brush radius (px). | | isViscous | boolean | false | Enable viscous diffusion. | | viscous | number | 30 | Viscosity coefficient. | | iterationsViscous | number | 32 | Viscous Jacobi iterations. | | iterationsPoisson | number | 32 | Pressure (Poisson) iterations. | | dt | number | 0.014 | Simulation time step. | | BFECC | boolean | true | BFECC advection (MacCormack). | | resolution | number | 0.5 | FBO size as a fraction of the container. | | isBounce | boolean | false | Bounce at boundary (false = soft wall). | | autoDemo | boolean | true | Auto-pilot driver. | | autoSpeed | number | 0.5 | Auto-pilot speed. | | autoIntensity | number | 2.2 | Auto-pilot force multiplier. | | takeoverDuration | number | 0.25 | Takeover lerp duration (s). | | autoResumeDelay | number | 1000 | Idle ms before auto-pilot resumes. | | autoRampDuration | number | 0.6 | Auto-pilot ramp-up (s). | | className | string | '' | Class on the root container. |

Note: LiquidEther and FloatingLines use the bundled peer three (npm install vue3-bits three). LightRays reuses the bundled ogl. No new dependencies are added.


FloatingLines

Full-screen shader of floating lines built on three — multiple waves flow along curves with pointer bending and parallax. The component fills its parent.

<script setup lang="ts">
import { FloatingLines } from 'vue3-bits';
</script>

<template>
  <div style="position: relative; height: 400px">
    <FloatingLines :line-count="8" :animation-speed="1" />
  </div>
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | linesGradient | string[] | undefined | Line gradient stops (max 8). | | enabledWaves | ('top'\|'middle'\|'bottom')[] | ['top','middle','bottom'] | Waves to render. | | lineCount | number \| number[] | [6] | Lines per wave. | | lineDistance | number \| number[] | [5] | Distance per wave (×0.01). | | topWavePosition | WavePosition | {x:10,y:0.5,rotate:-0.4} | Top wave position. | | middleWavePosition | WavePosition | {x:5,y:0,rotate:0.2} | Middle wave position. | | bottomWavePosition | WavePosition | {x:2.0,y:-0.7,rotate:-1} | Bottom wave position. | | animationSpeed | number | 1 | Time multiplier. | | interactive | boolean | true | Pointer bending interaction. | | bendRadius | number | 5.0 | Bend radial falloff. | | bendStrength | number | -0.5 | Bend strength. | | mouseDamping | number | 0.05 | Mouse / parallax easing. | | parallax | boolean | true | Parallax offset. | | parallaxStrength | number | 0.2 | Parallax strength. | | mixBlendMode | string | 'screen' | Container mix-blend-mode. | | className | string | '' | Class on the root container. |

WavePosition = { x: number; y: number; rotate: number }.


LightRays

Full-screen shader of light rays built on the bundled ogl — rays emit from an anchor with pulsing, mouse deflection and noise. The component fills its parent.

<script setup lang="ts">
import { LightRays } from 'vue3-bits';
</script>

<template>
  <div style="position: relative; height: 400px">
    <LightRays rays-origin="top-center" rays-color="#ffffff" />
  </div>
</template>

Props

| Prop | Type | Default | Description | | --- | --- | --- | --- | | raysOrigin | 'top-center'\|'top-left'\|'top-right'\|'right'\|'left'\|'bottom-center'\|'bottom-right'\|'bottom-left' | 'top-center' | Ray anchor + direction. | | raysColor | string | '#ffffff' | Ray color (hex). | | raysSpeed | number | 1 | Ray pulse speed. | | lightSpread | number | 1 | Spread exponent. | | rayLength | number | 2 | Ray length. | | pulsating | boolean | false | Breathing pulse. | | fadeDistance | number | 1.0 | Far fade distance. | | saturation | number | 1.0 | Color saturation. | | followMouse | boolean | true | Mouse deflects rays. | | mouseInfluence | number | 0.1 | Mouse influence weight. | | noiseAmount | number | 0.0 | Noise amount. | | distortion | number | 0.0 | Angle distortion. | | className | string | '' | Class on the root container. |

Note: LightRays reuses the bundled ogl — no extra install needed.


Components ported from react-bits (#16–46)

31 个组件,1:1 还原 props / uniforms / GLSL。背景类复用 peer three 或 bundled ogl;交互类为纯 DOM/SVG/CSS,部分用 bundled gsap0 新增依赖(构建 external 列表不变,ogl/gsap 仍 bundled)。完整 Props 以 src/components/<Name>/types.ts<Name>Demo.vue 为准。

LineWaves (Background · ogl)

ogl 全屏波浪线着色器背景。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | color | string | '#ffffff' | 线条颜色 | | speed | number | 1 | 动画速度 | | waveWidth | number | 1 | 波宽 | | lineColor | string[] | — | 多色线条 | | className | string | '' | 根 class |

Radar (Background · ogl)

ogl 雷达扫描着色器背景。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | color | string | '#ffffff' | 扫描线颜色 | | speed | number | 1 | 扫描速度 | | strokeColor | string | '#ffffff' | 网格描边色 | | className | string | '' | 根 class |

SoftAurora (Background · ogl)

ogl 极光着色器背景。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | colors | string[] | 3 色 | 极光配色 | | speed | number | 1 | 流动速度 | | className | string | '' | 根 class |

Plasma (Background · ogl)

ogl 等离子着色器背景。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | color | string | '#ff0000' | 等离子主色 | | speed | number | 1 | 动画速度 | | className | string | '' | 根 class |

Particles (Background · ogl)

ogl 粒子着色器背景。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | color | string | '#ffffff' | 粒子颜色 | | particleCount | number | 200 | 粒子数量 | | particleSpread | number | 10 | 扩散范围 | | speed | number | 1 | 动画速度 | | className | string | '' | 根 class |

GradientBlinds (Background · ogl)

ogl 渐变百叶着色器背景。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | color | string | '#ffffff' | 百叶颜色 | | speed | number | 1 | 动画速度 | | className | string | '' | 根 class |

GridScan (Background · three)

three 网格扫描着色器背景(引擎在 gridScanEngine.ts)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | lineColor | string | '#ffffff' | 扫描线颜色 | | gridColor | string | '#ffffff' | 网格颜色 | | cellSize | number | 20 | 单元格尺寸 | | gridThickness | number | 1 | 网格线宽 | | gridOpacity | number | 0.3 | 网格透明度 | | scanColor | string | '#ffffff' | 扫描光带色 | | scanSpeed | number | 1 | 扫描速度 | | className | string | '' | 根 class |

Lightning (Background · 原生 WebGL)

原生 canvas.getContext('webgl') 闪电背景(无 three/ogl)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | hue | number | 230 | 色相 | | xOffset | number | 0 | 横向偏移 | | speed | number | 1 | 动画速度 | | intensity | number | 1 | 强度 | | size | number | 1 | 尺寸 |

Galaxy (Background · ogl)

ogl 星系粒子背景。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | radius | number | Math.PI | 星系半径 | | density | number | 1 | 密度 | | maxParticles | number | 7000 | 最大粒子数 | | color | string | '#ffffff' | 粒子颜色 | | className | string | '' | 根 class |

DotField (Background · Canvas2D)

Canvas2D 点阵背景(getContext('2d') 已做 null 守卫)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | dotColor | string | '#ffffff' | 点颜色 | | gap | number | 20 | 点间距 | | size | number | 2 | 点大小 | | className | string | '' | 根 class |

DotGrid (Background · Canvas2D + gsap)

Canvas2D 点阵网格,指针交互(bundled gsap 驱动)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | dotColor | string | '#ffffff' | 点颜色 | | gap | number | 20 | 点间距 | | size | number | 2 | 点大小 | | className | string | '' | 根 class |

Hyperspeed (Background · three)

three 超光速隧道背景(复杂多 pass 引擎在 hyperspeedEngine.ts)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | effectOptions | object | DEFAULT_EFFECT_OPTIONS | 隧道/星点/光带全套配置 | | className | string | '' | 根 class |

Waves (Background · Canvas2D + gsap)

Canvas2D 波浪背景(bundled gsap)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | lineColor | string | '#ffffff' | 线颜色 | | backgroundColor | string | '#000000' | 背景色 | | waveSpeed | number | 1 | 波浪速度 | | className | string | '' | 根 class |

Ballpit (Background · ogl)

ogl 弹球物理背景(含 three 向量数学)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | className | string | '' | 根 class | | followCursor | boolean | true | 跟随指针 | | count | number | — | 球数 | | maxVelocity | number | — | 最大速度 | | radius | number | — | 球半径 |

Orb (Background · ogl)

ogl 光球着色器背景,悬停旋转。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | hue | number | 0 | 色相 | | rotateOnHover | boolean | true | 悬停旋转 | | hoverIntensity | number | 2 | 悬停强度 | | forceHoverState | boolean | false | 强制悬停 | | backgroundColor | string | '#000000' | 背景色 |

ShapeGrid (Background · Canvas2D)

Canvas2D 形状网格,悬停拖尾(null 守卫)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | speed | number | 0.1 | 动画速度 | | squareSize | number | 40 | 单元尺寸 | | direction | 'up'\|'down'\|'left'\|'right'\|'diagonal' | 'diagonal' | 流动方向 | | borderColor | string | '#5408df' | 边框色 | | hoverFillColor | string | '#222' | 悬停填充 | | shape | 'square'\|'hexagon'\|'circle'\|'triangle' | 'square' | 形状 | | hoverTrailAmount | number | 2 | 拖尾数 | | hoverColor | string | '#5bbd98' | 悬停色 | | size | number | 20 | 点大小 |

Stepper (Interaction · DOM)

分步导航,使用 <Step> 子组件 / 插槽。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | initialStep | number | 0 | 初始步 | | onStepChange | (step: number) => void | — | 步变化回调 | | onFinalStepCompleted | () => void | — | 完成回调 | | backButtonText | string | 'Previous' | 返回按钮文案 | | nextButtonText | string | 'Next' | 下一步文案 | | disableStepIndicators | boolean | false | 隐藏步指示 |

InfiniteMenu (Interaction · 原生 WebGL2 + DOM)

无限循环菜单,带 WebGL2 扭曲背景(jsdom 下早退,不 throw)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | items | { image: string; link: string; title: string; description: string }[] | [] | 菜单项 | | className | string | '' | 根 class |

Counter (Interaction · gsap)

数字滚动计数器。原 motion/react 已重写为 bundled gsap / 原生 rAF。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | value | number | 0 | 目标值 | | places | (number \| '.')[] | [100, 10, 1] | 数位权重 | | fontSize | number | 80 | 字号 | | padding | number | 5 | 内边距 | | gap | number | 10 | 位间距 | | textColor | string | 'white' | 文字色 | | fontWeight | number | 900 | 字重 | | digitPlaceHolders | boolean | false | 占位符 |

ElasticSlider (Interaction · gsap)

弹性滑块。原 motion/react+@chakra-ui/react+react-icons 已重写为 gsap / 内联 SVG 图标(未引入新依赖)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | leftIcon / rightIcon | slot | — | 左右图标 | | startingValue | number | 0 | 起始值 | | defaultValue | number | 50 | 默认值 | | maxValue | number | 100 | 最大值 | | isStepped | boolean | false | 步进 | | stepSize | number | 10 | 步长 |

DecayCard (Interaction · gsap)

消散卡片,悬停粒子衰减(bundled gsap)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | width | number | 300 | 宽度 | | height | number | 300 | 高度 | | className | string | '' | 根 class |

GlassIcons (Interaction · DOM)

玻璃质感图标(图标经插槽传入,非 React 元素)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | items | { icon: ...; color: string; label: string; customClass?: string }[] | [] | 图标项 | | colorful | boolean | false | 彩色模式 | | className | string | '' | 根 class |

PixelCard (Interaction · Canvas2D + DOM)

像素化卡片,悬停像素动画(Canvas2D null 守卫)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | variant | 'pink'\|'blue'\|'green'\|... | 'pink' | 配色变体 | | className | string | '' | 根 class |

GooeyNav (Interaction · SVG filter)

粘滞导航,SVG gooey 滤镜 + 粒子。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | items | { label: string; href: string }[] | [] | 导航项 | | particleCount | number | 15 | 粒子数 | | particleDistances | [number, number] | [90, 10] | 粒子距离 | | particleR | number | 100 | 粒子半径 | | initialActiveIndex | number | 0 | 初始激活项 | | animationTime | number | 600 | 动画时长 | | timeVariance | number | 300 | 时间方差 | | colors | number[] | [1, 2, 3, 1, 2, 3, 1, 4] | 配色 |

ChromaGrid (Interaction · gsap)

色块网格,悬停高亮(bundled gsap)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | items | { image: string; title: string; subtitle: string; handle: string; borderColor: string; gradient: string; url: string }[] | [] | 网格项 | | className | string | '' | 根 class |

DomeGallery (Interaction · DOM)

穹顶画廊,3D 变换拖拽。原 @use-gesture/react 已重写为原生 pointer 事件(未引入新依赖)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | images | (string \| { src: string; alt?: string })[] | [] | 图片 | | fit | number | 0.8 | 适配 | | fitBasis | 'auto'\|'min'\|'max'\|'width'\|'height' | 'auto' | 适配基准 | | minRadius | number | 400 | 最小半径 | | maxVerticalRotationDeg | number | 0 | 最大纵向旋转 | | segments | number | 34 | 分片数 | | dragDampening | number | 2 | 拖拽阻尼 | | grayscale | boolean | false | 灰度 |

GlassSurface (Interaction · SVG displacement)

玻璃表面,SVG feDisplacementMap 位移扭曲。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | width | number | 300 | 宽度 | | height | number | 200 | 高度 | | borderRadius | number | 50 | 圆角 | | displace | number | 0.5 | 位移量 | | distortionScale | number | -180 | 扭曲缩放 | | redOffset / greenOffset / blueOffset | number | 0/10/20 | RGB 偏移 | | brightness | number | 50 | 亮度 | | opacity | number | 0.93 | 不透明度 | | mixBlendMode | string | 'screen' | 混合模式 | | className | string | '' | 根 class |

TiltedCard (Interaction · gsap)

倾斜卡片,3D 悬停。原 motion/react 已重写为 bundled gsap / 原生 spring。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | imageSrc | string | — | 图片地址 | | altText | string | — | 替代文本 | | captionText | string | — | 标题 | | containerHeight / containerWidth | string | '300px' | 容器尺寸 | | imageHeight / imageWidth | string | '300px' | 图片尺寸 | | rotateAmplitude | number | 12 | 旋转幅度 | | scaleOnHover | number | 1.05 | 悬停缩放 | | showMobileWarning | boolean | false | 移动端警告 | | showTooltip | boolean | false | 提示 | | displayOverlayContent | boolean | false | 显示覆盖内容 | | overlayContent | slot | — | 覆盖内容 |

PillNav (Interaction · gsap)

胶囊导航,悬停高亮(bundled gsap)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | items | { label: string; href: string }[] | [] | 导航项 | | className | string | '' | 根 class |

Stack (Interaction · DOM)

堆叠卡片,自动轮播(卡片经插槽传入)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | randomRotation | boolean | false | 随机旋转 | | sensitivity | number | 150 | 灵敏度 | | sendToBackOnClick | boolean | true | 点击置底 | | cards | slot | — | 卡片 | | autoplay | boolean | false | 自动播放 | | autoplayDelay | number | 2000 | 自动间隔 | | pauseOnHover | boolean | false | 悬停暂停 |

CardNav (Interaction · gsap)

卡片导航,悬停展开链接(bundled gsap)。 | Prop | Type | Default | Description | | --- | --- | --- | --- | | items | { label: string; bgColor: string; textColor: string; links: { label: string; ariaLabel: string }[] }[] | [] | 卡片项 | | className | string | '' | 根 class |


Development

npm install        # install deps
npm run dev        # vite dev server (play/ demo at index.html)
npm run typecheck  # vue-tsc --noEmit
npm run test       # vitest run
npm run build      # type-check + library build to dist/

The dev demo (src/play/App.vue) showcases prop combinations live.


Publish

npm run build      # emits dist/ (es + cjs + d.ts)
npm publish        # uses "files": ["dist"]

License

MIT