# runets
> Components, springs and WebGL 2 shader effects for React, in TypeScript, by Ziyam Khan. MIT. Source: https://github.com/ziyam-khan/runets. Every entry has a live demo at its page.
## Install
```sh
npm i github:ziyam-khan/runets
```
Peer dependencies: react and react-dom 19, motion 12, @base-ui/react, lucide-react. Load the styles once (or bring your own tokens and only kit.css):
```ts
import 'runets/styles/theme.css'
import 'runets/styles/kit.css'
```
Or copy the files an entry lists into your project, keeping their folders.
## Effects
Every effect is one component, ``, placed inside a positioned parent. It draws on WebGL 2, draws a still frame on a software renderer, pauses off screen and settles under reduced motion. Props shared by every effect:
- effect (string): The effect’s id, as in its entry’s address.
- preset (string): One of its entry’s presets; the first by default.
- params (Params): Any parameter from its entry’s parameters, over the preset.
- place ('under' | 'over'): Under the parent’s content (fills, halos) or over it (sparkles, glass). Default under.
- radius (number): Corner radius in points; the parent’s own border radius by default.
- backdrop (string | Paint): What glass and distortion read: an image URL, or a function that paints a canvas the size of the parent.
- mask (Paint): An alpha mask for mask glow and text sheen.
- hot (boolean): Drives heat: the layer lights in 60 ms and cools over half a second instead of cutting off.
- trigger (number): Change it to fire a one-shot now (ping, ripple, burst, shockwave, zap).
- wake (number): Change it to redraw for a second when something the layer reads, such as its occluders, moves on its own.
- shape ((time, w, h) => Rect): The effect’s shape inside the parent, per frame: a lens that drifts.
## Index
### Motion
Springs as duration and bounce, presence that blurs in and out, labels that roll.
- [Springs](https://ziyamkhan.com/my-components/springs/): Eight named springs, each a duration and a bounce with SwiftUI’s parameterisation, in enter and exit pairs. Exits settle sooner than entrances.
- [Presence](https://ziyamkhan.com/my-components/presence/): Things entering or leaving in place blur in from 96% scale and blur out the same way; one that comes back mid-exit revives from where it is.
- [Rolling text](https://ziyamkhan.com/my-components/rolling-text/): A label whose changed characters roll, up as a value rises and down as it falls, while the unchanged ones slide into place and the width springs.
- [Motion blur](https://ziyamkhan.com/my-components/motion-blur/): Blur along the direction of travel while something flies, measured from its velocity; at rest it is sharp.
### Text
Words that change in place: a terminal that retypes itself, labels that swap, a marquee.
- [Marquee](https://ziyamkhan.com/my-components/marquee/): A row that slides on a seamless loop at a speed in pixels per second, and holds still under the pointer or focus.
- [Word swap](https://ziyamkhan.com/my-components/word-swap/): Words that take turns in one place: the new one drops in out of a blur as the old one sinks away. Pure CSS transitions.
- [Terminal](https://ziyamkhan.com/my-components/terminal/): Prompt lines that retype their own words while a block cursor smears from line to line, like smear-cursor in Neovim.
### Effects
Light and distortion as layers beside an element: glow, pulses, electricity, fire, glass, CRT.
- [Glow](https://ziyamkhan.com/my-components/glow/): Bloom around a shape: a soft breathing halo, neon that cools instead of cutting off, a spectrum flowing round the border, or text bloom from a mask.
- [Pulse](https://ziyamkhan.com/my-components/pulse/): Light that beats: radar rings, a breathing halo, a heartbeat whose earlier rings keep fading under the new one, a ping that winds up, lands and cools, and a tap ripple.
- [Electricity](https://ziyamkhan.com/my-components/electricity/): Lightning that strikes, holds and re-strikes down the same channel: an arc between two points with forks that shoot out and cool, a current round a border, or a calm charged hairline for UI.
- [Fire](https://ziyamkhan.com/my-components/fire/): Flames off a top edge with embers that are flung up, slow to a buoyant drift and cool from white to red; plasma hugging a border; or a little heat for a button.
- [Heat haze](https://ziyamkhan.com/my-components/heat-haze/): Hot air rising off an edge: the backdrop wobbles in a column above it, strongest a little up where the air has risen.
- [Shockwave](https://ziyamkhan.com/my-components/shockwave/): A ring of displaced light expanding from a point, with a little chromatic split on its front. A one-shot.
- [Liquid glass](https://ziyamkhan.com/my-components/lens/): Glass that bends what is behind it: the rim squeezes the page, the middle stays sharp and colour splits only at the edge. Two lenses melt together like liquid.
- [CRT](https://ziyamkhan.com/my-components/crt/): An old tube: the picture bulges, scanlines and an aperture grille cross it, a roll bar drifts down and colour bleeds sideways.
- [Chromatic split](https://ziyamkhan.com/my-components/chroma-split/): Red and blue pulled apart from green, with optional glitch slices that jump sideways a few frames at a time.
- [Shimmer](https://ziyamkhan.com/my-components/shimmer/): A band of light sweeping across a shape: a skeleton shimmer while content loads, or a sheen across text that is still thinking. Under reduced motion the surface breathes instead.
- [Sparkles](https://ziyamkhan.com/my-components/sparkles/): Four-point stars round a shape, each with its own size, twinkle and spin, taking turns. A burst pops every star once and flings it out a little.
- [Aurora](https://ziyamkhan.com/my-components/aurora/): Three curtains of light with bright lower hems, swaying across a surface. Their heights and warps are a CPU table per frame; the rays are noise per pixel.
- [Grain](https://ziyamkhan.com/my-components/grain/): Film grain: triangular noise per pixel that lightens and darkens, static or redrawn a few times a second.
- [Spotlight mark](https://ziyamkhan.com/my-components/spotlight-mark/): A stroked logo lit by a light that follows the pointer across it on a spring.
### Fills
Surfaces painted by a shader: metal, gradients, dither, glass, blobs, cells, waves, print, plastic.
- [Liquid metal](https://ziyamkhan.com/my-components/liquid-metal/): A polished conductor in a photo studio: a domed slab whose surface flows and pools, Fresnel to white at grazing angles, a little thin-film colour where it bends hardest.
- [Mesh gradient](https://ziyamkhan.com/my-components/mesh-gradient/): Up to six colours, each owning a point that wanders; Shepard weights blend them in OKLab, so the middle never turns muddy.
- [Dither](https://ziyamkhan.com/my-components/dither/): Ordered dithering of a tone into a palette: Bayer matrices, a blue-noise tile built by void-and-cluster, or white noise, over a ramp, a radial, drifting noise or the backdrop.
- [Grain gradient](https://ziyamkhan.com/my-components/grain-gradient/): A linear, radial or conic ramp whose position is scattered by triangular noise, so the colours stipple into each other like risograph ink.
- [Fluted glass](https://ziyamkhan.com/my-components/fluted-glass/): Reeded glass: every rib is a cylindrical lens that returns the strip under it squeezed and flipped, with a sheen down the lit side and a shaded groove.
- [Metaballs](https://ziyamkhan.com/my-components/metaballs/): Glossy blobs that drift and melt into each other where their fields add past the surface, each carrying its colour into the merge.
- [Swirl](https://ziyamkhan.com/my-components/swirl/): Ink folding into itself: noise twisted round the centre and warped by more noise, read through a colour ramp.
- [Voronoi](https://ziyamkhan.com/my-components/voronoi/): Cells whose seed points orbit their own spots, with exact seams to every neighbour and a little depth toward each cell centre.
- [Waves](https://ziyamkhan.com/my-components/waves/): Bands of colour stacked like a coastline or a dune field, each front shading the band behind it just above its crest.
- [Halftone](https://ziyamkhan.com/my-components/halftone/): A print screen: dots on a rotated grid sized by tone, merging across cell lines where the ink is heavy.
- [Plastic](https://ziyamkhan.com/my-components/plastic/): A keycap under one soft light: the diffuse base keeps its colour, a GGX highlight widened by the size of the light, and a faint sky at grazing angles.
### Weather
The four skies of the home page, and sakura petals on the wind of your pointer.
- [Rain](https://ziyamkhan.com/my-components/rain/): Three depths of slanted streaks that catch the light behind them, splashes on the wet ground, and drops sliding down the glass in surges, each a tiny fisheye showing the scene upside down.
- [Snow](https://ziyamkhan.com/my-components/snow/): Four depths of flakes on the wind: fine far flakes, nearer ones that sway, and big out-of-focus bokeh flakes close to the glass; snow lifting off the ground; frost creeping in from the corners.
- [Shooting stars](https://ziyamkhan.com/my-components/meteors/): Stars that scintillate, and meteors in staggered slots: one crosses soon after the scene arrives, trails grow and taper, the odd fireball lights the sky. The land hides anything behind it.
- [Sandstorm](https://ziyamkhan.com/my-components/sandstorm/): A storm wall rolling along the horizon behind the dunes, its billows domain-warped and torn at the top, with dust gusts and grains streaming past in front.
- [Petal wind](https://ziyamkhan.com/my-components/petal-wind/): Sakura petals that tumble and flip as they fall. Move the pointer and the air moves with it, then settles.
### Light
A lamp above the page: soft shadows and rim light from raised elements.
- [Light](https://ziyamkhan.com/my-components/light/): A lamp above the page: raised elements cast soft shadows whose penumbra widens with distance, their bevels catch the light, and the rest of the page falls into shade.
### Controls
Buttons, toggles and small indicators, in every variant, size and state.
- [Button](https://ziyamkhan.com/my-components/button/): Ten variants in three sizes and five states. A rolling label springs the width as it changes.
- [Icon button](https://ziyamkhan.com/my-components/icon-button/): A square button whose name comes from its label or its help text.
- [Switch](https://ziyamkhan.com/my-components/switch/): Compact and standard. The knob travels on a snappy spring; the track fills with the accent.
- [Checkbox](https://ziyamkhan.com/my-components/checkbox/): Checked, unchecked and mixed, with the tick drawn on as it checks.
- [Radio group](https://ziyamkhan.com/my-components/radio-group/): One of a few, arrow keys move the choice.
- [Segmented control](https://ziyamkhan.com/my-components/segmented-control/): A pill that slides to the chosen segment, its width leading its position.
- [Badge](https://ziyamkhan.com/my-components/badge/): A small label for status and counts: neutral, accent, success, warning, danger.
- [Keybind](https://ziyamkhan.com/my-components/keybind/): Keys as keycaps, in the platform’s order.
- [Spinner and loader](https://ziyamkhan.com/my-components/spinner/): A ring that spins and three dots that wait their turn.
- [Progress](https://ziyamkhan.com/my-components/progress/): A bar and a circle that spring to each new value and read their percentage aloud.
- [Copy button](https://ziyamkhan.com/my-components/copy-button/): Copies text and answers with a tick, or a cross if the browser refused, then turns back. It never changes size.
- [Filter keys](https://ziyamkhan.com/my-components/filter-keys/): Raised keys, one down at a time, each with its count; a press squashes the key, and the result count rolls.
### Inputs
Text, choices and shortcuts.
- [Text field](https://ziyamkhan.com/my-components/text-field/): Input and text area inside a field with its label, description and error, all wired for assistive tech.
- [Select](https://ziyamkhan.com/my-components/select/): A list of options in a popover anchored to its trigger, grouped, with the chosen one checked.
- [Combobox](https://ziyamkhan.com/my-components/combobox/): Type to filter, arrows to move, Enter to choose; the list’s height springs as it filters.
- [Shortcut recorder](https://ziyamkhan.com/my-components/shortcut-recorder/): Press a combination and it is recorded as keycaps.
- [Elastic slider](https://ziyamkhan.com/my-components/elastic-slider/): A native range input with give: drag past an end and the track stretches toward you, then springs back.
### Navigation
Ways through a page or a site: signposts, outlines and rails.
- [Outline](https://ziyamkhan.com/my-components/outline/): Links to the sections of a page, indented by depth, with a mark on the one you are reading. Compact shows ticks.
- [Signpost](https://ziyamkhan.com/my-components/signpost/): Wooden signs on a picture, each a toggle: boards on a pole, arrows to either side, an effect on the chosen one and a sheen on the rest.
### Overlays
Menus, popovers, tooltips, cards on hover, dialogs and toasts.
- [Menu](https://ziyamkhan.com/my-components/menu/): Items, checkbox and radio items, a submenu and shortcuts, opening out of its button.
- [Popover](https://ziyamkhan.com/my-components/popover/): A surface anchored to its trigger that flips and shifts to stay in the window.
- [Tooltip](https://ziyamkhan.com/my-components/tooltip/): Help that waits a moment on hover and describes its control.
- [Hover card](https://ziyamkhan.com/my-components/hover-card/): A preview that rests on hover before it opens.
- [Dialog](https://ziyamkhan.com/my-components/dialog/): A modal that grows out of its button, traps focus and gives it back.
- [Toast](https://ziyamkhan.com/my-components/toast/): Messages that queue, stack and swipe away, announced politely.
- [Share menu](https://ziyamkhan.com/my-components/share-menu/): Copy the link, share through the device's own sheet, or open any link you give it. A details element: works without script.
- [Brand menu](https://ziyamkhan.com/my-components/brand-menu/): Right-click a logo and, instead of the browser's menu, a dialog offers the brand's own actions.
### Surfaces
Cards, lists, disclosure and the app shell.
- [Card](https://ziyamkhan.com/my-components/card/): A raised surface: neutral, info, warning and error.
- [List](https://ziyamkhan.com/my-components/list/): Rows with a selection that springs between them and arrow-key navigation.
- [Accordion](https://ziyamkhan.com/my-components/accordion/): Sections that open one at a time, the chevron springing as they do.
- [Collapsible](https://ziyamkhan.com/my-components/collapsible/): One region that opens and closes on the disclosure spring.
- [Shell](https://ziyamkhan.com/my-components/shell/): A sidebar that resizes, collapses on a spring and peeks back when the pointer rests on the edge.
- [Spotlight](https://ziyamkhan.com/my-components/spotlight/): A surface with a soft light that follows the pointer while it is over it, written to CSS variables, not React state.
- [Scroll fade](https://ziyamkhan.com/my-components/scroll-fade/): A scroll box whose edges fade only where there is more to scroll, and stay crisp at either end.
### Content
The pieces a portfolio is made of: shelves, timelines, cards and quotes.
- [Testimonial](https://ziyamkhan.com/my-components/testimonial/): A quote and who said it, with a picture or their initials: a figure, a blockquote and a caption.
- [Timeline](https://ziyamkhan.com/my-components/timeline/): Work and study in groups, each under its own colour: where on the left, what and when on the right. Server-rendered.
- [Heat card](https://ziyamkhan.com/my-components/heat-card/): A card that warms while you look at it, pointer or keyboard, and cools slowly when you leave instead of switching off.
- [Badge groups](https://ziyamkhan.com/my-components/badge-groups/): Labelled groups of badges in one panel, flowing into as many columns as fit. Renders on the server: no JavaScript.
- [Article list](https://ziyamkhan.com/my-components/article-list/): A row per article: date and tag on the left, title and a line on the right. Drafts are marked for the build to catch.
- [Bookshelf](https://ziyamkhan.com/my-components/bookshelf/): Books stand spine out. The one you open turns on its spine to show its cover, and its neighbours slide aside by exactly the space it takes.
### Data
A virtual file tree, a sortable table, a lineage drawn as a tree and a year of activity as squares.
- [Tree](https://ziyamkhan.com/my-components/tree/): A file tree: folders before files, natural order, a cursor the arrow keys move, chains of single folders shown as one row.
- [Table](https://ziyamkhan.com/my-components/table/): Sortable columns, a cursor row, zebra stripes and figures that line up.
- [Network map](https://ziyamkhan.com/my-components/network-map/): A hub joined to its nodes; done nodes fill in and their links go solid, the rest stay hollow and dashed.
- [Lineage tree](https://ziyamkhan.com/my-components/lineage-tree/): Which work builds on which: a tier per generation, elbow wires that draw in, one focal node.
- [Contribution graph](https://ziyamkhan.com/my-components/contribution-graph/): A year of daily counts as squares, a column per week, busier days in stronger accent. Drawn on the server; a tip reads out each day.
### Play
Small toys: things to drag, slide and break.
- [Slide to unlock](https://ziyamkhan.com/my-components/slide-to-unlock/): Drag the handle to the end, or use the arrow keys, and the action fires; let go early and it springs back.
- [Brick breaker](https://ziyamkhan.com/my-components/brick-breaker/): A small brick breaker on a canvas, in the theme's colours: pointer or arrow keys, Space to launch.
## Entries
### Springs
https://ziyamkhan.com/my-components/springs/
Eight named springs, each a duration and a bounce with SwiftUI’s parameterisation, in enter and exit pairs. Exits settle sooner than entrances.
Features:
- Eight named springs as (duration, bounce), with SwiftUI’s parameterisation: ω = 2π / duration, ζ = 1 − bounce.
- Each has an exit that settles sooner than its entrance.
- Also as CSS linear() curves for transitions.
```tsx
import { snappy, spring } from 'runets'
```
Files: src/motion.ts
Uses: motion
Accessibility:
- Pair with reduced motion: swap travel for a short fade (reducedFade).
### Presence
https://ziyamkhan.com/my-components/presence/
Things entering or leaving in place blur in from 96% scale and blur out the same way; one that comes back mid-exit revives from where it is.
Features:
- Enters from 4 px of blur at 96% scale, leaves the same way.
- Revives mid-exit from where it is.
```tsx
import { blurReplace } from 'runets'
{open && }
```
Files: src/motion.ts
Uses: motion
Accessibility:
- Reduced motion keeps only the fade.
### Rolling text
https://ziyamkhan.com/my-components/rolling-text/
A label whose changed characters roll, up as a value rises and down as it falls, while the unchanged ones slide into place and the width springs.
Features:
- Unchanged characters keep their key and slide; changed ones roll out one edge and in the other.
- Direction from the value: up as it rises, down as it falls.
- A 0.03 s stagger per changed glyph, capped at six; the width springs.
```tsx
import { RollingText } from 'runets'
```
Props:
- text (string): The label.
- value (number): Optional value that picks the roll direction.
Files: src/kit/controls.tsx, src/motion.ts, styles/kit.css
Uses: react, motion
Accessibility:
- The whole text is the accessible label; the moving glyphs are hidden.
- Reduced motion crossfades.
### Motion blur
https://ziyamkhan.com/my-components/motion-blur/
Blur along the direction of travel while something flies, measured from its velocity; at rest it is sharp.
Features:
- Blur along the direction of travel, from the measured velocity, capped.
- Sharp the moment it stops.
```tsx
import { MotionBlur } from 'runets'
const vx = useVelocity(x)
// blur along the travel: stdDeviation = speed / 140, capped at 18 px
```
Props:
- perPx (number): Pixels per second per pixel of blur (140).
- max (number): Largest blur in pixels (18).
- …MotionProps (): drag, transitions and the rest of motion’s props.
Files: src/kit/motion-blur.tsx
Uses: react, motion
Accessibility:
- Nothing to announce; with reduced motion, avoid flinging.
### Glow
https://ziyamkhan.com/my-components/glow/
Bloom around a shape: a soft breathing halo, neon that cools instead of cutting off, a spectrum flowing round the border, or text bloom from a mask.
Features:
- Soft, neon, aura (a spectrum flowing round the border) and mask (text bloom) styles.
- Heat: neon cools and deepens instead of switching off.
- Breathing on a continuous phase, so speed changes never jump.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Soft, Neon, Aura, Hot core
Parameters:
- style (Style): soft, neon, aura; default soft
- color (Colour): color; default 0x7c5cff
- core (Hot core): color; default 0xf4f0ff
- third (Third): color; default 0x22d3ee
- radius (Radius): 1 to 64; default 14
- intensity (Intensity): 0 to 3; default 1
- inner (Inner): 0 to 1; default 0
- occlusion (Occlusion): 0 to 1; default 0.15
- breathe (Breathe): 0 to 1; default 0.6
- breathePeriod (Breathe period): 0.4 to 8; default 2.6
- heat (Heat): 0 to 1; default 1
- hot (Hot): 0 to 1; default 0.6
- auraSpeed (Aura speed): 0 to 1; default 0.12
- rimWidth (Rim width): 0.2 to 3; default 0.6
- reach (Reach): 2 to 8; default 4.5
Files: src/fx/glsl/emit.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Pulse
https://ziyamkhan.com/my-components/pulse/
Light that beats: radar rings, a breathing halo, a heartbeat whose earlier rings keep fading under the new one, a ping that winds up, lands and cools, and a tap ripple.
Features:
- Radar rings, a breathing halo and a heartbeat whose old rings fade under the new.
- A ping that winds up, lands with zero velocity and cools.
- A tap ripple clipped to the shape.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Radar, Breathe, Heartbeat, Ping
Parameters:
- style (Style): radar, breathe, heartbeat, ping, ripple; default radar
- color (Colour): color; default 0xef4444
- core (Core): color; default 0xffe4e4
- count (Rings): 1 to 6; default 3
- period (Period): 0.3 to 6; default 2.4
- reach (Reach): 4 to 200; default 36
- width (Width): 0.3 to 8; default 1.6
- intensity (Intensity): 0 to 3; default 1
- dur (Duration): 0.1 to 3; default 0.75
- repeat (Repeat): 0 to 6; default 0
- lag (Lag): 0.02 to 0.5; default 0.16
- headRadius (Head radius): 0.5 to 12; default 2.6
- travel (Travel): 20 to 600; default 160
- occlusion (Occlusion): 0 to 1; default 0.15
Files: src/fx/glsl/emit.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Electricity
https://ziyamkhan.com/my-components/electricity/
Lightning that strikes, holds and re-strikes down the same channel: an arc between two points with forks that shoot out and cool, a current round a border, or a calm charged hairline for UI.
Features:
- Fractal bolts that strike, hold and re-strike down the same channel.
- Forks that shoot out, cool from white to violet and die.
- A calm charged hairline for UI that should stay readable.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Border current, Charged, Arc
Parameters:
- style (Style): border, charged, arc; default border
- color (Glow): color; default 0x4f8dff
- core (Core): color; default 0xeaf3ff
- cool (Cooled fork): color; default 0x7a4dff
- amplitude (Amplitude): 0 to 24; default 5
- frequency (Frequency): 0.5 to 8; default 2.4
- speed (Speed): 0 to 10; default 3.2
- coreWidth (Core width): 0.2 to 3; default 0.6
- intensity (Intensity): 0 to 3; default 1
- glow (Glow): 1 to 20; default 5
- forks (Forks): 0 to 1; default 0.55
- flicker (Flicker): 0 to 1; default 0.45
- strands (Strands): 1 to 3; default 2
- gap (Gap): -6 to 12; default 2
- forkLen (Fork length): 2 to 60; default 20
- occlusion (Occlusion): 0 to 1; default 0.12
Files: src/fx/glsl/emit.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Fire
https://ziyamkhan.com/my-components/fire/
Flames off a top edge with embers that are flung up, slow to a buoyant drift and cool from white to red; plasma hugging a border; or a little heat for a button.
Features:
- Domain-warped flames off a top edge, hottest at the base.
- Embers flung up, slowed by drag into a buoyant drift, cooling white to red.
- Plasma hugging a border, and a small heat preset for buttons.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Flames, Heat, Plasma
Parameters:
- style (Style): top, heat, border, embers; default top
- low (Low): color; default 0x8a1405
- mid (Mid): color; default 0xff5a14
- hot (Hot): color; default 0xffc65a
- height (Height): 4 to 160; default 54
- scale (Scale): 4 to 80; default 20
- speed (Speed): 0 to 5; default 1.5
- intensity (Intensity): 0 to 3; default 1
- embers (Embers): 0 to 40; default 16
- emberRise (Ember rise): 0 to 200; default 58
- emberSize (Ember size): 0.2 to 3; default 0.8
- emberLife (Ember life): 0.2 to 4; default 1.5
- warp (Warp): 0 to 3; default 1
- sides (Sides): 0 to 1; default 0.32
- baseGlow (Base glow): 0 to 2; default 0.5
- swirl (Swirl): 0 to 3; default 0
- occlusion (Occlusion): 0 to 1; default 0.25
Files: src/fx/glsl/emit.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Heat haze
https://ziyamkhan.com/my-components/heat-haze/
Hot air rising off an edge: the backdrop wobbles in a column above it, strongest a little up where the air has risen.
Features:
- The backdrop wobbles in a column above an edge, strongest where hot air has risen.
- Or the whole shape, with the whole-shape switch.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Default
Parameters:
- height (Height): 4 to 160; default 34
- scale (Scale): 4 to 60; default 14
- speed (Speed): 0 to 5; default 1.4
- amount (Amount): 0 to 12; default 2.6
- wholeShape (Whole shape): toggle; default false
Files: src/fx/glsl/surface.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Shockwave
https://ziyamkhan.com/my-components/shockwave/
A ring of displaced light expanding from a point, with a little chromatic split on its front. A one-shot.
Features:
- A ring of displaced pixels with a chromatic split on its front.
- Highlights only where there is content, so empty space gets no grey donut.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Default
Parameters:
- reach (Reach): 20 to 400; default 160
- width (Width): 2 to 40; default 14
- amount (Amount): 0 to 30; default 9
- chroma (Chroma): 0 to 1; default 0.35
- dur (Duration): 0.2 to 3; default 0.9
Files: src/fx/glsl/surface.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Liquid glass
https://ziyamkhan.com/my-components/lens/
Glass that bends what is behind it: the rim squeezes the page, the middle stays sharp and colour splits only at the edge. Two lenses melt together like liquid.
Features:
- The rim squeezes the page, the middle stays sharp, colour splits only at the edge.
- Two lenses melt together with a smooth union.
- Optional frost reads a blurred copy of the backdrop.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Default
Parameters:
- bevel (Bevel): 1 to 40; default 14
- depth (Depth): 0 to 40; default 16
- dispersion (Dispersion): 0 to 0.6; default 0.14
- magnification (Magnification): 0.8 to 1.4; default 1.04
- presence (Presence): 0 to 1; default 1
- frost (Frost): 0 to 1; default 0
- shadow (Shadow): 0 to 1; default 0.35
- rim (Rim): 0 to 3; default 1.6
- lightAngle (Light angle): -3.141592653589793 to 3.141592653589793; default -2.09
- tint (Tint): color; default 0xffffff
- tintAmount (Tint amount): 0 to 1; default 0
Files: src/fx/glsl/surface.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### CRT
https://ziyamkhan.com/my-components/crt/
An old tube: the picture bulges, scanlines and an aperture grille cross it, a roll bar drifts down and colour bleeds sideways.
Features:
- Barrel bulge, scanlines, an aperture grille, a drifting roll bar and colour bleed.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Default
Parameters:
- bulge (Bulge): 0 to 0.4; default 0.08
- scanline (Scanline): 1 to 6; default 1.5
- scanDepth (Scan depth): 0 to 1; default 0.28
- chroma (Chroma): 0 to 4; default 0.8
- vignette (Vignette): 0 to 1.5; default 0.6
- glow (Glow): 0 to 1.5; default 0.35
- roll (Roll): 0 to 3; default 1
- feather (Feather): 0 to 12; default 2
Files: src/fx/glsl/surface.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Chromatic split
https://ziyamkhan.com/my-components/chroma-split/
Red and blue pulled apart from green, with optional glitch slices that jump sideways a few frames at a time.
Features:
- Red and blue pulled apart from green.
- Glitch slices that jump sideways a few frames at a time.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Default
Parameters:
- glitch (Glitch): 0 to 2; default 0.6
- feather (Feather): 0 to 12; default 2
Files: src/fx/glsl/surface.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Shimmer
https://ziyamkhan.com/my-components/shimmer/
A band of light sweeping across a shape: a skeleton shimmer while content loads, or a sheen across text that is still thinking. Under reduced motion the surface breathes instead.
Features:
- A sweeping band with a pause between sweeps.
- Over a shape (skeleton) or through a text mask (sheen).
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Skeleton, Text sheen
Parameters:
- color (Sheen): color; default 0xffffff
- base (Base): color; default 0x1c1f26
- baseAlpha (Base alpha): 0 to 1; default 0
- period (Period): 0.4 to 6; default 1.8
- band (Band): 4 to 120; default 28
- angle (Angle): -1.2 to 1.2; default 0.35
- intensity (Intensity): 0 to 1.5; default 0.16
- pause (Pause): 0 to 0.9; default 0.3
- feather (Feather): 0 to 12; default 0
Files: src/fx/glsl/emit.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Sparkles
https://ziyamkhan.com/my-components/sparkles/
Four-point stars round a shape, each with its own size, twinkle and spin, taking turns. A burst pops every star once and flings it out a little.
Features:
- Four-point stars, each with its own size, twinkle and spin, taking turns.
- A burst that pops every star once and flings it out.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Twinkle, Burst
Parameters:
- color (Colour): color; default 0xffe6a8
- count (Count): 1 to 64; default 6
- life (Life): 0.3 to 4; default 1.5
- size (Size): 2 to 20; default 7
- intensity (Intensity): 0 to 2; default 1
- margin (Margin): 0 to 40; default 10
Files: src/fx/glsl/emit.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Aurora
https://ziyamkhan.com/my-components/aurora/
Three curtains of light with bright lower hems, swaying across a surface. Their heights and warps are a CPU table per frame; the rays are noise per pixel.
Features:
- Three curtains with bright lower hems; heights and warps are a CPU table, rays per pixel.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Polar, Ember
Parameters:
- a (First): color; default 0x16c79a
- b (Second): color; default 0x3b6cff
- c (Third): color; default 0xa23bff
- scale (Scale): 20 to 400; default 120
- speed (Speed): 0 to 2; default 0.25
- intensity (Intensity): 0 to 1.5; default 0.5
- feather (Feather): 0 to 120; default 40
Files: src/fx/glsl/emit.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Grain
https://ziyamkhan.com/my-components/grain/
Film grain: triangular noise per pixel that lightens and darkens, static or redrawn a few times a second.
Features:
- Triangular noise that lightens and darkens, static or redrawn a few times a second.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Static, Film
Parameters:
- amount (Amount): 0 to 0.3; default 0.05
- fps (Rate): 0 to 30; default 0
- feather (Feather): 0 to 40; default 0
Files: src/fx/glsl/emit.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Liquid metal
https://ziyamkhan.com/my-components/liquid-metal/
A polished conductor in a photo studio: a domed slab whose surface flows and pools, Fresnel to white at grazing angles, a little thin-film colour where it bends hardest.
Features:
- A domed slab or a tube border reflecting a photo studio.
- Flowing, pooling surface; Fresnel to white at grazing angles.
- Chrome, gold, rose gold and gunmetal presets.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Chrome, Gold, Rose gold, Gunmetal
Parameters:
- tint (Tint): color; default 0xe9ecf0
- light (Light): color; default 0xffffff
- flow (Flow): 0 to 1.5; default 0.6
- scale (Scale): 16 to 480; default 100
- speed (Speed): 0 to 2; default 0.35
- bevel (Bevel): 0 to 48; default 14
- dome (Dome): 0 to 1; default 0.55
- angle (Angle): -3.141592653589793 to 3.141592653589793; default -0.12
- iridescence (Iridescence): 0 to 1; default 0.08
- contrast (Contrast): 0.5 to 2; default 1
- anchor (Anchor): world, element; default world
- border (Border): 0 to 24; default 0
- intensity (Intensity): 0 to 1; default 1
Files: src/fx/glsl/surface.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Mesh gradient
https://ziyamkhan.com/my-components/mesh-gradient/
Up to six colours, each owning a point that wanders; Shepard weights blend them in OKLab, so the middle never turns muddy.
Features:
- Up to six colours, each owning a wandering point, blended in OKLab.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Dusk, Lagoon, Orchid, Graphite
Parameters:
- colors (Colours): colors; default 5 colours
- drift (Drift): 0 to 0.4; default 0.12
- speed (Speed): 0 to 2; default 0.25
- sharpness (Sharpness): 0.5 to 4; default 1.6
- warp (Warp): 0 to 1; default 0.35
- border (Border): 0 to 24; default 0
- intensity (Intensity): 0 to 1; default 1
Files: src/fx/glsl/surface.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Dither
https://ziyamkhan.com/my-components/dither/
Ordered dithering of a tone into a palette: Bayer matrices, a blue-noise tile built by void-and-cluster, or white noise, over a ramp, a radial, drifting noise or the backdrop.
Features:
- Bayer 2, 4 and 8, a void-and-cluster blue-noise tile, white noise.
- Inputs: a ramp, a radial, drifting noise or the backdrop.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Bayer, Handheld, Blue noise, Backdrop
Parameters:
- pattern (Pattern): bayer2, bayer4, bayer8, blue, white; default bayer4
- input (Input): linear, radial, noise, backdrop; default linear
- colors (Colours): colors; default 2 colours
- pixel (Pixel): 0.5 to 16; default 2
- angle (Angle): -3.141592653589793 to 3.141592653589793; default 0.6
- scale (Noise scale): 8 to 400; default 90
- speed (Speed): 0 to 2; default 0.2
- bias (Bias): -1 to 1; default 0
- contrast (Contrast): 0.2 to 4; default 1
- border (Border): 0 to 24; default 0
- intensity (Intensity): 0 to 1; default 1
Files: src/fx/glsl/surface.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Grain gradient
https://ziyamkhan.com/my-components/grain-gradient/
A linear, radial or conic ramp whose position is scattered by triangular noise, so the colours stipple into each other like risograph ink.
Features:
- Linear, radial and conic ramps scattered by triangular noise.
- Mono or colour grain, static or animated.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Ember, Halo, Sweep
Parameters:
- kind (Kind): linear, radial, conic; default linear
- colors (Colours): colors; default 4 colours
- angle (Angle): -3.141592653589793 to 3.141592653589793; default 1.2
- amount (Grain): 0 to 1; default 0.4
- size (Grain size): 0.5 to 8; default 0.5
- mono (Mono): toggle; default true
- fps (Grain rate): 0 to 30; default 12
- border (Border): 0 to 24; default 0
- intensity (Intensity): 0 to 1; default 1
Files: src/fx/glsl/surface.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Fluted glass
https://ziyamkhan.com/my-components/fluted-glass/
Reeded glass: every rib is a cylindrical lens that returns the strip under it squeezed and flipped, with a sheen down the lit side and a shaded groove.
Features:
- Every rib is a cylindrical lens: the strip under it comes back squeezed and flipped.
- Sheen down each rib, shaded grooves, optional frost and tint.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Reeded, Fine, Frosted, Wide
Parameters:
- rib (Rib width): 2 to 64; default 14
- angle (Angle): -3.141592653589793 to 3.141592653589793; default 0
- refraction (Refraction): 0 to 40; default 9
- frost (Frost): 0 to 1; default 0
- dispersion (Dispersion): 0 to 1; default 0.15
- highlight (Highlight): 0 to 1; default 0.5
- tint (Tint): color; default 0xffffff
- tintAmount (Tint amount): 0 to 1; default 0
- border (Border): 0 to 24; default 0
- intensity (Intensity): 0 to 1; default 1
Files: src/fx/glsl/surface.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Metaballs
https://ziyamkhan.com/my-components/metaballs/
Glossy blobs that drift and melt into each other where their fields add past the surface, each carrying its colour into the merge.
Features:
- Blobs that drift and merge where their fields add past the surface, carrying their colours.
- A glossy body lit from the top left.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Lava, Mint
Parameters:
- colors (Colours): colors; default 3 colours
- base (Base): color; default 0x1a0f1f
- count (Count): 1 to 8; default 6
- size (Size): 0.05 to 0.5; default 0.2
- speed (Speed): 0 to 2; default 0.4
- gloss (Gloss): 0 to 1; default 0.5
- border (Border): 0 to 24; default 0
- intensity (Intensity): 0 to 1; default 1
Files: src/fx/glsl/surface.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Swirl
https://ziyamkhan.com/my-components/swirl/
Ink folding into itself: noise twisted round the centre and warped by more noise, read through a colour ramp.
Features:
- Noise twisted round the centre and warped by more noise, through a colour ramp.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Ink, Marble
Parameters:
- colors (Colours): colors; default 4 colours
- scale (Scale): 16 to 480; default 140
- speed (Speed): 0 to 2; default 0.2
- twist (Twist): -2 to 2; default 0.6
- warp (Warp): 0 to 2.5; default 1
- border (Border): 0 to 24; default 0
- intensity (Intensity): 0 to 1; default 1
Files: src/fx/glsl/surface.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Voronoi
https://ziyamkhan.com/my-components/voronoi/
Cells whose seed points orbit their own spots, with exact seams to every neighbour and a little depth toward each cell centre.
Features:
- Seed points orbiting their own spots, exact seams to every neighbour.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Cells, Stained glass
Parameters:
- colors (Colours): colors; default 4 colours
- seam (Seam colour): color; default 0x0b0f1a
- scale (Cell size): 6 to 200; default 36
- speed (Speed): 0 to 2; default 0.25
- edge (Seam): 0 to 8; default 1.5
- depth (Depth): 0 to 1; default 0.4
- border (Border): 0 to 24; default 0
- intensity (Intensity): 0 to 1; default 1
Files: src/fx/glsl/surface.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Waves
https://ziyamkhan.com/my-components/waves/
Bands of colour stacked like a coastline or a dune field, each front shading the band behind it just above its crest.
Features:
- Bands stacked like a coastline or dunes, each front shading the band behind it.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Sea, Dunes
Parameters:
- colors (Colours): colors; default 5 colours
- amplitude (Amplitude): 0 to 0.25; default 0.05
- frequency (Frequency): 0.2 to 6; default 1.6
- speed (Speed): 0 to 2; default 0.4
- angle (Angle): -3.141592653589793 to 3.141592653589793; default 0
- softness (Softness): 0 to 0.1; default 0.006
- border (Border): 0 to 24; default 0
- intensity (Intensity): 0 to 1; default 1
Files: src/fx/glsl/surface.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Halftone
https://ziyamkhan.com/my-components/halftone/
A print screen: dots on a rotated grid sized by tone, merging across cell lines where the ink is heavy.
Features:
- Dots on a rotated screen sized by tone, merging where the ink is heavy.
- Inputs: ramp, radial, noise or the backdrop.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Print, Backdrop
Parameters:
- input (Input): linear, radial, noise, backdrop; default radial
- ink (Ink): color; default 0x1b1b1f
- base (Base): color; default 0xf1ece1
- cell (Dot pitch): 2 to 32; default 6
- angle (Screen angle): -3.141592653589793 to 3.141592653589793; default 0.785
- rampAngle (Ramp angle): -3.141592653589793 to 3.141592653589793; default 0.6
- scale (Noise scale): 8 to 400; default 90
- speed (Speed): 0 to 2; default 0.2
- bias (Bias): -1 to 1; default 0
- contrast (Contrast): 0.2 to 4; default 1
- border (Border): 0 to 24; default 0
- intensity (Intensity): 0 to 1; default 1
Files: src/fx/glsl/surface.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Plastic
https://ziyamkhan.com/my-components/plastic/
A keycap under one soft light: the diffuse base keeps its colour, a GGX highlight widened by the size of the light, and a faint sky at grazing angles.
Features:
- A dielectric under one soft light: GGX highlight widened by the light’s size, a faint sky at grazing angles.
- Glossy, matte and dished presets.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Glossy, Matte, Dished
Parameters:
- color (Colour): color; default 0xece8de
- roughness (Roughness): 0.05 to 1; default 0.15
- dome (Dome): -1 to 1; default 0.35
- bevel (Bevel): 0 to 48; default 6
- angle (Light angle): -3.141592653589793 to 3.141592653589793; default -0.5
- border (Border): 0 to 24; default 0
- intensity (Intensity): 0 to 1; default 1
Files: src/fx/glsl/surface.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Rain
https://ziyamkhan.com/my-components/rain/
Three depths of slanted streaks that catch the light behind them, splashes on the wet ground, and drops sliding down the glass in surges, each a tiny fisheye showing the scene upside down.
Features:
- Three depths of slanted streaks that catch the light behind them.
- Splashes on the ground line.
- Drops sliding down the glass in surges, each a fisheye showing the scene upside down, leaving trails of beads.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Default
Parameters:
- intensity (Intensity): 0 to 2; default 1
- wind (Wind): 0 to 2; default 0.5
- speed (Speed): 0 to 2; default 1
- density (Density): 0 to 2; default 1
- tint (Tint): color; default 0xbfe0ff
- lens (Drops on glass): 0 to 1; default 0.55
- ground (Ground line): 0.3 to 1; default 0.8
Files: src/fx/glsl/weather.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Snow
https://ziyamkhan.com/my-components/snow/
Four depths of flakes on the wind: fine far flakes, nearer ones that sway, and big out-of-focus bokeh flakes close to the glass; snow lifting off the ground; frost creeping in from the corners.
Features:
- Four depths of flakes on gusting wind, the nearest as out-of-focus bokeh.
- Snow lifting off the ground; frost creeping in from the corners.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Default
Parameters:
- intensity (Intensity): 0 to 2; default 1
- wind (Wind): 0 to 2; default 0.5
- speed (Speed): 0 to 2; default 1
- density (Density): 0 to 2; default 1
- tint (Tint): color; default 0xe8f4ff
- ground (Ground line): 0.3 to 1; default 0.72
Files: src/fx/glsl/weather.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Shooting stars
https://ziyamkhan.com/my-components/meteors/
Stars that scintillate, and meteors in staggered slots: one crosses soon after the scene arrives, trails grow and taper, the odd fireball lights the sky. The land hides anything behind it.
Features:
- Scintillating stars and meteors in staggered slots, the odd fireball lighting the sky.
- A skyline keeps them behind the land.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Default
Parameters:
- intensity (Intensity): 0 to 2; default 1
- wind (Wind): 0 to 2; default 0.5
- speed (Speed): 0 to 2; default 1
- density (Density): 0 to 2; default 1
- tint (Tint): color; default 0x7fd7e6
- accent (Fireball): color; default 0xb8fff0
Files: src/fx/glsl/weather.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Sandstorm
https://ziyamkhan.com/my-components/sandstorm/
A storm wall rolling along the horizon behind the dunes, its billows domain-warped and torn at the top, with dust gusts and grains streaming past in front.
Features:
- A storm wall rolling along the horizon behind the land, billows domain-warped and torn at the top.
- Dust gusts and streaming grains in front.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Default
Parameters:
- intensity (Intensity): 0 to 2; default 1
- wind (Wind): 0 to 2; default 0.8
- speed (Speed): 0 to 2; default 1
- density (Density): 0 to 2; default 1
- tint (Tint): color; default 0xd9b98a
- accent (Horizon glow): color; default 0xff4d3d
Files: src/fx/glsl/weather.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Light
https://ziyamkhan.com/my-components/light/
A lamp above the page: raised elements cast soft shadows whose penumbra widens with distance, their bevels catch the light, and the rest of the page falls into shade.
Features:
- Raised elements cast soft shadows whose penumbra widens with distance, traced through their distance field.
- Rim light on the bevels facing the lamp; the lamp can follow the pointer.
```tsx
import { Fx } from 'runets'
{/* position: relative */}
```
Presets: Reading lamp, Flashlight
Parameters:
- color (Colour): color; default 0xffd9a8
- intensity (Intensity): 0 to 5; default 2.2
- ambient (Darkness): 0 to 1; default 0.72
- range (Range): 60 to 900; default 340
- softness (Softness): 0.2 to 3; default 1
- height (Height): 20 to 400; default 120
- size (Source size): 2 to 40; default 14
Files: src/fx/glsl/weather.ts, src/fx/effects.ts, src/fx/engine.ts, src/fx/fx.tsx, src/fx/cpu.ts, src/fx/glsl/common.ts
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; the parent keeps its semantics and focus.
- Under prefers-reduced-motion every loop settles on one calm pose; one-shots fade in place instead of travelling.
- Off screen, in a hidden tab or once settled, the layer draws nothing.
- data-motion="off" on the root element is a pause switch for the whole page: every layer rests on that calm pose until it is removed.
### Button
https://ziyamkhan.com/my-components/button/
Ten variants in three sizes and five states. A rolling label springs the width as it changes.
Features:
- Neutral, danger, warning, outline, contrast, submit, accent, ghost, ghost muted, ghost faint and loading.
- Small, normal and large.
- Hover, pressed, focus and disabled, and a `state` prop to force one for documentation.
```tsx
import { Button } from 'runets'
}>Create
```
Props:
- variant (ButtonVariant): Look; neutral by default.
- size ('small' | 'normal' | 'large'): Height and type size.
- state ('hover' | 'pressed' | 'focus' | 'disabled'): Forces a state.
- icon (ReactNode): Leading icon.
Files: src/kit/controls.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, motion
Accessibility:
- A native button; Enter and Space press it.
- Loading sets aria-busy and shows a spinner.
### Icon button
https://ziyamkhan.com/my-components/icon-button/
A square button whose name comes from its label or its help text.
Features:
- Square, in every button variant and size.
```tsx
import { IconButton } from 'runets'
```
Props:
- label (string): Its accessible name and tooltip.
Files: src/kit/controls.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, motion
Accessibility:
- Named by its label: never an unlabelled icon.
### Switch
https://ziyamkhan.com/my-components/switch/
Compact and standard. The knob travels on a snappy spring; the track fills with the accent.
Features:
- Compact and standard sizes.
- The knob widens while pressed and travels on the snap spring.
```tsx
import { Switch } from 'runets'
```
Props:
- checked (boolean): On or off.
- onCheckedChange ((v) => void): Called on toggle.
- size ('compact' | 'standard'): Size.
- label (string): Visible label.
Files: src/kit/controls.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, motion, lucide-react
Accessibility:
- role switch with aria-checked; Space toggles.
### Checkbox
https://ziyamkhan.com/my-components/checkbox/
Checked, unchecked and mixed, with the tick drawn on as it checks.
Features:
- Checked, unchecked and mixed.
- The tick draws on as it checks.
```tsx
import { Checkbox } from 'runets'
```
Props:
- checked (boolean): State.
- indeterminate (boolean): Mixed state.
- onCheckedChange ((v) => void): Called on change.
- label (string): Visible label.
Files: src/kit/controls.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, motion, lucide-react
Accessibility:
- Native checkbox semantics, including mixed.
### Radio group
https://ziyamkhan.com/my-components/radio-group/
One of a few, arrow keys move the choice.
Features:
- One choice of a few; the dot pops in on the pop spring.
```tsx
import { RadioGroup } from 'runets'
```
Props:
- value (string): The chosen option.
- onValueChange ((v) => void): Called on change.
- options ([id, label][]): The options.
Files: src/kit/controls.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, motion, lucide-react
Accessibility:
- Arrow keys move the choice; one Tab stop.
### Segmented control
https://ziyamkhan.com/my-components/segmented-control/
A pill that slides to the chosen segment, its width leading its position.
Features:
- A pill that slides to the chosen segment, its width leading its position.
```tsx
import { SegmentedControl } from 'runets'
```
Props:
- value (string): Chosen segment.
- onValueChange ((v) => void): Called on change.
- options ([id, label][]): Segments.
Files: src/kit/controls.tsx, src/motion.ts, styles/kit.css
Uses: react, motion
Accessibility:
- role radiogroup; arrow keys move and focus the choice.
### Badge
https://ziyamkhan.com/my-components/badge/
A small label for status and counts: neutral, accent, success, warning, danger.
Features:
- Neutral, accent, success, warning and danger; an optional dot.
```tsx
import { Badge } from 'runets'
Accepted
```
Props:
- tone (string): Colour.
- dot (boolean): Leading dot.
Files: src/kit/controls.tsx, src/motion.ts, styles/kit.css
Uses: react
Accessibility:
- Plain text; the dot is hidden from assistive tech.
### Keybind
https://ziyamkhan.com/my-components/keybind/
Keys as keycaps, in the platform’s order.
Features:
- Keys as keycaps.
```tsx
import { Keybind } from 'runets'
```
Props:
- keys (string[]): The keys, in order.
Files: src/kit/controls.tsx, src/motion.ts, styles/kit.css
Uses: react
Accessibility:
- Named with its keys as one label.
### Spinner and loader
https://ziyamkhan.com/my-components/spinner/
A ring that spins and three dots that wait their turn.
Features:
- A spinning ring and three waiting dots.
```tsx
import { Spinner, Loader } from 'runets'
```
Files: src/kit/controls.tsx, src/motion.ts, styles/kit.css
Uses: react
Accessibility:
- role status with a Loading label; slower under reduced motion.
### Progress
https://ziyamkhan.com/my-components/progress/
A bar and a circle that spring to each new value and read their percentage aloud.
Features:
- A bar and a circle that spring to each new value.
```tsx
import { Progress, ProgressCircle } from 'runets'
```
Props:
- value (number): 0 to 100.
- label (string): What is progressing.
Files: src/kit/controls.tsx, src/motion.ts, styles/kit.css
Uses: react
Accessibility:
- role progressbar with aria-valuenow; reads its percentage.
### Text field
https://ziyamkhan.com/my-components/text-field/
Input and text area inside a field with its label, description and error, all wired for assistive tech.
Features:
- Input or text area with its label, description and error.
- Focus ring and invalid state from tokens.
```tsx
import { TextField } from 'runets'
```
Props:
- label (string): Label.
- description (string): Help below.
- error (string): Shown and announced when set.
- multiline (boolean): Text area.
Files: src/kit/inputs.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, motion, lucide-react
Accessibility:
- Label, description and error are wired to the control; an error is announced.
### Select
https://ziyamkhan.com/my-components/select/
A list of options in a popover anchored to its trigger, grouped, with the chosen one checked.
Features:
- Options grouped, the chosen one checked, in a popover anchored to the trigger.
```tsx
import { Select } from 'runets'
```
Props:
- options (Option[]): { value, label, group }.
- value (string): Chosen value.
- onValueChange ((v) => void): Called on change.
Files: src/kit/inputs.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, motion, lucide-react
Accessibility:
- Listbox semantics; arrow keys, typeahead, Escape closes.
### Combobox
https://ziyamkhan.com/my-components/combobox/
Type to filter, arrows to move, Enter to choose; the list’s height springs as it filters.
Features:
- Type to filter, arrows to move, Enter to choose.
```tsx
import { Combobox } from 'runets'
```
Props:
- items (string[]): Options.
- onValueChange ((v) => void): Called on choice.
Files: src/kit/inputs.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, motion, lucide-react
Accessibility:
- Combobox semantics; an empty state is announced.
### Shortcut recorder
https://ziyamkhan.com/my-components/shortcut-recorder/
Press a combination and it is recorded as keycaps.
Features:
- Press a combination and it is shown as keycaps.
- Escape cancels, Backspace clears.
```tsx
import { ShortcutRecorder } from 'runets'
```
Props:
- value (string[]): Recorded keys.
- onChange ((keys) => void): Called on record.
Files: src/kit/inputs.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, lucide-react
Accessibility:
- A toggle button whose name says what is recorded.
### Menu
https://ziyamkhan.com/my-components/menu/
Items, checkbox and radio items, a submenu and shortcuts, opening out of its button.
Features:
- Items with shortcuts, checkbox and radio items, labels, separators, submenus.
- Opens out of its button.
```tsx
import { Menu } from 'runets'
```
Props:
- trigger (ReactNode): Button content.
- items (MenuEntry[]): The entries.
Files: src/kit/overlays.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, motion, lucide-react
Accessibility:
- Menu semantics; arrows, typeahead, Escape; focus returns to the button.
### Popover
https://ziyamkhan.com/my-components/popover/
A surface anchored to its trigger that flips and shifts to stay in the window.
Features:
- Anchored to its trigger; flips and shifts to stay in the window.
```tsx
import { Popover } from 'runets'
Fixed before any result was seen.
```
Props:
- trigger (ReactNode): Button content.
- title (string): Heading.
Files: src/kit/overlays.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, motion, lucide-react
Accessibility:
- Dialog semantics with a title and description; Escape closes.
### Tooltip
https://ziyamkhan.com/my-components/tooltip/
Help that waits a moment on hover and describes its control.
Features:
- Waits 450 ms on hover, appears at once on focus.
```tsx
import { Tooltip } from 'runets'
```
Props:
- label (string): The help.
Files: src/kit/overlays.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, motion, lucide-react
Accessibility:
- Describes its control; never holds the only name of a control.
### Hover card
https://ziyamkhan.com/my-components/hover-card/
A preview that rests on hover before it opens.
Features:
- A preview that rests on hover before it opens.
```tsx
import { HoverCard } from 'runets'
…
```
Props:
- href (string): Where the link goes.
- trigger (ReactNode): Link content.
Files: src/kit/overlays.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, motion, lucide-react
Accessibility:
- The link works on its own; the card is extra.
### Dialog
https://ziyamkhan.com/my-components/dialog/
A modal that grows out of its button, traps focus and gives it back.
Features:
- Grows out of its button on the morph spring, over a soft backdrop.
```tsx
import { Dialog } from 'runets'
```
Props:
- title (string): Heading.
- description (string): Body.
- confirm (string): Confirm label.
- onConfirm (() => void): Called on confirm.
Files: src/kit/overlays.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, motion, lucide-react
Accessibility:
- Modal: focus is trapped and returns to the button; Escape cancels.
### Toast
https://ziyamkhan.com/my-components/toast/
Messages that queue, stack and swipe away, announced politely.
Features:
- Queue, stack and swipe away; at most three at once.
```tsx
import { Toaster, useToast } from 'runets'
…
const toast = useToast(); toast.add({ title: 'Saved', description: 'Your changes are on disk.' })
```
Props:
- toast.add (({ title, description })): Shows one (from useToast inside a Toaster).
Files: src/kit/overlays.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, motion, lucide-react
Accessibility:
- A polite live region; never steals focus.
### Card
https://ziyamkhan.com/my-components/card/
A raised surface: neutral, info, warning and error.
Features:
- Neutral, info, warning and error.
```tsx
import { Card } from 'runets'
Two gates are slow.
```
Props:
- tone (string): Colour.
- title (string): Heading.
Files: src/kit/surfaces.tsx, src/motion.ts, styles/kit.css
Uses: react
Accessibility:
- Warning and error cards are alerts.
### List
https://ziyamkhan.com/my-components/list/
Rows with a selection that springs between them and arrow-key navigation.
Features:
- A selection that springs between rows.
```tsx
import { List } from 'runets'
```
Props:
- rows (Row[]): { id, title, detail, icon }.
- label (string): Name of the list.
Files: src/kit/surfaces.tsx, src/motion.ts, styles/kit.css
Uses: react, motion
Accessibility:
- One Tab stop; Up, Down, Home and End move the selection.
### Accordion
https://ziyamkhan.com/my-components/accordion/
Sections that open one at a time, the chevron springing as they do.
Features:
- Sections whose panels spring open; the chevron turns with them.
```tsx
import { Accordion } from 'runets'
```
Props:
- items ({ title, body }[]): The sections.
Files: src/kit/surfaces.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, motion, lucide-react
Accessibility:
- Headings with buttons; panels are labelled by them.
### Collapsible
https://ziyamkhan.com/my-components/collapsible/
One region that opens and closes on the disclosure spring.
Features:
- One region on the reflow spring.
```tsx
import { Collapsible } from 'runets'
…
```
Props:
- title (string): Trigger text.
Files: src/kit/surfaces.tsx, src/motion.ts, styles/kit.css
Uses: react, @base-ui/react, motion, lucide-react
Accessibility:
- aria-expanded on the trigger.
### Shell
https://ziyamkhan.com/my-components/shell/
A sidebar that resizes, collapses on a spring and peeks back when the pointer rests on the edge.
Features:
- A sidebar that resizes by its edge, resets on double-click and collapses when dragged below half its minimum.
- It peeks back when the pointer rests on the left edge.
```tsx
import { Shell } from 'runets'
{content}
```
Props:
- sidebar (ReactNode): Sidebar content.
- title (string): Toolbar title.
Files: src/kit/surfaces.tsx, src/motion.ts, styles/kit.css
Uses: react, motion, lucide-react
Accessibility:
- The edge is a focusable separator; arrow keys resize it.
### Tree
https://ziyamkhan.com/my-components/tree/
A file tree: folders before files, natural order, a cursor the arrow keys move, chains of single folders shown as one row.
Features:
- Folders before files, natural order (icon2 before icon10), chains of single folders as one row.
- Indent guides and a springing chevron.
```tsx
import { Tree } from 'runets'
```
Props:
- nodes (Node[]): From fileTree(paths).
- label (string): Name of the tree.
Files: src/kit/surfaces.tsx, src/motion.ts, styles/kit.css
Uses: react, lucide-react
Accessibility:
- role tree; arrows move, Right opens, Left closes or climbs, typing jumps.
### Table
https://ziyamkhan.com/my-components/table/
Sortable columns, a cursor row, zebra stripes and figures that line up.
Features:
- Sortable columns, a cursor row, zebra stripes, figures at one width; rows glide when sorted.
```tsx
import { Table } from 'runets'
```
Props:
- columns (Column[]): { id, title, align, format }.
- rows (T[]): Data.
Files: src/kit/surfaces.tsx, src/motion.ts, styles/kit.css
Uses: react, motion, lucide-react
Accessibility:
- aria-sort on headers; Up and Down move the cursor.
### Marquee
https://ziyamkhan.com/my-components/marquee/
A row that slides on a seamless loop at a speed in pixels per second, and holds still under the pointer or focus.
Features:
- Two copies of the row slide by one copy and the gap, so the loop has no seam.
- Speed in pixels per second, from the row's measured width: longer rows take longer.
- Pauses under the pointer, on focus inside, when play is false and for reduced motion.
- Edges fade with a mask instead of hard cuts.
```tsx
import { Marquee } from 'runets'
```
Props:
- speed (number): Pixels per second (40).
- play (boolean): Run or hold; hold it while off screen.
- gap (number): Pixels between items (16).
- label (string): Names the region for assistive tech.
Files: src/kit/marquee.tsx, styles/kit.css
Uses: react
Accessibility:
- The second copy is aria-hidden and inert, so everything is read and tabbed once.
- Hover and focus pause it, so it can be read.
### Spotlight
https://ziyamkhan.com/my-components/spotlight/
A surface with a soft light that follows the pointer while it is over it, written to CSS variables, not React state.
Features:
- A radial light at the pointer that fades in on hover.
- The position goes straight to two CSS variables: moving the pointer never re-renders.
```tsx
import { Spotlight } from 'runets'
```
Props:
- …rest (HTML attributes): Passed to the div; your own onPointerMove still runs.
Files: src/kit/spotlight.tsx, styles/kit.css
Uses: react
Accessibility:
- Decoration only: content and focus are untouched.
### Testimonial
https://ziyamkhan.com/my-components/testimonial/
A quote and who said it, with a picture or their initials: a figure, a blockquote and a caption.
Features:
- A figure with a blockquote and a caption, so it reads as a quote anywhere.
- A picture, or initials when there is none.
- No state: renders on the server.
```tsx
import { Testimonial } from 'runets'
```
Props:
- quote (ReactNode): What they said.
- name / role (string): Who said it.
- avatar (string): An image URL.
Files: src/kit/testimonial.tsx, styles/kit.css
Uses: react
Accessibility:
- The avatar is decorative; the name is text.
### Timeline
https://ziyamkhan.com/my-components/timeline/
Work and study in groups, each under its own colour: where on the left, what and when on the right. Server-rendered.
Features:
- Groups (work, education, anything) under a heading in their own colour, set per group with tone.
- A row per role: where and an optional badge on the left; the title, the dates and a description on the right.
- One column in a container under 640px; no state, so it renders on the server.
```tsx
import { Timeline } from 'runets'
```
Props:
- groups ({ id, title, icon?, tone?, entries }[]): tone is any CSS colour.
- entries ({ id, org, title, start, end?, badge?, description? }[]): No end reads as present.
- level (2 | 3 | 4): Heading level of the groups; entries take the next.
- present (string): The word for an open end.
Files: src/kit/timeline.tsx, styles/kit.css
Uses: react
Accessibility:
- Each group is a section labelled by its heading; entries are an ordered list.
- Dates are time elements.
### Word swap
https://ziyamkhan.com/my-components/word-swap/
Words that take turns in one place: the new one drops in out of a blur as the old one sinks away. Pure CSS transitions.
Features:
- Every word sits in the same grid cell, so the slot is as wide as the widest word and the line never jumps.
- The swap is CSS transitions on a data-state: no animation library, nothing per frame.
- Controlled with index, or cycling on its own with every.
```tsx
import { WordSwap } from 'runets'
```
Props:
- words (string[]): The words, in order.
- index (number): Which word shows; wraps, so a running counter works.
- every (number): Milliseconds per word when index is not given.
Files: src/kit/word-swap.tsx, styles/kit.css
Uses: react
Accessibility:
- Only the current word is exposed; the waiting ones are aria-hidden.
- If the words matter, also give the full list to assistive tech once (the hero does).
- Reduced motion swaps instantly.
### Heat card
https://ziyamkhan.com/my-components/heat-card/
A card that warms while you look at it, pointer or keyboard, and cools slowly when you leave instead of switching off.
Features:
- The Glow effect's Neon preset driven by heat: it lights in 60 ms and cools over half a second.
- Hover and focus anywhere inside both count, so keyboard users see the same warmth.
- The glow loads after the page, so the card renders and reads without it.
```tsx
import { HeatCard } from 'runets'
```
Props:
- glow (Params): Glow parameters over the Neon preset: color, core, radius, intensity, inner.
- …rest (HTML attributes): Passed to the article.
Files: src/kit/heat-card.tsx, src/fx/lazy.tsx, styles/kit.css
Uses: react
Accessibility:
- The glow canvas is aria-hidden and never takes the pointer.
- Reduced motion keeps the warm state and drops the fade.
### Badge groups
https://ziyamkhan.com/my-components/badge-groups/
Labelled groups of badges in one panel, flowing into as many columns as fit. Renders on the server: no JavaScript.
Features:
- Groups flow into as many columns as fit, then stack on a phone.
- Each group can carry an icon; the headings follow the level you give the panel.
- No hooks and no state: a server component that ships no JavaScript.
```tsx
import { BadgeGroups } from 'runets'
```
Props:
- title / note (string / ReactNode): The heading and the line beside it.
- groups ({ label, icon?, items }[]): Each group and its badges.
- level (2 | 3 | 4): Heading level of the panel; group labels take the next one.
- id (string): The heading id the section is labelled by.
Files: src/kit/badge-groups.tsx, styles/kit.css
Uses: react
Accessibility:
- A section labelled by its heading, groups as headed lists.
- Icons are aria-hidden.
### Copy button
https://ziyamkhan.com/my-components/copy-button/
Copies text and answers with a tick, or a cross if the browser refused, then turns back. It never changes size.
Features:
- Copy, tick and cross stacked in one cell and swapped in CSS, so the button never resizes.
- The text can be a function, read at the moment of copying.
- A polite status says Copied or Copy failed.
```tsx
import { CopyButton } from 'runets'
```
Props:
- text (string | () => string): What to copy.
- label (string): The accessible name (Copy).
- onCopied / onFailed (functions): Tell the rest of the page.
- reset (number): ms before it turns back (1500).
Files: src/kit/copy-button.tsx, styles/kit.css
Uses: react, lucide-react
Accessibility:
- A labelled button; the result is announced through a status region.
### Filter keys
https://ziyamkhan.com/my-components/filter-keys/
Raised keys, one down at a time, each with its count; a press squashes the key, and the result count rolls.
Features:
- Raised toggle keys, one down at a time, each carrying its count.
- A press squashes the key on a playful spring; the count pops only on change, never on first paint.
- ResultCount says Showing N of M with a rolling N, announced as one sentence.
```tsx
import { FilterKeys, ResultCount } from 'runets'
```
Props:
- options ({ id, label, count, palette? }[]): The keys.
- value / onChange (id): The key that is down.
- label (string): Names the group.
- ResultCount shown / total / noun (number, number, string): The sentence under the keys.
Files: src/kit/filter-keys.tsx, styles/kit.css
Uses: react, motion
Accessibility:
- Keys are toggle buttons (aria-pressed) in a labelled group.
- The count change is read once, as a sentence.
### Outline
https://ziyamkhan.com/my-components/outline/
Links to the sections of a page, indented by depth, with a mark on the one you are reading. Compact shows ticks.
Features:
- Section links indented by heading depth, with a tick that grows and inks on the section you are reading.
- The current section is the last heading past the top third of the window, checked once a frame while scrolling.
- Compact draws ticks only and opens into the labelled list on hover or focus.
```tsx
import { Outline } from 'runets'
```
Props:
- items ({ title, url, depth }[]): url is the #id of the heading.
- label (string): The nav label (On this page).
- compact (boolean): Ticks that open on hover or focus.
Files: src/kit/outline.tsx, styles/kit.css
Uses: react
Accessibility:
- A labelled nav; the current link has aria-current=location.
- Compact opens on keyboard focus too.
### Scroll fade
https://ziyamkhan.com/my-components/scroll-fade/
A scroll box whose edges fade only where there is more to scroll, and stay crisp at either end.
Features:
- The edges fade with a mask only where there is more to scroll.
- Two data attributes set on scroll and resize; the fade is CSS.
- Vertical or horizontal.
```tsx
import { ScrollFade } from 'runets'
```
Props:
- horizontal (boolean): Scroll sideways instead.
- …rest (HTML attributes): Passed to the scroll box.
Files: src/kit/scroll-fade.tsx, styles/kit.css
Uses: react
Accessibility:
- A plain scroll box; nothing is hidden from assistive tech.
### Elastic slider
https://ziyamkhan.com/my-components/elastic-slider/
A native range input with give: drag past an end and the track stretches toward you, then springs back.
Features:
- A native range input over a drawn track, so keys, screen readers and forms work as usual.
- Drag past an end and the track stretches toward the pointer like a rubber band (the give shrinks as you pull), then springs back.
- formatValue writes the value beside the label.
```tsx
import { ElasticSlider } from 'runets'
```
Props:
- label (string): Shown and read.
- min / max / step / value (number): As on a range input.
- onValueChange ((v: number) => void): Each change.
- formatValue ((v) => ReactNode): How the value reads.
Files: src/kit/elastic-slider.tsx, styles/kit.css
Uses: react
Accessibility:
- It is a real input type=range with aria-valuetext from formatValue.
- Reduced motion drops the spring back.
### Slide to unlock
https://ziyamkhan.com/my-components/slide-to-unlock/
Drag the handle to the end, or use the arrow keys, and the action fires; let go early and it springs back.
Features:
- Drag the handle to the end to fire; let go early and it springs back.
- The handle is a slider for assistive tech: arrow keys move it, End unlocks.
- The label sheens across the track and fades as you slide.
```tsx
import { SlideToUnlock } from 'runets'
```
Props:
- label (string): The text and the handle's name.
- onUnlock (() => void): Fires at the end.
Files: src/kit/slide-to-unlock.tsx, styles/kit.css
Uses: react, lucide-react
Accessibility:
- role=slider with a value from 0 to 100 and a spoken value.
- Keyboard: arrows, Home and End.
### Brick breaker
https://ziyamkhan.com/my-components/brick-breaker/
A small brick breaker on a canvas, in the theme's colours: pointer or arrow keys, Space to launch.
Features:
- A canvas game: paddle by pointer or arrow keys, Space or a click launches, clear the bricks to win.
- Where the ball lands on the paddle steers it.
- Colours come from the theme: accent and muted bricks, an ink paddle and ball.
```tsx
import { BrickBreaker } from 'runets'
```
Props:
- rows / cols (number): The wall (4 by 8).
- label (string): Names the canvas.
Files: src/kit/brick-breaker.tsx, styles/kit.css
Uses: react
Accessibility:
- The canvas is focusable and labelled with its controls; wins and losses are announced.
- Offer it as an opt-in toy: it moves.
### Share menu
https://ziyamkhan.com/my-components/share-menu/
Copy the link, share through the device's own sheet, or open any link you give it. A details element: works without script.
Features:
- Copy link, the device's share sheet where there is one, and any links you add.
- A details element: it opens and closes without script.
- onMessage hands back what to tell the visitor (Link copied).
```tsx
import { ShareMenu } from 'runets'
```
Props:
- title / url (string): What is shared.
- links ({ label, href }[]): Extra destinations, opened in a new tab.
- onMessage ((text) => void): Feedback for a toast.
Files: src/kit/share-menu.tsx, styles/kit.css
Uses: react, lucide-react
Accessibility:
- A native disclosure; every action is a button or a link.
### Brand menu
https://ziyamkhan.com/my-components/brand-menu/
Right-click a logo and, instead of the browser's menu, a dialog offers the brand's own actions.
Features:
- A context-menu press on the logo opens a modal dialog of actions instead of the browser menu.
- A plain click still follows the logo's link.
- Actions are buttons or download links; clicking the backdrop closes it.
```tsx
import { BrandMenu } from 'runets'
```
Props:
- title (string): The dialog heading.
- actions ({ label, onSelect? | href, download? }[]): What it offers.
- children (ReactElement): The logo.
Files: src/kit/brand-menu.tsx, styles/kit.css
Uses: react
Accessibility:
- A native modal dialog: focus moves in and returns; Escape closes.
- It is an extra, never the only way to the assets.
### Spotlight mark
https://ziyamkhan.com/my-components/spotlight-mark/
A stroked logo lit by a light that follows the pointer across it on a spring.
Features:
- The stroke is a radial gradient from the accent to the ink, centred on the pointer.
- The light glides on a snappy spring; under reduced motion it rests.
```tsx
import { SpotlightMark } from 'runets'
```
Props:
- d (string): Path data, drawn as a stroke.
- width / height (number): The view box (80 by 48).
- stroke (number): Stroke width (3).
Files: src/kit/spotlight-mark.tsx, styles/kit.css
Uses: react, motion
Accessibility:
- Decorative: aria-hidden. Name the link around it.
### Network map
https://ziyamkhan.com/my-components/network-map/
A hub joined to its nodes; done nodes fill in and their links go solid, the rest stay hollow and dashed.
Features:
- A hub and its nodes in SVG; done nodes fill and their links go solid.
- Labelled, every node is a link that says whether it is done; bare, it is a decorative glyph.
- Strokes keep their width at any size.
```tsx
import { NetworkMap } from 'runets'
```
Props:
- hub / nodes ({ id, label, href?, at, done?, labelAt? }): at and labelAt are in view-box units.
- labelled (boolean): Labels and links.
- viewBox (string): The drawing's frame.
Files: src/kit/network-map.tsx, styles/kit.css
Uses: react
Accessibility:
- Labelled: a group of links that say visited or not visited yet.
- Bare: aria-hidden.
### Article list
https://ziyamkhan.com/my-components/article-list/
A row per article: date and tag on the left, title and a line on the right. Drafts are marked for the build to catch.
Features:
- Date (or a Draft badge) and a tag on the left, title and a line on the right; one column when narrow.
- Drafts are marked with a data attribute, so a production check can refuse to ship one.
- No state: renders on the server.
```tsx
import { ArticleList } from 'runets'
```
Props:
- items ({ href, title, description, date?, tag?, dark?, draft? }[]): dark puts the tag on the dark side of the palette.
- level (2 | 3): Heading level of the titles.
Files: src/kit/article-list.tsx, styles/kit.css
Uses: react
Accessibility:
- Each row is an article with a heading link; dates are time elements.
### Signpost
https://ziyamkhan.com/my-components/signpost/
Wooden signs on a picture, each a toggle: boards on a pole, arrows to either side, an effect on the chosen one and a sheen on the rest.
Features:
- Signs placed by percent on any picture, so they stay on the painted post at every width.
- Three shapes: a framed board with brass nails, and arrows pointing left or right from a pole.
- The chosen sign stands proud and draws its own effect; the others pass a sheen now and then, so they read as buttons.
- A hidden sign fades and steps aside; in a container under 640px the signs leave the picture for a two-column board.
```tsx
import { Signpost } from 'runets'
```
Props:
- image (img attributes): The picture; its width and height set its shape.
- signs ({ id, label, count?, shape, at, effect?, hidden? }[]): at is [x, y] in percent: the pole for boards, the base for arrows.
- value / onValueChange (string): The chosen sign.
- pole ([x, top, bottom]): A pole in percent that carries the boards.
- idle (boolean): The occasional sheen; off when motion is off.
- label (string): The name of the group of signs.
Files: src/kit/signpost.tsx, styles/kit.css
Uses: react
Accessibility:
- Signs are toggle buttons (aria-pressed) inside a labelled nav.
- A hidden sign leaves the tab order and the accessibility tree.
- Reduced motion drops the sheens; the chosen sign still stands proud.
### Terminal
https://ziyamkhan.com/my-components/terminal/
Prompt lines that retype their own words while a block cursor smears from line to line, like smear-cursor in Neovim.
Features:
- Four parts: TerminalWindow (panel and title bar), TerminalLines (prompt lines with one changing word), useRetype (backspace, pause, type at an uneven pace) and SmearCursor.
- The cursor is one clip-path polygon whose corners each chase their spot, the nearest fastest, so a jump leaves a tapering smear and a keystroke steps one crisp cell.
- Every line keeps an unseen copy of its widest version, so the block never reflows while it types.
- Render the lines on the server and load the typing later: the static lines carry their own caret.
```tsx
import { TerminalWindow, TerminalLines, SmearCursor, useRetype } from 'runets'
```
Props:
- TerminalLines lines ({ pre, word, post?, widest? }[]): The lines; widest sizes a line for its longest word.
- TerminalLines active / edit / caret (number / string / Ref): The line being edited, its text mid-edit and the caret element the cursor follows.
- useRetype(id, from, to, run) ({ text, busy }): A new id starts an edit; run false finishes it at once.
- SmearCursor target / busy (Ref / boolean): The cell to follow; busy stops the blink while typing.
- SmearCursor lead / trail / curve (number): Per-frame pull of the nearest and farthest corners and the curve between (0.6, 0.3, 2).
Files: src/kit/terminal.tsx, src/kit/smear-cursor.tsx, styles/kit.css
Uses: react
Accessibility:
- The lines are aria-hidden: give the window a readable list or label of what they say.
- Reduced motion moves the cursor without a smear.
- Typing pauses when run is false and the word finishes at once.
### Bookshelf
https://ziyamkhan.com/my-components/bookshelf/
Books stand spine out. The one you open turns on its spine to show its cover, and its neighbours slide aside by exactly the space it takes.
Features:
- The turn is CSS: one registered angle animates from 0 to 90 degrees, and the book's width (spine x cos + cover x sin) and its 3D turn are both computed from it, so the neighbours move aside by exactly the cover's room.
- Hover and focus lift a book; the open one stays raised.
- One book open at a time, controlled or not; arrow keys move along the shelf, Escape closes.
- Each book has its own height, thickness and colour; the look is plain CSS at zero specificity, so a site's own classes win.
```tsx
import { Bookshelf } from 'runets'
```
Props:
- books ({ id, title, by?, height, thickness, coverWidth?, color?, ink?, spine?, cover? }[]): spine and cover replace what each face shows.
- open / onOpenChange (string | null): The open book, controlled or not.
- label (string): Names the shelf.
Files: src/kit/bookshelf.tsx, styles/kit.css
Uses: react
Accessibility:
- Each book is a button with aria-expanded and the title and author as its name.
- The cover is inert while it faces away, so focus and screen readers never reach a hidden face.
- Escape closes the open book without closing a dialog around the shelf.
- Reduced motion opens a book in place, without the turn.
### Lineage tree
https://ziyamkhan.com/my-components/lineage-tree/
Which work builds on which: a tier per generation, elbow wires that draw in, one focal node.
Features:
- Tiers by the longest path from a root, so a paper sits one tier below the deepest work it builds on.
- Elbow wires (down, along a shared bus, down) measured from the laid-out nodes; they draw in once the tree is seen.
- One focal node, branches and leaves told apart by fill, with an optional legend and tier names.
- Nodes stay ordinary links and text: the tree reads without the wires.
```tsx
import { LineageTree } from 'runets'
```
Props:
- nodes (LineageNode[]): { id, title, tag?, sub?, href?, parents?, focal? }; parents are ids.
- label (string): The figure’s accessible name.
- tiers (string[]): A name per tier, top down.
- legend (['focal' | 'branch' | 'leaf', string][]): Swatches under the tree.
- caption (ReactNode): A line under the legend.
Files: src/kit/lineage-tree.tsx, styles/kit.css
Uses: react
Accessibility:
- The wires are aria-hidden; each node says which nodes it builds on, for screen readers.
- Tiers are ordered lists; linked nodes take focus in reading order.
- Reduced motion shows the wires at once.
### Contribution graph
https://ziyamkhan.com/my-components/contribution-graph/
A year of daily counts as squares, a column per week, busier days in stronger accent. Drawn on the server; a tip reads out each day.
Features:
- A column per week and a row per weekday, Sunday on top, months along the top and Mon, Wed, Fri down the side.
- Five levels: none, then the quartile of the active days, as GitHub shades its graph, so one huge day does not dim the rest. Set --k-cg-0 to --k-cg-4 for your own colours.
- The grid is an SVG with no hooks, drawn on the server; the only client code is the tip that reads out a day.
- On a narrow screen the grid scrolls sideways and opens on the latest weeks, without script.
- Bring the days from anywhere. This site reads GitHub’s public calendar at build time, so visitors never call GitHub.
```tsx
import { ContributionGraph } from 'runets'
```
Props:
- days ({ date, count }[]): One entry per day, oldest first; dates as YYYY-MM-DD.
- title / note (string / ReactNode): An optional heading and the line beside it.
- href (string): Links the total to the profile the counts come from.
- label (string): What a count counts, made plural on its own; contribution by default.
- period (string): Ends the total line; in the last year by default.
- level (2 | 3 | 4): Heading level of the title.
- id (string): The heading id the section is labelled by.
Files: src/kit/contribution-graph.tsx, src/kit/contribution-tip.tsx, styles/kit.css
Uses: react
Accessibility:
- The grid is one focus stop: up and down move a day, left and right a week, Home and End go to either end.
- The tip is a polite live region, so each day is read out as the keys move.
- The SVG is aria-hidden; the grid is a group labelled with the total.
- The legend is aria-hidden: colour only repeats the number the tip says.
### Petal wind
https://ziyamkhan.com/my-components/petal-wind/
Sakura petals that tumble and flip as they fall. Move the pointer and the air moves with it, then settles.
Features:
- Notched sakura petals that tumble and flip; a petal lying flat to the air falls slower than one edge-on.
- The pointer stirs a coarse field of air that decays over about half a second, so the petals along its path are pushed and keep drifting.
- Petals are born where you say (the blossoms of a tree), and a trigger sends one gust across.
- A 2D canvas with pre-drawn sprites: no GPU needed. It stops off-screen and in hidden tabs.
```tsx
import { PetalWind } from 'runets'
canopyBox()} trigger={slide} />
```
Props:
- count (number): Petals in the air at once (36).
- colors ((number | string)[]): Tints as 0xRRGGBB or CSS colours; changing them repaints in place.
- breeze (number): Steady wind in px/s; positive blows left (22).
- fall (number): Edge-on fall speed in px/s (46).
- stir (number): How hard the pointer pushes the air; 0 turns it off (1).
- source (() => Box | null): Where a petal is born, in the layer’s pixels; the top edge by default.
- trigger (number): Change it to send one gust.
- paused (boolean): Hold the petals where they are.
Files: src/kit/petal-wind.tsx, styles/kit.css
Uses: react
Accessibility:
- The canvas is aria-hidden and never takes the pointer; it listens on its parent.
- Under reduced motion the petals are drawn once, at rest.