Glow Orb
nexvyn/glow-orbFreeComponent
A WebGL fbm-noise glow orb with state-driven colors, volume-responsive scale and glow, idle and connecting pulse animations, and a settle-back transition.
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/glow-orb.jsonSource
1'use client'23import { useEffect, useLayoutEffect, useRef, type AriaAttributes, type CSSProperties } from 'react'4import { useReducedMotion } from 'motion/react'5import { useCssColorRgb } from '@/lib/hooks/use-css-color-rgb'67const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect89export type OrbState = 'idle' | 'connecting' | 'listening' | 'thinking' | 'speaking' | 'error'1011type DataAttributeValue = string | number | boolean | null | undefined1213export interface OrbHtmlAttributes extends AriaAttributes {14 id?: string15 title?: string16 role?: string17 tabIndex?: number18 [dataAttribute: `data-${string}`]: DataAttributeValue19}2021export interface GlowOrbProps extends OrbHtmlAttributes {22 state: OrbState23 volume: number24 size: number25 className?: string26 style?: CSSProperties27 disabled?: boolean28 interactive?: boolean29 onClick?: () => void30}3132type RGB = [number, number, number]3334const VERT = `35attribute vec2 a_pos;36void main() {37 gl_Position = vec4(a_pos, 0.0, 1.0);38}39`4041const FRAG = `42#ifdef GL_FRAGMENT_PRECISION_HIGH43precision highp float;44#else45precision mediump float;46#endif4748uniform vec2 u_resolution;49uniform float u_time;50uniform vec3 u_color;5152float hash(vec2 p) {53 return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);54}5556float noise(vec2 p) {57 vec2 i = floor(p);58 vec2 f = fract(p);59 vec2 u = f * f * (3.0 - 2.0 * f);60 return mix(61 mix(hash(i + vec2(0.0, 0.0)), hash(i + vec2(1.0, 0.0)), u.x),62 mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0, 1.0)), u.x),63 u.y64 );65}6667float fbm(vec2 p) {68 float v = 0.0;69 float a = 0.55;70 for (int i = 0; i < 4; i++) {71 v += a * noise(p);72 p *= 2.0;73 a *= 0.5;74 }75 return v;76}7778void main() {79 vec2 uv = gl_FragCoord.xy / u_resolution.xy;80 vec2 c = uv - 0.5;81 float r = length(c);82 float t = u_time;8384 // fake sphere depth: 1 at center, 0 at rim85 float z = sqrt(max(1.0 - dot(c, c) * 4.0, 0.0));8687 // wrap the cloud field around the sphere and drift it sideways88 vec2 drift = vec2(t * 0.35, -t * 0.16);89 vec2 p = c * (2.4 + (1.0 - z) * 1.6) + drift;9091 // domain-warped fbm = soft billowing clouds92 vec2 q = vec2(fbm(p + t * 0.12), fbm(p + vec2(4.7, 2.3) - t * 0.09));93 float clouds = fbm(p * 1.6 + 1.4 * q);9495 vec3 sky = u_color;96 vec3 skyLight = mix(u_color, vec3(1.0), 0.55);97 vec3 cloud = vec3(0.99, 1.0, 1.0);9899 vec3 col = mix(sky, skyLight, smoothstep(0.30, 0.60, clouds));100 col = mix(col, cloud, smoothstep(0.56, 0.84, clouds));101102// … 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 |
