Tangent
A tangent mate keeps two surfaces touching. Unlike the other joints it is not written on connectors but on exposed geometry: a cylindrical or spherical face against a plane, a cam against a follower, a roller on a track. The parts keep every freedom that does not break the contact.
| Free motion | anything that keeps the surfaces in contact |
|---|
In the viewport
- Click Tangent on the assembly toolbar. Instead of connector triads, the exposed faces of the inserted parts are offered as pick targets.
- Click the roller's tread, then the plate's top face. The roller drops until it touches.
- Click Apply. Drag the roller and it rolls across the surface.

The code behind it
Each part publishes the surface with expose(); the mate reads them as instance.features.<name>:roller.part.js
import { assembly, insert, mate } from 'fluidcad/core';
import { plate } from './asm-plate.part.js';
import { roller } from './asm-roller.part.js';
export const rollerStand = assembly('roller-stand', () => {
const deck = insert(plate).grounded();
const wheel = insert(roller).translate(-20, 0, 30);
// Tangent is written on exposed geometry, not connectors: the roller's
// tread touches the plate's top face. The contact side comes from the
// faces themselves, so there is nothing to flip, rotate or offset.
mate('tangent', wheel.features.tread, deck.features.deck);
});
Options
mate('tangent', wheel.features.tread, deck.features.deck)
.noPropagate() // touch only the picked face, not its tangent chain
The contact side comes from the faces themselves (which way each surface faces in the B-rep), so there is nothing to flip, and a tangent mate has no joint frame — .rotate(), .offset() and .limits() are refused.
By default the contact propagates along a tangent-continuous chain: a filleted edge blending into a face counts as one surface, so a follower rides over the blend without a jump. .noPropagate() restricts the contact to the one face you picked.
Supported surfaces
Planes, cylinders, cones and spheres. A torus or a free-form face cannot be a tangent side; the mate fails with a message naming the face.
Both sides are exposures
mate('tangent', …) refuses connectors, and the other mate types refuse exposures — the two kinds of side are not interchangeable. Publish the faces inside the parts with expose().