The cookie
The canonical Tangle demo. Drag the 3 — right raises it, left lowers it. Nothing else on the page is a control.
You eat
Tangle is Bret Victor's library for reactive documents: an essay where the numbers are handles. You read a sentence, you notice a number is underlined, you drag it, and the rest of the page re-derives itself around you. The argument it makes is that a reader who can move a quantity understands the model that quantity sits in, and a reader who can only look at one number does not.
That is a very different thing from a control panel. A Manipulate puts the sliders in a box above a plot, and the reader has to hold in their head which slider goes with which term. Tangle's controls sit where the quantity is mentioned, in the sentence that says what it means — so there is nothing to map.
Five components come out of that, and they are all inline:
| Component | What it is | After |
|---|---|---|
<dynamic-module-box> | the scope; renders nothing of its own | Tangle's Tangle |
<knob-box> | a number you drag inside the prose | TKAdjustableNumber |
<toggler-box> | a word that cycles when clicked | Wolfram's Toggler |
<dynamic-box> | a derived readout | Wolfram's Dynamic |
<pane-selector-box> | a phrase that appears only under a condition | Tangle's TKIf |
The binding machinery is the one <notatio-manipulate> already uses: a knob named a publishes the wildcard _a, and any expression in the subtree that mentions _a is a template, re-evaluated on every move. So a knob can drive a sentence, a glyph and a plot at once without knowing that any of them exist.
The canonical Tangle demo. Drag the 3 — right raises it, left lowers it. Nothing else on the page is a control.
You eat
The value follows the pointer's position, not a rate. Drag out and back and you land on the number you started from — a scrubber that accelerates the further you pull is a throttle, not a value, and a reader cannot put it back.
step also fixes how many places are printed, so the readout keeps a constant width while you drag it. A number that reflows its own sentence on every frame is unreadable, and reading it is the point.
step gives the rate three places and the years none; sensitivity is how many pixels of travel buy one step, so the rate moves faster under the same gesture. N(…) forces the decimal — without it the engine would hand back an exact power of a fraction.
A rate of
A knob that moves at one speed is either too fast for the last digit or too slow for the first. Every gesture here is in one of three gears: normal moves by step, coarse by ten steps, fine by a tenth of one — and there are three ways into a gear, so what you learn at the keyboard holds under the pointer and on a phone.
Shift for coarse or Alt for fine, while dragging or at the keyboard. PageUp/PageDown step coarse on their own.Drag the principal and drift upward to move by ten thousands, then back down into the band to settle the last thousand. Drift below the band on the rate to land on a quarter point.
A loan of
An integer knob has no tenth of a step to offer, so its fine gear keeps whole numbers and asks ten times the travel for each — the ladder says 1 slow. A real knob in fine gear lands off its own grid, and the readout grows a place to say so rather than rounding back onto it.
Typing. Sometimes you know the number. Enter, or a double tap, turns the value into a field; Enter commits and Escape puts the old value back. A count typed with a fraction is rounded, since the knob would otherwise show one number and bind another.
Vertical. axis="y" makes a one-axis knob drag up to raise, with the ladder on the horizontal — for a quantity the prose already treats as a height.
Focus a knob and press Space: it sweeps its range one step at a time, until you press again or touch it. play adds a ▶ beside the value for the mouse; autoplay starts the sweep when the knob scrolls into view and pauses it when it leaves, which is how an explainer animates itself without a reader having to find the button. A toggler plays too, cycling its entries.
Loop. What happens at the ends is the control's loop, and it governs every iteration — playback, a click on a toggler, the arrow keys: cycle wraps, reflect turns round, none stops there (and a play-through that has run to its end rewinds when played again). The arrows are a special case: they wrap on cycle and clamp on the other two, since pressing the other arrow is the reflection. A range has ends, so a numeric knob is none by default; a list goes round, so choices and togglers are cycle. A drag never loops — it is a position.
Speed. interval is milliseconds per step and rate multiplies it. Hold ▶ (or right-click it) for a panel with both the speed and the loop; a pick applies at once. The same panel opens off every ▶ there is: a Manipulate slider's, a plot's params, a worksheet binding's.
Press either ▶. The knob steps along its grid at a pace that covers the range in a few seconds and, being loop="cycle", starts over at the top — without that a numeric knob plays through once and stops. The toggler cycles its entries every second and a half. Hold either ▶ for the speed and loop panel.
At
A knob does not have to be real. complex adds the second axis: up raises the imaginary part, down lowers it, and the cursor changes to say so. Both parts stay on screen even when one of them reads zero — an axis you cannot see is an axis you cannot find again.
Drag horizontally for the real part, vertically for the imaginary one. The same gesture that moves a real knob along the line moves this one around the plane.
The number
Not every quantity is a number on a line. choices turns the knob into a scrub through a list — each step of the gesture moves one entry along, clamped at the ends rather than wrapped.
The
The more interesting discrete case is a family of objects, where the knob is an index and the thing it indexes is drawn. An integer knob is already that, and the glyph is just another template.
The knob is the ground-set size; the glyph and the count both read it. Neither knows the other exists.
Ground set of
The index unranks: the knob walks the 24 permutations of {1..4} in the collection's own order, and the glyph draws whichever one it lands on. No step here — a value written 1 rather than 1.0 already says it is a count.
Permutation
A number beside a picture is still one level removed: you move the number and the picture follows. Better is to put the gesture on the picture, so that walking a family of objects is the same motion as walking a range.
Give a knob children and they become the grip. It renders no number of its own — you drag whatever is inside it, and what you are dragging is the thing you are looking at.
Drag across the matrix. The knob is still an index into the 24 permutations of {1..4} — it just has nothing of its own on the page, and the ring on hover is the whole affordance.
The same gesture on a different family. Nothing in the sentence knows the control is a picture rather than a number — a knob publishes one binding whatever it looks like.
A toggler is a knob without an axis, and that is the whole difference between them. There is no direction to drag a word in, so a click steps it once and wraps, the arrows step it from the keyboard, and a long press (or right-click) opens a menu of every entry — the only way to reach the fifth of twelve without passing four.
A knob, having an axis, has no menu: choices is a list you brush along, and the two gestures would fight over the same press. Which one a quantity wants is the question worth asking — a list you move through is a knob, a value you pick is a toggler.
A toggler is a word you click. Entries are separated by |, since commas belong to the sentence. An entry that looks like a value is typeset; a word is set as prose. Either way the binding is a number — the entry's own value when it has one, and otherwise its index — so a toggle over words can still drive a condition.
Click the phrase to cycle it. The clause after it is a pane of a <pane-selector-box> keyed True, and appears only on the last entry.
There are
The other half of the sentence is the pane keyed False: one selector, two panes, each of them prose with its own markup in it.
A graph on
The binding does not stop at the prose. Any component attribute in the subtree that mentions a knob is a template too, so the same drag that changes a word changes the plot beside it. This is where a tangle stops being a nicer slider and starts being a document.
One knob, two axes, and a picture that has to be re-evaluated on every frame of the drag. This is the case a panel of sliders handles badly: the quantity is a point, and it wants a gesture with two directions in it.
Moving the pole
ew-resize, ns-resize for axis="y", move for a complex knob, and a plain pointer on a toggler, which has nothing to drag.role="slider" with a tab stop, and a click focuses it as a Tab would. The arrows along its drag axis step it (left/right, up/down for axis="y", both pairs on a complex knob — the keys teach the gesture), holding one accelerates through 1, 2, 5 and 10 steps a repeat, Shift/Alt and the Page keys change gear, Home/End take it to the ends and Enter opens the field. A document whose only affordance is a drag excludes the readers who cannot drag.min/max/step are all optional. What is left over comes from the same predictable ±10-or-wider window the worksheet sliders infer, so a knob's sensitivity is guessable before you touch it.step, a knob reads how its value was written: value="4" steps by one and value="4.0" does not. A count — a ground-set size, an index, a number of cookies — is written without a point precisely because there is nothing between its values, and a knob that says 4 and lands on 4.05 is reporting a quantity nobody meant it to have.Dynamic and Toggler are real Wolfram symbols, and the tags take them. The other three are not: Wolfram has no inline draggable value, no prose-run conditional and no reactive-document wrapper, so those keep descriptive names — which is what the naming rule says to do when there is no symbol to take.