Glass
lore-glass/glassFreeComponent
A cross-browser liquid-glass lens engine built on SVG feDisplacementMap. Refracts live DOM content through movable lens regions with a circle-profile bezel, dome bulge, chromatic aberration, and baked specular highlights. Ships with a dependency-free motion core (overshoot tweens, springs, rubber-band) for gel-like interactions. Independent implementation of the displacement-map technique described in Aave Labs' 'Building Glass for the Web'.
Live preview
live · rendered by the registry
Rendered by lore-glass on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://loreglasses.com/r/glass.jsonSource
1"use client";23import {4 GlassWebGLRenderer,5 isRasterChild,6 webglAvailable,7} from "@/components/ui/glass-webgl";8import { cn } from "@/lib/utils";9import {10 type ComponentProps,11 type ReactNode,12 type RefObject,13 useCallback,14 useEffect,15 useId,16 useRef,17 useState,18 useSyncExternalStore,19} from "react";2021const SLOTS = 5;22const MAP_CACHE_LIMIT = 64;23const EDGE_BIAS = 0.5;2425interface MapParams {26 depth: number;27 domeDepth: number;28 edgeExponent: number;29 edgeStrength: number;30 edgeWidth: number;31 glowExponent: number;32 glowSpread: number;33 glowStrength: number;34 halfH: number;35 halfW: number;36 radius: number;37 size: number;38 splay: number;39 specularAngle: number;40 sdfBoundary?: boolean;41 edgeFalloff?: boolean;42 alphaBlend?: boolean;43}4445interface GlassDynamics {46 zoom?: number;47 depthMul?: number;48 mapDims?: { halfW: number; halfH: number; radius: number };49}5051function clamp01(v: number): number {52 return v < 0 ? 0 : v > 1 ? 1 : v;53}5455function erf(x: number): number {56 return Math.tanh(1.7724538509 * x);57}5859function sphereAvgSlope(r: number, halfDim: number): number {60 let sum = 0;61 for (let i = 0; i <= 200; i++) {62 const a = (i / 200) * halfDim;63 const s = a / Math.sqrt(r * r - a * a);64 sum += i === 0 || i === 200 ? 0.5 * s : s;65 }66 return sum / 200;67}6869interface DomeConstants {70 rx: number;71 ry: number;72 scaleX: number;73 scaleY: number;74}7576function computeDomeConstants(77 domeDepth: number,78 halfW: number,79 halfH: number80): DomeConstants {81 const h = Math.max(0.01, Math.min(domeDepth, Math.min(halfW, halfH) - 1));82 const rx = (halfW * halfW + h * h) / (2 * h);83 const ry = (halfH * halfH + h * h) / (2 * h);84 const ax = sphereAvgSlope(rx, halfW);85 const ay = sphereAvgSlope(ry, halfH);86 return {87 rx,88 ry,89 scaleX: ax > 0 ? 0.5 / ax : 1,90 scaleY: ay > 0 ? 0.5 / ay : 1,91 };92}9394function domeGradient(p: number, r: number, scale: number): number {95 const c = Math.min(p, 0.999 * r);96 return (c / Math.sqrt(r * r - c * c)) * scale;97}9899function generateLensMap(p: MapParams): string | null {100 if (p.halfW < 2 || p.halfH < 2) {101 return null;102 }103 const sdfBoundary = p.sdfBoundary ?? true;104 const edgeFalloff = p.edgeFalloff ?? true;105 const size = p.size;106 const canvas = document.createElement("canvas");107 canvas.width = size;108 canvas.height = size;109 const ctx = canvas.getContext("2d");110 if (!ctx) {111 return null;112 }113 const image = ctx.createImageData(size, size);114// … truncated
Files it writes
More from lore-glass
All 10 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Glass Buttonglass-button | lore-glass | Components | Free | no deps | |
| Glass Dialogglass-dialog | lore-glass | Components | Free | 1 dep | |
| Glass Dockglass-dock | lore-glass | Components | Free | 1 dep | |
| Glass Inputglass-input | lore-glass | Components | Free | 1 dep | |
| Glass Popoverglass-popover | lore-glass | Components | Free | 1 dep | |
| Glass Sliderglass-slider | lore-glass | Components | Free | no deps | |
| Glass Switchglass-switch | lore-glass | Components | Free | no deps | |
| Glass Tabsglass-tabs | lore-glass | Components | Free | 1 dep |
