Media & effects
Density Lens
Cursor-tracking magnification & detail inspection lens
detent-density-lens
Port status
- Catalog status
- implemented
- Origin
- upstream
- Phase
- 4
- Wave
- phase-4-pointer
- Group
- Media & effects
renderLensContent.
4.5 KB gzip for the class module · inlines the shared spring
Variants
Hover (or tap, on touch) any panel on this page: the lens follows the pointer with the pinned spring (stiffness
450, damping 28, mass 0.2) and eases from opacity 0 / scale 0.8 to opacity 1 / scale 1.
The three recorded lensShape variants only change the corner geometry: circle is a 50 %
radius, oval 40 px and square 16 px on the same square box. Nothing is captured and no
layout moves.
The square lens opts out of the border through the property (showBorder = false). With
prefers-reduced-motion: reduce the lens appears at the pointer in its final state and schedules no
frame.
Recorded states
hoverrecorded state; no setter
Usage
Import
import '/components/density-lens/define.js';
// or register it yourself
import { DetentDensityLens } from '/components/density-lens/density-lens.js';
Attributes
lens-shapelens-sizeshow-borderzoom-scale
Properties
renderLensContent
Slots
default
Events
No events are recorded for this component.
Example
Runnable example: site/examples/density-lens.ts. The snippet below is generated from the catalogued attributes.
<detent-density-lens
lens-shape="circle"
lens-size="150"
show-border
zoom-scale="2"
></detent-density-lens>
Property-only values
const element = document.querySelector('detent-density-lens');
if (element !== null) {
// renderLensContent: (pos: { x: number, y: number, scale: number }) => ReactNode
element.renderLensContent = () => {};
}
Source
The pinned upstream source for this row:
src/components/ui/DensityLens.tsxsha256 9090e41248b8…
Native files
The native module and its artifacts:
src/components/density-lens/density-lens.tssrc/components/density-lens/styles.csssrc/components/density-lens/define.tsdocs/components/density-lens.mdsite/examples/density-lens.tstests/browser/density-lens.spec.tsevidence/components/density-lens.md
API
Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.
Attributes
| Attribute | Property | Type | Default | Notes |
|---|---|---|---|---|
lens-shape | lensShape | 'circle' | 'oval' | 'square' | 'circle' | Kebab-case attribute; camelCase property. |
lens-size | lensSize | number | 150 | Kebab-case attribute; camelCase property. |
show-border | showBorder | boolean | true | Presence semantics: present means true, absent means false. |
zoom-scale | zoomScale | number | 2 | Kebab-case attribute; camelCase property. |
Properties
| Property | Type | Default | Notes |
|---|---|---|---|
renderLensContent | (pos: { x: number, y: number, scale: number }) => ReactNode | undefined | Property-only: assign from script; not accepted as an attribute. |
Events
No custom events are recorded for this component.
Slots
| Slot | Notes |
|---|---|
default | Consumer content; rendered through a slot, never re-created. |
CSS customisation
- React `children`/`ReactNode` props become DOM slots; caller content stays light DOM.
- Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- A custom element may not clone or re-serialise slotted nodes (PC-11.2), so the lens does not duplicate children: the default path is the documented glass highlight and the 2x magnified view comes from the recorded renderLensContent property ({ x, y, scale }).
- Lens border and ring colours were corrected from #1f1f1f / #4a4a4a (1.05:1 and 1.8:1 on white) to #6b7280 (accessibility correction).
- Touch inspects directly on pointerdown; upstream listened to mouse events only, leaving the recorded touch fallback unimplemented.
What it does
A hover lens that follows the pointer, showing a consumer-supplied magnified rendering or a glass highlight.
Upstream behaviour
- Subtle spring lag cursor tracking for realistic tactile lens momentum
- Automatic coordinate interpolation with 2x magnification or custom overlay renderers
- Configurable lens geometry (circle, oval, rounded square), border glow, and zoom scale
- Zero layout shifts and smooth GPU-accelerated backdrop blur
Differences from upstream
- React `children`/`ReactNode` props become DOM slots; caller content stays light DOM.
- Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- A custom element may not clone or re-serialise slotted nodes (PC-11.2), so the lens does not duplicate children: the default path is the documented glass highlight and the 2x magnified view comes from the recorded renderLensContent property ({ x, y, scale }).
- Lens border and ring colours were corrected from #1f1f1f / #4a4a4a (1.05:1 and 1.8:1 on white) to #6b7280 (accessibility correction).
- Touch inspects directly on pointerdown; upstream listened to mouse events only, leaving the recorded touch fallback unimplemented.