Skip to the page
TACTILE UI

Kit part · Carousels

Film strip

A carousel as a strip of film in a machined viewer. The frames run behind a gate lit from behind, with sprocket holes along both edges, and the frames either side wait under a smoked cover. It moves a frame at a time and settles as each one registers. Turn the thumbwheel, press the keys or swipe the film itself: underneath it is a native scroller with a snap point at every frame.

Element
<tui-film-strip>
Needs
kit.css + kit.mjs
Rules
film-strip.rules.md · 6
Finishes
Aluminium · Graphite · Porcelain · Black
Volumes
Tactile · Quiet
On this page
  1. Variants
  2. Every state, at once
  3. API
  4. Markup
  5. Accessibility
  6. How it’s built
  7. Rules
  8. Related parts
01

Variants

North ridge, site survey
The mast, site survey
Access road, site survey
Substation, site survey
Last light, site survey
Photographs
Lode 4.2 · 09:31
Stage

Staging takes it. Smoke tests pass.

Lode 4.2 · 09:48
Canary

Five per cent of traffic. p95 at 180 ms.

Lode 4.2 · 10:24
Roll back

p95 passes 800 ms. The canary comes out.

Lode 4.2 · 11:03
Fix

4.2.1 fixes the slow query on db-2.

Lode 4.2 · 11:40
Canary again

Five, then 25 per cent. p95 under 200 ms.

Lode 4.2 · 12:15
Roll out

Three regions, one at a time.

Starts on a frame · index
Lode 4.2 · 13:30
Watch

Errors flat at 0.02 per cent for an hour.

Lode 4.2 · 13:52
Notes

Release notes go to the whole team.

Lode 4.2 · 14:10
Live

4.2.1 is live in every region.

Three frames
The mast, site survey
Access road, site survey
Substation, site survey
No script: it still swipes and scrolls
02

Every state, at once

Both finishes, side by side. Hover, pressed and focus are forced with .is-hover, .is-down and .is-focus; checked and disabled are real.

Aluminium

PartRestHoverPressedFocus
Key
Thumbwheel
Counter01 / 1204 / 1211 / 1212 / 12

Graphite

PartRestHoverPressedFocus
Key
Thumbwheel
Counter01 / 1204 / 1211 / 1212 / 12
03

API

NameKindValuesWhat it does
<tui-film-strip>elementlabel · indexThe viewer: role="region" with aria-roledescription="carousel", named by label. index is the frame to start on, from 0.
.tui-film-strip__viewer · __reel · __filmclassin the markupThe housing with its gate, the native scroller, and the film that carries the frames and the holes. Write them yourself or with filmStripHTML().
figure.tui-film-strip__frameelementdata-nameA frame: an image or a card. data-name is what it is called; the element names it “4 of 12: Canary”.
.tui-film-strip__cardclasssmall · b · pA frame of words, printed on paper: a small label, a title and one line.
--fs-w · --fs-peekcustom propertylengthA frame’s width at most, 320px, and how much of each neighbour shows beside the gate, 44px. Frames are 3:2.
.tui-film-strip__deckclassadded by kit.mjsUnder the viewer: the LCD counter, the previous and next keys and the thumbwheel.
.tui-film-strip__wheelclassrole="slider"The thumbwheel. Drag it and the film goes with its ridges; scroll on it and it clicks round a frame a notch; with focus, the arrows, Page Up and Down, Home and End.
index · go(i)property · methodfrom 0The frame at rest in the gate, and a way to bring another there. The film has ends and does not wrap.
tui-frameeventdetail.index · frame · of · nameWhen a new frame comes to rest in the gate, however it got there. Bubbles.
Arrows · Home · Endkeyboardon the filmA frame at a time, and the ends. The film is one tab stop and the thumbwheel another.
filmStripHTML · filmStripCount · filmStripLabel · filmStripIndex · filmStripTurn · filmStripNotchfunctionkit.mjsThe markup, and the rules under it, pure: the counter, a frame’s name, the frame at a scroll position, how far the wheel turns, and wheel notches.
04

Markup

