Fluid Orb
nexvyn/fluid-orbFreeComponent
A WebGL fluid orb in muted/neutral design tokens with sphere normals, fBm noise, and audio-reactive pulse.
Live preview
live · rendered by the registry
Rendered by nexvyn on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ui.nexvyn.dev/r/fluid-orb.jsonSource
1'use client'23import {4 forwardRef,5 useEffect,6 useLayoutEffect,7 useMemo,8 useRef,9 useState,10 type ComponentProps,11} from 'react'12import { useReducedMotion } from 'motion/react'13import { cn } from '@/lib/utils'14import { useCssColorRgb } from '@/lib/hooks/use-css-color-rgb'1516export type FluidOrbProps = ComponentProps<'div'> & {17 size?: number18 /**19 * Hex color override. When omitted, uses the design-system muted/neutral20 * foreground token so the orb follows light/dark theme.21 */22 color?: string23 audioLevel?: number24}2526const VERT = [27 'attribute vec2 a_pos;',28 'void main() {',29 ' gl_Position = vec4(a_pos, 0.0, 1.0);',30 '}',31].join('\n')3233const FRAG = [34 'precision mediump float;',35 'uniform vec2 u_resolution;',36 'uniform float u_time;',37 'uniform float u_pulse;',38 'uniform vec3 u_color;',39 'float hash(vec2 p) {',40 ' return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);',41 '}',42 'float noise(vec2 p) {',43 ' vec2 i = floor(p);',44 ' vec2 f = fract(p);',45 ' vec2 u = f * f * (3.0 - 2.0 * f);',46 ' return mix(',47 ' mix(hash(i + vec2(0.0, 0.0)), hash(i + vec2(1.0, 0.0)), u.x),',48 ' mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0, 1.0)), u.x),',49 ' u.y',50 ' );',51 '}',52 'float fbm(vec2 p) {',53 ' float v = 0.0;',54 ' float a = 0.5;',55 ' for (int i = 0; i < 5; i++) {',56 ' v += a * noise(p);',57 ' p *= 2.0;',58 ' a *= 0.5;',59 ' }',60 ' return v;',61 '}',62 'void main() {',63 ' vec2 uv = gl_FragCoord.xy / u_resolution.xy;',64 ' vec2 p = uv - 0.5;',65 ' p.x *= u_resolution.x / max(u_resolution.y, 1.0);',66 ' float dist = length(p);',67 ' float edge = smoothstep(0.5, 0.49, dist);',68 ' vec3 sphereNormal = normalize(vec3(p.x, p.y, sqrt(max(0.0, 0.25 - dot(p, p)))));',69 ' float t = u_time * 0.15;',70 ' vec2 flow = vec2(t * 0.5, t * 0.3);',71 ' float fluid = fbm(p * 3.0 + flow);',72 ' fluid = pow(fluid, 1.5);',73 ' vec3 keyLightDir = normalize(vec3(-0.5, 0.6, 0.5));',74 ' vec3 fillLightDir = normalize(vec3(0.4, -0.3, 0.2));',75 ' float keyLight = max(dot(sphereNormal, keyLightDir), 0.0);',76 ' float fillLight = max(dot(sphereNormal, fillLightDir), 0.0);',77 ' vec3 viewDir = vec3(0.0, 0.0, 1.0);',78 ' vec3 halfVec = normalize(keyLightDir + viewDir);',79 ' float specular = pow(max(dot(sphereNormal, halfVec), 0.0), 48.0);',80 ' float coreRadius = 0.16 + 0.18 * u_pulse;',81 ' float coreMask = 1.0 - smoothstep(coreRadius, coreRadius + 0.22, dist);',82// … truncated
What it pulls in
npm packages
Files it writes
More from nexvyn
All 33 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Badgebadge | nexvyn | Components | Free | 2 deps · 2 files | |
| Bars Themebars-theme | nexvyn | Components | Free | 1 dep · 3 files | |
| Bounce Sidebarbounce-sidebar | nexvyn | Components | Free | 1 dep · 2 files | |
| Breadcrumbsbreadcrumbs | nexvyn | Components | Free | 1 dep · 2 files | |
| Checkboxcheckbox | nexvyn | Components | Free | 1 dep · 3 files | |
| Clipboard Fieldclipboard-field | nexvyn | Components | Free | no deps · 2 files | |
| Color Pickercolor-picker | nexvyn | Components | Free | no deps · 16 files | |
| Comboboxcombobox | nexvyn | Components | Free | 1 dep · 2 files |
