Skip to the object
Tactile UI

Iris

A lens’s iris diaphragm, as a reveal. Curved blades pivot on their pins, close to a pinhole and open onto what lies beneath, the engraved f-stop ring turning with them.

What it is for

Reveal a hero image, a portfolio thumbnail or a page with a mechanism people recognise from a camera, not a fade: the content stays real, accessible DOM under the blades, and the opening is driven by the ring, hover, a press, the scroll, or a slow breathing loop for a loader.

Installnpx shadcn add https://tactileui.dev/r/iris.jsonWith a Pass: how

Presets

Controls

0 is straight blades and a sharp polygon; 1 is as round as a blade that still hides under the lip.

FinishAuto

Auto casts the blades, housing and engraving in the page’s finish: pale metal on a light one, anodised metal with bright cut edges on a dark one, lit in the display’s light on Phosphor and Night (without the kit’s tokens, steel on a light page and graphite on a dark one). Or pin one: graphite, ink, steel or brass.

Fit

Lens: the whole object, content seen only through it. Cover: the blades fill the frame and wide open clears it (a reveal).

Off leaves a thin lip. Lens fit only.

dial: turn the ring (or arrow keys, a stop at a time). hover and press open it. scroll follows the page. breathe is a loader. manual is open() and close() only.

For dial, hover, press and manual.

Where it settles: 1 is wide open (f/1.4), 0.35 about f/4, 0 shut. Hover and press open from here.

0 is from above, clockwise.

Synthesised, no audio file. Starts only after you touch it.

Reduced motion shows

open: fully open, because the content is the information. rest: the rest opening, for a loader.

The accessible name of the ring slider or the toggle button.

This stage only

Content

A painted photograph, or live DOM type: either way, real content under the blades.

Everything you set here is what the Code and Prompt tabs give you.

Seats open in 11 days. Want one email that morning?

Datasheet

Mechanism
Pivot linkage, Shingle stack, Sdf shading, Spring opening, Shared webgl context, Polar engraving texture, Sleeping loop, Canvas 2d fallback, Sector ordered painting, Touch grab zone
Stack
Vanilla ES modules, CSS, WebGL, Canvas 2D
Needs
Nothing, no dependencies
States
11 documented
Version
0.1.0
Licence
With a Pass

States

  1. At restSettled at the rest opening (f/4 by default); the loop is asleep and costs nothing.
  2. Opening when first seenShut until the lens is a third in view, then a short beat and the blades open to rest through the spring.
  3. Turning the ringDrag round the ring or use the arrow keys: the blades follow the hand with no lag and click into the nearest f-stop on release; the slider's value text is the f-number. In the cover fit a sideways drag scrubs.
  4. Hover and pressHover (or focus inside) opens it wide and leaving returns it to rest; as a toggle it has its own small button (aria-expanded) and a click on anything not interactive in the object toggles too, so links in the content still work.
  5. Scroll-linkedShut as it enters from the bottom of the viewport, wide open by the time it is a little above the middle; the spring gives the blades weight.
  6. BreathingThe loader: stops down to a pinhole and opens back to rest every 3.6 s, and only while it can be seen.
  7. ShutThe blades meet at the centre in a pinwheel; the content under them stays in the accessibility tree.
  8. Off screen or hiddenThe loop pauses; a tab returning with a long frame advances the spring one clamped step.
  9. TouchA vertical swipe anywhere over the object scrolls the page (pan-y); the knurled ring is the grab zone and takes a drag in any direction; hover becomes a tap.
  10. Reduced motionNo animation: the first paint is fully open (or the rest opening, by choice), and every later change snaps.
  11. No WebGLPainted with Canvas 2D from the same linkage: blades stacked sector by sector in the exact shingle order, each lit from the lamp with a brushed grain, cast shadow and lit or shaded edge; the housing's turned sheen from the same formula. Same motion; also used if the WebGL context is lost.

Notes

Original. Modelled from how a real diaphragm is built (rigid blades on fixed pivots turned together), not from a catalogue reference, so references is honestly empty. One shared WebGL context renders every instance, with a Canvas 2D painter of the same geometry when WebGL is missing or lost; no image or font ships (the preview's photograph is painted procedurally, the exported example's is inline SVG). PRESETS in controls.mjs: Graphite prime (default), Brass field camera, Six-blade hexagon, Steel cine lens, Cover reveal.

Anatomy

Pivot linkage, Shingle stack, Sdf shading, Spring opening, Shared webgl context, Polar engraving texture, Sleeping loop, Canvas 2d fallback, Sector ordered painting, Touch grab zone

Usage notes

Reveal a hero image, a portfolio thumbnail or a page with a mechanism people recognise from a camera, not a fade: the content stays real, accessible DOM under the blades, and the opening is driven by the ring, hover, a press, the scroll, or a slow breathing loop for a loader.

Options

OptionTypeDescription
bladesnumberBlades
curvaturenumber0 is straight blades and a sharp polygon; 1 is as round as a blade that still hides under the lip.
finishenumAuto casts the blades, housing and engraving in the page’s finish: pale metal on a light one, anodised metal with bright cut edges on a dark one, lit in the display’s light on Phosphor and Night (without the kit’s tokens, steel on a light page and graphite on a dark one). Or pin one: graphite, ink, steel or brass.
fitenumLens: the whole object, content seen only through it. Cover: the blades fill the frame and wide open clears it (a reveal).
ringbooleanOff leaves a thin lip. Lens fit only.
knurlbooleanKnurled grip
scalebooleanEngraved f-stop scale
driverenumdial: turn the ring (or arrow keys, a stop at a time). hover and press open it. scroll follows the page. breathe is a loader. manual is open() and close() only.
introbooleanFor dial, hover, press and manual.
restnumberWhere it settles. Hover and press open from here.
stiffnessnumberSpring stiffness
lightnumber0 is from above, clockwise.
readoutbooleanShow f-number
soundbooleanSynthesised, no audio file. Starts only after you touch it.
stillenumopen: fully open, because the content is the information. rest: the rest opening, for a loader.
labeltextThe accessible name of the ring slider or the toggle button.

Methods

  • opening
  • aim
  • state
  • open
  • close
  • toggle
  • replay
  • update
  • destroy

How it works

Original. One shared WebGL context renders every instance, with a Canvas 2D painter of the same geometry when WebGL is missing or lost; no image or font ships (the preview's photograph is painted procedurally, the exported example's is inline SVG). PRESETS in controls.mjs: Graphite prime (default), Brass field camera, Six-blade hexagon, Steel cine lens, Cover reveal.