<tui-film-strip class="tui-film-strip" label="Lode 4.2, the release frame by frame">
  <div class="tui-film-strip__viewer">
    <div class="tui-film-strip__reel" tabindex="0" role="group" aria-label="Frames">
      <div class="tui-film-strip__film">
        <figure class="tui-film-strip__frame" data-name="Cut">
          <img src="/release/cut.jpg" alt="The release branch, cut from main">
        </figure>
        <figure class="tui-film-strip__frame" data-name="Build">
          <div class="tui-film-strip__card">…</div>      <!-- or a card of words -->
        </figure>
        <!-- three to twenty frames -->
      </div>
    </div>
  </div>
</tui-film-strip>
import { filmStripHTML } from '/kit/kit.mjs';   // also defines <tui-film-strip>

// The markup above, written for you: names become "4 of 12: Canary".
box.innerHTML = filmStripHTML({ label: 'Site survey', frames: photos.map((p) => ({ name: p.title, html: `<img src="${p.src}" alt="${p.alt}">` })) });

const strip = document.querySelector('tui-film-strip');
strip.addEventListener('tui-frame', (e) => {
  e.detail.frame;   // 4
  e.detail.name;    // 'Canary'
});
strip.go(6);        // bring the seventh frame into the gate

Needs kit.css and kit.mjs. How to install the kit.

05

Accessibility

  • It is a region with aria-roledescription="carousel", named by its label, and each frame is a group named “4 of 12: Canary”, so a screen reader hears where it is and what the frame is before anything on it.
  • When a frame comes to rest, the same words go to a polite live region. While the thumbwheel has focus they are left to the slider, which speaks its own value, so nothing is said twice.
  • Underneath is a native scroller with a snap point at every frame. Without the script a swipe, a trackpad and the arrow keys still move it a frame at a time, and the film is a tab stop for that.
  • The thumbwheel is a slider with aria-valuetext and the keys are real buttons named “Previous frame” and “Next frame”. At an end the key is aria-disabled, so focus is never dropped.
  • The LCD counter is a second signal for the eye and is hidden from assistive technology.
  • A frame beside the gate takes one click to come in before anything on it acts.
  • With reduced motion the film goes straight to the frame, with no glide and no settle.
06

How it’s built

The reel is a scroller with scroll-snap-type: x mandatory and a snap point at the middle of every frame, with scroll-snap-stop: always so a flick moves one. The film inside it is as long as its frames, padded so the first and the last can reach the gate, and carries the sprocket holes as two repeating backgrounds, so they travel with it. Frames are sized in container units: 320px at most, and never so wide that less than 44px of each neighbour shows. The gate is a pseudo-element over the middle of the viewer whose shadow, spread a long way, is the smoked cover; a second one lights it from behind in screen. The thumbwheel is 36 ridges laid round a circle with CSS sin() and cos(): each one sits at its own angle less --turn, narrows as it turns away and is gone round the back, under a light that stays put. The script sets --turn from the scroll position, 36 degrees a frame, so the wheel turns with the film however the film is moved. The settle is a Web Animations nudge on the film, four pixels past and back, as a frame arrives.

07

Rules

film-strip.rules.mdIn the brain

For a sequence worth going through in order, with the next frame waiting at the edge.

6 rules in this file, with the foundations they rest on and the anti-patterns that break them. Full rules ship in the brain with the Pass.

08

Carousel

Slides seen one at a time through a viewer’s gate: transport keys either side of a frame counter on an LCD, lamp keys to jump, swipe on touch. Nothing moves on its own unless you ask it to.

  1. HubReserve raised to 20%
  2. Meter 2291Missed three readings
  3. HubMeter 2291 is back
  4. BatteryFull at 13.4 kWh
  5. GridExporting 2.1 kW at 15p
  6. CarBoost charge started

Scroll area

A region that scrolls, with its scrollbar made as a machined rail: a groove cut into the plate and a thumb like a fader cap riding in it. Scrolling itself is the browser’s own.

02:52min

LCD

A value that changes, on grey-green liquid crystal, with a ghost of the unlit segments behind it: clocks, battery, counters.

Docs
Finish
Volume