Detent web components
By Shane Logsdon

Media & effects

Dot Shader

Implemented

Interactive GPU dot matrix background with cursor proximity shader dynamics

detent-dot-shader

Port status
Catalog status
implemented
Origin
upstream
Phase
4
Wave
phase-4-canvas
Group
Media & effects

Demo surface

Interactive dot matrix

Move the pointer across the canvas to see proximity illumination, radial repulsion and the lens bulge. The wobble behind this text is the ambient wave.

5.3 KB gzip for the class module

Variants

Everything inside the shader is real, selectable, keyboard-reachable light DOM above two aria-hidden decorative layers. paused is demonstrated at runtime below: the last frame is kept and the loop stops. The component emits no events, so this demo only reports its own state.

Pause the shader loop

Pause target

Recorded states

  • expanded recorded state; no setter
  • reduced motion recorded state; no setter

Usage

Import

import '/components/dot-shader/define.js';

// or register it yourself
import { DetentDotShader } from '/components/dot-shader/dot-shader.js';

Attributes

  • accent-color
  • cursor-radius
  • distortion-strength
  • dot-color
  • dot-size
  • interactive
  • max-scale
  • overlay
  • paused
  • spacing
  • speed
  • wave-intensity

Properties

No properties are recorded for this component.

Slots

  • default

Events

No events are recorded for this component.

Example

Runnable example: site/examples/dot-shader.ts. The snippet below is generated from the catalogued attributes.

<detent-dot-shader
  accent-color="#00F0FF"
  cursor-radius="180"
  distortion-strength="0.35"
  dot-color="rgba(255, 255, 255, 0.15)"
  dot-size="1.5"
  interactive
  max-scale="2.2"
  overlay
  paused
  spacing="22"
  speed="1"
  wave-intensity="0.25"
></detent-dot-shader>

Source

The pinned upstream source for this row:

  • src/components/ui/DotShader.tsx sha256 eb2c3f2d3905…

Native files

The native module and its artifacts:

  • src/components/dot-shader/dot-shader.ts
  • src/components/dot-shader/styles.css
  • src/components/dot-shader/define.ts
  • docs/components/dot-shader.md
  • site/examples/dot-shader.ts
  • tests/browser/dot-shader.spec.ts
  • evidence/components/dot-shader.md

API

Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.

Attributes

Attributes
AttributePropertyTypeDefaultNotes
accent-coloraccentColorstring'#00F0FF'Kebab-case attribute; camelCase property.
cursor-radiuscursorRadiusnumber180Kebab-case attribute; camelCase property.
distortion-strengthdistortionStrengthnumber0.35Kebab-case attribute; camelCase property.
dot-colordotColorstring'rgba(255, 255, 255, 0.15)'Kebab-case attribute; camelCase property.
dot-sizedotSizenumber1.5Kebab-case attribute; camelCase property.
interactiveinteractivebooleantruePresence semantics: present means true, absent means false.
max-scalemaxScalenumber2.2Kebab-case attribute; camelCase property.
overlayoverlaybooleantruePresence semantics: present means true, absent means false.
paused———Recorded in the catalog as an attribute.
spacingspacingnumber22Kebab-case attribute; camelCase property.
speedspeednumber1Kebab-case attribute; camelCase property.
wave-intensitywaveIntensitynumber0.25Kebab-case attribute; camelCase property.

Properties

No property-only values are recorded for this component.

Events

No custom events are recorded for this component.

Slots

Slots
SlotNotes
defaultConsumer content; rendered through a slot, never re-created.

CSS customisation

  • React `children`/`ReactNode` props become DOM slots; caller content stays light DOM.
  • `className` prop is replaced by documented CSS parts/custom properties; no Tailwind in consumers.
  • React state/hooks replaced by element-owned state with pre-upgrade property preservation.
  • The WebGL/GLSL point shader is not ported; the Canvas 2D renderer (upstream fallback) is the only path. Headless WebKit exposes no WebGL, so the GPU path cannot be verified on the three required engines, and recorded features 1 and 6 are therefore not delivered (see evidenceGaps). Owner accepted this gap on 2026-10-29; every other recorded feature is implemented and pixel-verified.
  • Each colour alpha is applied once; the pinned 2D fallback also multiplied the same alpha into globalAlpha, painting the documented default at an effective 0.0225 alpha (invisible).
  • A document visibilitychange pause is added because PC-10.6 requires it; the source stops only for reduced motion, paused and offscreen.
  • paused is exposed as attribute and property with the pinned source default false (the row recorded no default).
  • The derived state is published as surface[data-state] and surface[data-motion] because a native element needs a DOM-observable hook where React owned it upstream.

What it does

An interactive dot-matrix background: cursor-proximity illumination, radial repulsion, a lens bulge and an ambient wave, painted into a canvas that sits beneath the caller's slotted content.

Upstream behaviour
  • Hardware-accelerated WebGL point primitive vertex & fragment shader with Canvas 2D fallback
  • Interactive cursor proximity illumination transitioning smoothly to accent color
  • Magnetic/gravitational radial repulsion with smooth exponential damping
  • Dynamic scale expansion creating a 3D lens bulge around the cursor
  • Ambient wave undulation breathing subtle life into the background when idle
  • Zero CPU overhead during rendering via GPU vertex shader positioning
  • Supports wrapping arbitrary children without interfering with pointer interactions
  • Full prefers-reduced-motion compliance freezing displacement and waves
Differences from upstream
  • React `children`/`ReactNode` props become DOM slots; caller content stays light DOM.
  • `className` prop is replaced by documented CSS parts/custom properties; no Tailwind in consumers.
  • React state/hooks replaced by element-owned state with pre-upgrade property preservation.
  • The WebGL/GLSL point shader is not ported; the Canvas 2D renderer (upstream fallback) is the only path. Headless WebKit exposes no WebGL, so the GPU path cannot be verified on the three required engines, and recorded features 1 and 6 are therefore not delivered (see evidenceGaps). Owner accepted this gap on 2026-10-29; every other recorded feature is implemented and pixel-verified.
  • Each colour alpha is applied once; the pinned 2D fallback also multiplied the same alpha into globalAlpha, painting the documented default at an effective 0.0225 alpha (invisible).
  • A document visibilitychange pause is added because PC-10.6 requires it; the source stops only for reduced motion, paused and offscreen.
  • paused is exposed as attribute and property with the pinned source default false (the row recorded no default).
  • The derived state is published as surface[data-state] and surface[data-motion] because a native element needs a DOM-observable hook where React owned it upstream.
Previous: Dot Field Next: Drag to Confirm

Docs

Components

Project