Lens Card
motiq/lens-cardFreeComponent
A refraction lens that floats over your own content: everything under the glass magnifies with a chromatic fringe while the background grid physically bends around the rim. A duplicated scaled clone clipped by a moving circle() - no filters, no repaint storms - with a spring-lagged centre that drifts on its own when unattended. Clones are aria-hidden, so AT reads the content once.
Live preview
live · rendered by the registry
Rendered by motiq on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://www.motiq.dev/r/lens-card.jsonSource
1"use client";23import * as React from "react";45import { cn } from "@/lib/utils";6import { useReducedMotion, useVisibilityPause } from "@/lib/motiq";78/* -------------------------------------------------------------------------- */9/* Types */10/* -------------------------------------------------------------------------- */1112export interface LensLag {13 stiffness: number;14 damping: number;15}1617export interface LensCardProps extends React.HTMLAttributes<HTMLDivElement> {18 /** The content under the glass — text, charts, images, code all work. */19 children: React.ReactNode;20 /** Lens radius in px. */21 radius?: number;22 /** Optical magnification of the clipped clone. */23 magnification?: number;24 /** Chromatic fringe offset in px. 0 disables the dispersion layer. */25 chromatic?: number;26 /** Follow spring — lower stiffness reads as heavier glass. */27 lag?: LensLag;28 /** Draw the canvas grid that physically bends around the lens rim. */29 gridBend?: boolean;30 /** Drift the lens on a slow two-frequency orbit when the pointer is away. */31 idleDrift?: boolean;32 /** Render the rim highlight ring. */33 showRing?: boolean;34 /** Deterministic seed for the idle-drift phase (SSR-stable). */35 seed?: number;36 /** Stop the rAF loop when scrolled offscreen or the tab is hidden. */37 pauseWhenHidden?: boolean;38 /** Force the static, motion-free variant regardless of system preference. */39 reducedMotion?: boolean;40}4142/* -------------------------------------------------------------------------- */43/* Physics */44/* -------------------------------------------------------------------------- */4546interface Spring {47 x: number;48 v: number;49}5051const mkSpring = (x = 0): Spring => ({ x, v: 0 });5253/** Semi-implicit Euler spring with substeps — stable at low/irregular frame rates. */54function spring(s: Spring, target: number, k: number, c: number, dt: number): number {55 const n = dt > 0.012 ? Math.ceil(dt / 0.008) : 1;56 const h = dt / n;57 for (let i = 0; i < n; i++) {58 s.v += (-k * (s.x - target) - c * s.v) * h;59 s.x += s.v * h;60 }61 return s.x;62}6364const clamp = (v: number, a: number, b: number) => (v < a ? a : v > b ? b : v);6566/** mulberry32 — no Math.random at render or module scope (SSR-stable). */67function makeRng(seed: number) {68 let a = seed >>> 0;69 return () => {70 a = (a + 0x6d2b79f5) | 0;71// … truncated
What it pulls in
Other registry items
Files it writes
More from motiq
All 100 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Activity Streamactivity-stream | motiq | Components | Free | 1 dep | |
| Adaptive Safe-Zone Gridadaptive-safe-zone-grid | motiq | Components | Free | no deps | |
| Agent Run Timelineagent-run-timeline | motiq | Components | Free | 1 dep | |
| AI Response Streamai-response-stream | motiq | Components | Free | 1 dep | |
| Animated Accordionanimated-accordion | motiq | Components | Free | 2 deps | |
| Animated Buttonanimated-button | motiq | Components | Free | 1 dep | |
| Animated Dialoganimated-dialog | motiq | Components | Free | 2 deps | |
| Animated Gridanimated-grid | motiq | Components | Free | 2 deps |
