KQ-1790 · MERCURY/GATE
Mercury Gate
A metal ring hanging in a place, a membrane of liquid mercury across it — a WebGL2 height field shaded as a near-perfect mirror with a crisp reflected horizon, slowly wobbling — drawing a faint stream of motes in from the card's edges. Hover or focus it and ripples run out from the pointer while the mercury parts on the springs.glide constants into a clear disc with a beaded meniscus, showing the place the gate leads to; a click or Enter dives through — a breath back, then the ring rushes past on an accelerating tween with streaks pouring outward and a soft flash — and the destination fills the card as the value changes. The ring re-forms behind you on springs.glide, still clear and showing where you came from, before the mercury flows back in on springs.drift. Arrow keys on the gate, or the marks beneath it (a radiogroup with roving focus), choose where it leads.
Waylight Travel
Pick a door
The field
To Coldbrook Shore
Arrow keys choose where the gate leads; Enter goes through.
at The field · gate leads to Coldbrook Shore
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/mercury-gate
Props
- destinations
- MercuryGateDestination[]
- default four invented places
- The places the gate connects: { id, title, caption?, kind?, tone?, scene? }. Without scene a built-in painting (field, shore, dunes, peaks, grove) is drawn from tone.
- value / defaultValue
- string
- default the first destination
- Where you are: a destination id; controlled or uncontrolled.
- onValueChange
- (id: string) => void
- default —
- Fires when a dive arrives, with the new place's id.
- target / defaultTarget
- string
- default the next destination
- Where the gate leads: a destination id; controlled or uncontrolled. After a dive it leads back where you came from.
- onTargetChange
- (id: string) => void
- default —
- Fires from the key or mark that pointed the gate somewhere else, and on arrival when it turns to lead back.
- onDive
- (from: string, to: string) => void
- default —
- Fires as a dive begins, with where from and where to.
- ripple
- number
- default 0.55
- How high the hover ripples run and how wide the mercury parts, 0 to 1.
- glow
- number
- default 0.5
- How strongly the ring glows, 0 to 1.
- pull
- number
- default 0.5
- How many motes the gate draws in, and how fast, 0 to 1.
- ringSize
- number
- default 0.8
- The ring's diameter as a share of the box's short side, 0.4 to 1.
- metalColor
- string
- default a cool silver from the accent token
- The ring's metal, any CSS colour.
- glowColor
- string
- default "var(--accent-bright)"
- The ring's glow and the motes, any CSS colour.
- showLabels
- boolean
- default true
- Show where you are and where the gate leads, as text over the scene.
- sound
- boolean
- default false
- A whoosh as you dive, and a softer one as the ring re-forms.
- paused
- boolean
- default false
- Hold the mercury and the motes still.
- seed
- number
- default 1
- Seeds the motes and the built-in paintings' stars and ridges.
- dpr
- number
- default 2
- Cap on the canvases' device pixel ratio, at most 2.
- label
- string
- default "Go through"
- The gate's accessible name, before "to" and the place.
- disabled
- boolean
- default false
- No diving and no changing where it leads.
- className
- string
- default —
- Sizes the gate; it fills its parent by default.
| Prop | Type | Default | Description |
|---|---|---|---|
| destinations | MercuryGateDestination[] | four invented places | The places the gate connects: { id, title, caption?, kind?, tone?, scene? }. Without scene a built-in painting (field, shore, dunes, peaks, grove) is drawn from tone. |
| value / defaultValue | string | the first destination | Where you are: a destination id; controlled or uncontrolled. |
| onValueChange | (id: string) => void | — | Fires when a dive arrives, with the new place's id. |
| target / defaultTarget | string | the next destination | Where the gate leads: a destination id; controlled or uncontrolled. After a dive it leads back where you came from. |
| onTargetChange | (id: string) => void | — | Fires from the key or mark that pointed the gate somewhere else, and on arrival when it turns to lead back. |
| onDive | (from: string, to: string) => void | — | Fires as a dive begins, with where from and where to. |
| ripple | number | 0.55 | How high the hover ripples run and how wide the mercury parts, 0 to 1. |
| glow | number | 0.5 | How strongly the ring glows, 0 to 1. |
| pull | number | 0.5 | How many motes the gate draws in, and how fast, 0 to 1. |
| ringSize | number | 0.8 | The ring's diameter as a share of the box's short side, 0.4 to 1. |
| metalColor | string | a cool silver from the accent token | The ring's metal, any CSS colour. |
| glowColor | string | "var(--accent-bright)" | The ring's glow and the motes, any CSS colour. |
| showLabels | boolean | true | Show where you are and where the gate leads, as text over the scene. |
| sound | boolean | false | A whoosh as you dive, and a softer one as the ring re-forms. |
| paused | boolean | false | Hold the mercury and the motes still. |
| seed | number | 1 | Seeds the motes and the built-in paintings' stars and ridges. |
| dpr | number | 2 | Cap on the canvases' device pixel ratio, at most 2. |
| label | string | "Go through" | The gate's accessible name, before "to" and the place. |
| disabled | boolean | false | No diving and no changing where it leads. |
| className | string | — | Sizes the gate; it fills its parent by default. |