BannerPattern
neon-ui/banner-patternFreeComponent
The neon.com banner dot pattern as a live WebGL surface: a square-dot grid sampling a drifting green-to-amber field.
Install it
npx shadcn@latest add https://ui.neon.com/r/banner-pattern.jsonSource
1"use client";23/*4 * BannerPattern: neon.com's banner dot pattern as a live WebGL5 * surface — a square-dot grid masking a drifting color field, so6 * every dot samples the green-to-amber glow behind it. A brand7 * background for banners, cards, and covers. Static single frame8 * under reduced motion. GLSL lives in banner-pattern-shader.ts.9 */1011import { useEffect, useRef } from "react";12import type { ComponentProps } from "react";1314import { cn } from "@/lib/utils";1516import { BANNER_FRAGMENT, BANNER_VERTEX } from "./banner-pattern-shader";1718export type BannerPatternPalette = [19 base: string,20 green: string,21 sage: string,22 amber: string,23 cream: string,24 rust: string,25];2627export type BannerPatternProps = Omit<ComponentProps<"canvas">, "children"> & {28 /** Animation speed multiplier; 0 freezes the field. */29 speed?: number;30 /** Grid cell size in CSS pixels. */31 cell?: number;32 /** 0-0.5 dot half-width as a fraction of the cell. */33 dotSize?: number;34 /** 0-1 unmasked ambient glow behind the dots. */35 haze?: number;36 /** 0-1 per-dot brightness variance. */37 jitter?: number;38 /** The field, painted back to front: [base, green, sage, amber, cream, rust]. */39 colors?: BannerPatternPalette;40};4142/**43 * Seconds for a dial or palette change to close ~63% of its gap —44 * uniforms ease toward their targets each frame, so a dragged slider45 * or a palette switch glides instead of snapping.46 */47const SMOOTH_TAU = 0.12;4849const DEFAULT_COLORS: BannerPatternPalette = [50 "#0a0b09",51 "#34d59a",52 "#97b47d",53 "#feaa2c",54 "#ffeacc",55 "#b03323",56];5758const parseColor = (css: string): [number, number, number] => {59 const probe = document.createElement("canvas");60 probe.width = 1;61 probe.height = 1;62 const context = probe.getContext("2d");6364 if (!context) {65 return [0, 0, 0];66 }6768 context.fillStyle = css;69 context.fillRect(0, 0, 1, 1);70 const [r, g, b] = context.getImageData(0, 0, 1, 1).data;71 return [(r ?? 0) / 255, (g ?? 0) / 255, (b ?? 0) / 255];72};7374const warnDev = (message: string) => {75 if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {76 console.warn(message);77 }78};7980const compile = (81 gl: WebGLRenderingContext,82 type: number,83 source: string84): WebGLShader | null => {85 const shader = gl.createShader(type);8687 if (!shader) {88 return null;89 }9091 gl.shaderSource(shader, source);92 gl.compileShader(shader);9394 if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {95 warnDev(96// … truncated
What it pulls in
Other registry items
Files it writes
More from neon-ui
All 77 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| ActivityFeedactivity-feed | neon-ui | Components | Free | 2 deps | |
| AgentChatagent-chat | neon-ui | Components | Free | 6 deps | |
| AnimatedWashanimated-wash | neon-ui | Components | Free | no deps · 2 files | |
| ApiKeyListapi-key-list | neon-ui | Components | Free | 2 deps | |
| AppCardapp-card | neon-ui | Components | Free | 2 deps | |
| AppCreatorapp-creator | neon-ui | Components | Free | 2 deps | |
| AuthFormauth-form | neon-ui | Components | Free | no deps | |
| AutoscaleChartautoscale-chart | neon-ui | Components | Free | 1 dep |
