Doubled lines and connectors
The brand's doubled line as a component, with live gauge, gap, two-tone and pulse controls, and the production connector that carries a translation.
The doubled line is the General Translation connector: two parallel hairlines at a constant gap along any curve. It is one center path stroked twice, a full-width stroke in ink and a narrower stroke in the ground's color on top, so the ground carves the ink into two threads. Both strokes share one geometry, so the gap never drifts on a bend. The gt-diagrams skill holds the rules for drawing with it.
The doubled line
The plate draws two sources that merge into a trunk and a trunk that fans out to three outputs, each connector one DoubledLine. Gauge and gap set the thread width and the space between the threads. Two-Tone draws the upper thread in full ink and the lower one at half ink. Show Core paints the carving stroke in the accent, so the construction is visible.
The forks and the outputs draw first and the trunk draws last, so its core paints both junctions back into one clean pair with no offset-curve math. The moving pulse is geometry: each path is sampled once, and on every frame the pulse's d is rewritten to the slice under a traveling window. One window runs per journey, from a source through the trunk to one output, and it crosses each junction as one object because both slices come from one head coordinate.
Import and props
import DoubledLine from '@/components/shared/diagrams/DoubledLine';
<svg viewBox='0 0 720 240' aria-hidden='true'>
<DoubledLine d='M330 120 L680 120' core='var(--pt-paper)' ink='var(--pt-ink)'>
{/* the pulse slot: a stroke at the full width, gauge * 2 + gap */}
<path d='M470 120 L590 120' fill='none' stroke='var(--docs-accent)' strokeWidth={6} vectorEffect='non-scaling-stroke' />
</DoubledLine>
</svg>;| Prop | Type | Default | What it does |
|---|---|---|---|
d | string | required | The center path, the only geometry. |
core | CSS color | required | The color that carves. It must match the ground behind the line, or it shows as a stripe. |
gauge | number | 1.5 | Pixels per thread, held in screen pixels by non-scaling-stroke. |
gap | number | 3 | Pixels between the threads. |
ink | CSS color | rgba(255, 255, 255, 0.88) | The thread ink, white for an ink ground. Pass the ink token on paper. |
inkB | CSS color | none | A second ink for the other thread. Needs splitD. |
splitD | string | none | The center path closed off one side of the view box; the ink thread takes that side. |
children | SVG | none | The pulse layer, drawn between the threads and the core, so the core splits it into two hairlines. |
DoubledLine is a server component: it renders three paths and ships no JavaScript. The moving pulse needs a client component that samples the path and rewrites the pulse's d, as this plate and TranslationFlow do.
When to use it
Use the doubled line for every connector in a GT diagram: a flow from a source to its outputs, a route, a merge. Keep the defaults, 1.5 and 3, on the site and in the deck. A pulse is the drawing's one accent only when nothing else in the drawing takes the accent; otherwise it runs in the page ink. Never use the doubled line as a page rail beside the reading column, because it is a connector.
Reduced motion and themes
DoubledLine itself does not move. The host's pulse ships hidden and never starts under reduced motion; the still is a static window on the trunk, which this plate shows in place of the moving pulse. The threads read the stage's ink token and the core reads its ground token, so the line follows the docs theme.
The connector in production
The plate mounts TranslationFlow from the Toolchain direction as it ships. A real source component on the left forks into the three output files gt.config.json declares, one doubled trunk leaves the panel and splits at a drawn junction, and a pulse window carries each transfer from the trunk onto its branch. Replay remounts it, which restarts the staggered journeys.
Its three journeys leave 2.4 seconds apart and share one speed of 40 units a second, so branches of different lengths move alike.
Import and props
import TranslationFlow from '@/app/d/toolchain/diagrams/TranslationFlow';
<TranslationFlow title='A source component forked into its translated output files' />;| Prop | Type | Default | What it does |
|---|---|---|---|
title | string | none | The accessible name. |
className | string | none | A class on the root grid. |
The diagram reads --tc-plate as the ground its cores carve, --tc-panel as the source panel's ground and --tc-ink as the pulse's ink, so a host sets those three on an ancestor.
When to use it
Use it where a page explains what the build produces: one source file and the files it becomes. It is a whole figure with real content and a fixed set of files, so it takes a band or a plate of its own, up to 680 pixels wide.
Reduced motion and themes
Under reduced motion the loop never starts and the fork holds its still. The source panel stays ink in both themes, and the threads and the files follow the host's tokens.
Traps
SVG lines in motion explains each of these with its proof.
- Under
vector-effect: non-scaling-stroke, Chromium measures dashes in screen pixels and ignorespathLength:pathLength=100withdasharray 25 100draws a 25-pixel fleck where a quarter of the path was meant. Author a progress ring's dash in user units (pathLength under a non-scaling stroke). - A single travelling dash, its dasharray equal to the path length and its offset animated, tiles into several dashes on a scaled SVG under
non-scaling-stroke. Translate a short<line>in user units instead (a travelling dash that tiles). - A dash clips at the end of a closed subpath and never wraps the loop. Start the path where the arc starts, or use
dasharray d (L - d)(dashes on a closed path). - The sign of the parked offset picks the end a draw starts from: an offset tweened from +100 to 0 reveals from the path's first point, and from -100 from its last. A backwards draw was rejected three review rounds running in August 2026, so read the first point of
dbefore touching the timing (the sign of the parked offset). - A bare
100dash bleeds a sub-pixel fleck at the path's end in Chromium.strokeDasharray='100 200'parked at 101 or -101 keeps both ends clear, and offset 0 still covers the whole path (a fleck at the end of the path). - GSAP rounds offsets to whole numbers, so fine dash motion normalizes
pathLengthto 1000 (rounding, cached paths and empty paths). - An SVG stretched with
preserveAspectRatio="none"keeps straight segments straight, warps curves, turns circles into ellipses and distorts text. A stretched strip holds straight taps with one elbow and no text, and its labels live in HTML beside it. TranslationFlow's fork predates the rule and still bends its branches with cubic curves, which the gt-diagrams figure check warns on (drawing under a stretched viewBox). - The line audit rebuilds lines from computed CSS and cannot see SVG strokes, so check every junction of a connector by eye in 2x crops.
Dithered transitions and brushes
Tone-mix wipes on one cell grid, a lens that reveals a picture under the screen, and a brush that paints in dither cells.
Isometric drawings
The isometric kit live: one 30 degree projection, one corner radius and one light, with boxes and prisms built on a slab and a mark seated on a face.