glimm
v0.1.3
Published
WebGL sweep transitions for the web — framework-agnostic core with React and Next.js adapters.
Maintainers
Readme
glimm
WebGL sweep transitions for the web. A colour band sweeps across the viewport, your page swaps underneath it at the midpoint, then the band fades out — the iOS "name drop" feel, as a page transition.
- Framework-agnostic core — drive the shader directly from vanilla JS.
- React adapter —
<GlimmProvider>+useGlimm(). - Next.js adapter —
<TransitionLink>,useTransitionRouter(), auto link interception. - Zero runtime dependencies. WebGL only — no CSS, no assets.
- Respects
prefers-reduced-motionand degrades gracefully when WebGL is unavailable.
Install
npm install glimmreact and next are optional peer dependencies — install whichever adapter
you use. The core entry point needs neither.
Quick start (Next.js, App Router)
// app/layout.tsx
import { GlimmProvider, InterceptLinks } from 'glimm/next'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<GlimmProvider palette="prism">
<InterceptLinks />
{children}
</GlimmProvider>
</body>
</html>
)
}<InterceptLinks /> runs every same-origin link click through a sweep. Opt a
link out with data-glimm-skip.
Per-navigation control
'use client'
import { TransitionLink, useTransitionRouter } from 'glimm/next'
// Declarative — a drop-in <Link> replacement:
<TransitionLink href="/about" sweep={{ palette: 'berry', direction: 'rtl' }}>
About
</TransitionLink>
// Programmatic — a drop-in useRouter():
const router = useTransitionRouter()
await save(form)
router.push('/dashboard', { palette: 'ember' })React (without Next.js)
import { GlimmProvider, useGlimm } from 'glimm/react'
function MyButton() {
const { sweep } = useGlimm()
return <button onClick={() => sweep(() => doNavigation())}>Go</button>
}sweep(navigate, options?) plays the band, awaits your navigate callback at
the midpoint, and returns a { midpoint, done, cancel } handle.
Vanilla / framework-agnostic core
import { createShader, playSweep } from 'glimm'
const canvas = document.querySelector('canvas')!
const ctrl = createShader({ canvas, /* palette, bandTight, direction */ })
playSweep(ctrl, {
palette: 'citrus',
onMidpoint: () => swapPageContent(),
onComplete: () => ctrl.destroy(),
})Alternate looks: createMeshShader (vertex-displaced mesh) and
createNamedropShader (radial bulge reveal).
Sweep options
| Option | Default | Notes |
| ------------- | -------- | ----- |
| sweepMs | 1100 | ms for the band to cross the viewport |
| outroMs | 700 | ms for the post-traversal fade-out |
| midpoint | 0.5 | 0–1 progress point where onMidpoint fires |
| palette | prism | preset name or a custom Palette |
| direction | ltr | ltr | rtl | ttb | btt |
| easing | easeOutQuart | preset name or an (p) => number fn |
| bandTight | — | band sharpness |
| peakAlpha | 1 | caps the band's peak opacity |
| brightness | 1 | 0–1.5, multiplies band RGB (dim it on dark backgrounds) |
| waveAmount | 1 | 0–2, edge wave displacement |
| rippleAmount| 1 | 0–2, vertical ripple texture |
| waveSpeed | 1 | 0–3, multiplies time-based motion |
| swellAmount | 0.8 | 0–1, depth swell |
| onMidpoint | — | fires when the band reaches midpoint — swap pages here |
| onComplete | — | fires when the outro fade finishes |
Built-in palettes: prism, berry, lagoon, citrus, azure,
ember. Build your own with accentPair,
accentChain, or shuffleAccentPalette.
Built-in easings: linear, easeOutQuart, easeOutCubic, easeInCubic,
easeInOutCubic, easeOutExpo, easeInOutQuint, snap, ease, back.
Entry points
| Import | Use for |
| --------------- | ------- |
| glimm | Framework-agnostic core: shader factories, playSweep, palettes, easings, colour math. |
| glimm/react | <GlimmProvider> and useGlimm() for any React app. |
| glimm/next | Everything in glimm/react plus <TransitionLink>, useTransitionRouter(), and interceptLinks / <InterceptLinks>. |
Import the provider and hooks from a single entry point per app so they share one React context.
License
Proprietary — all rights reserved. This package is published for installation only; it is not licensed for redistribution, modification, or reuse.
