Summary
Setting pcbPositionMode="relative_to_board_anchor" (or any of the other PcbPositionMode enum values: "auto", "relative_to_group_anchor", "relative_to_component_anchor") on a chip/component in JSX has no observable runtime effect. The resulting pcb_component's position_mode field stays "packed" (the auto-placer's collision-avoidance mode), and the component lands wherever the placer puts it — not at the requested pcbX/pcbY.
The prop typechecks via PcbLayoutProps.pcbPositionMode in @tscircuit/props, so users assume it works. The runtime silently ignores it.
Repro
// index.circuit.tsx — board 22 × 20 mm, U1 should be at top edge
export default () => (
<board width="22mm" height="20mm" layers={2}>
<chip
name="U1"
footprint="dip8"
pcbX={0}
pcbY={4}
pcbPositionMode="relative_to_board_anchor" // ← typechecks but no-op
/>
<resistor name="R1" resistance="1k" footprint="0402" />
</board>
)
tsci build
jq '.[] | select(.type=="pcb_component") | {center, position_mode}' dist/index/circuit.json
# → { "center": { "x": 0, "y": 0 }, "position_mode": "packed" }
# Expected: center.y near 4, position_mode "relative_to_board_anchor"
Workaround
Add pcbX={0} pcbY={0} to the parent <group>. That presence-of-prop (regardless of value) flips the group into "relative_to_group_anchor" mode, and child pcbX/pcbY are then honoured. Discovered by JSON inspection on a real board after burning ~5 turns of debugging.
<board ...>
<group pcbX={0} pcbY={0}> {/* ← required */}
<chip name="U1" pcbX={0} pcbY={4} /> {/* now lands at (0, 4) */}
</group>
</board>
Why this matters
Component-level pcbPositionMode is the documented escape hatch for "place this exactly where I asked, ignore the auto-placer." When it silently doesn't work, there's no error, no warning — the component just shows up somewhere else. Without JSON inspection (jq against circuit.json), the failure mode is "I set pcbY=4 and the chip is at y=0 and I don't know why."
Suggested fix (any of)
- Implement the prop — wire it through to the placer so
relative_to_board_anchor actually skips the packed-mode collision-avoidance for that component.
- Or warn: at JSX-prop-parse time, log a
[tscircuit] pcbPositionMode is set on a component but is not yet implemented; positioning will fall back to "packed" mode unless the parent group has explicit pcbX/pcbY.
- Or remove from typings until implemented, so TypeScript catches the use.
Hit while placing an InsightSiP ISP3080-UX module on a daughter board — wanted U1 flush against the top edge. The pcbPositionMode prop on the chip seemed like the obvious knob; took several turns of bisection to find the group-level workaround.
Summary
Setting
pcbPositionMode="relative_to_board_anchor"(or any of the otherPcbPositionModeenum values:"auto","relative_to_group_anchor","relative_to_component_anchor") on a chip/component in JSX has no observable runtime effect. The resultingpcb_component'sposition_modefield stays"packed"(the auto-placer's collision-avoidance mode), and the component lands wherever the placer puts it — not at the requestedpcbX/pcbY.The prop typechecks via
PcbLayoutProps.pcbPositionModein@tscircuit/props, so users assume it works. The runtime silently ignores it.Repro
Workaround
Add
pcbX={0} pcbY={0}to the parent<group>. That presence-of-prop (regardless of value) flips the group into"relative_to_group_anchor"mode, and childpcbX/pcbYare then honoured. Discovered by JSON inspection on a real board after burning ~5 turns of debugging.Why this matters
Component-level
pcbPositionModeis the documented escape hatch for "place this exactly where I asked, ignore the auto-placer." When it silently doesn't work, there's no error, no warning — the component just shows up somewhere else. Without JSON inspection (jqagainstcircuit.json), the failure mode is "I set pcbY=4 and the chip is at y=0 and I don't know why."Suggested fix (any of)
relative_to_board_anchoractually skips the packed-mode collision-avoidance for that component.[tscircuit] pcbPositionMode is set on a component but is not yet implemented; positioning will fall back to "packed" mode unless the parent group has explicit pcbX/pcbY.Hit while placing an InsightSiP ISP3080-UX module on a daughter board — wanted U1 flush against the top edge. The pcbPositionMode prop on the chip seemed like the obvious knob; took several turns of bisection to find the group-level workaround.