Add global board viaTenting prop with per-via overrides, mask rendering and exports
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 58
- Forks
- 203
- Avg merge
- 7h 39m
- Merged PRs (30d)
- 286
Description
Versions: tscircuit 0.0.2516, @tscircuit/core 0.0.1892, @tscircuit/props 0.0.649, circuit-json 0.0.484, circuit-to-svg 0.0.413, circuit-json-to-gltf 0.0.118, CLI 0.1.2057, Bun 1.4.2, Linux. Native export comparison uses KiCad 10.0.2.
Request
Please expose via tenting in TSX and carry it consistently into mask-aware SVG/3D rendering and manufacturing exports. Our two-layer board uses local ground vias next to each SMD ground pin and a continuous bottom ground plane. We want both faces of these vias covered by solder mask while connector holes remain exposed.
Primary usage: one global board-level default (proposed API, not currently implemented):
<board viaTenting="both">
{/* All manual and autorouted vias inherit tenting on both faces. */}
<via name="GND_U1" pcbX={-1.85} pcbY={0}
holeDiameter="0.3mm" outerDiameter="0.6mm"
fromLayer="top" toLayer="bottom" connectsTo="net.GND" />
</board>
The global setting is required for this workflow: users should not have to repeat it on every via. Suggested values: "both" | "top" | "bottom" | "none". Inheritance should reach nested components/subcircuits and all generated routing vias belonging to this PCB; it should not spill into a separate child PCB.
Per-via overrides for exceptions:
<via name="GND_U1" pcbX={-1.85} pcbY={0}
holeDiameter="0.3mm" outerDiameter="0.6mm"
fromLayer="top" toLayer="bottom" connectsTo="net.GND"
tented />
tented would mean both sides. For asymmetric mask requirements, consider tented={{ top: true, bottom: false }}. The board default <board viaTenting="both"> must also apply to autorouter-generated vias, with explicit per-via overrides. Preserve existing behavior when no setting is supplied.
Current observations
- The installed ViaProps/viaProps schema has no tenting property.
- Circuit JSON already supports optional
pcb_via.is_tented; reuse it for the both-sides case rather than introducing a competing boolean. Per-side support would need a backward-compatible schema extension. circuit-to-svgrenders otherwise identical vias withis_tented: trueandfalseidentically even withshowSolderMask: true. ItscreateSvgObjectsFromPcbViaalways emits exposed copper and drill circles.circuit-json-to-gltfbakes board textures with this SVG path, so our detailed model also shows the vias as exposed.
Minimal texture-path reproduction:
import { convertCircuitJsonToPcbSvg } from "circuit-to-svg"
const board = { type: "pcb_board", pcb_board_id: "b", width: 4, height: 4,
center: { x: 0, y: 0 }, num_layers: 2, thickness: 1.6 }
const via = { type: "pcb_via", pcb_via_id: "pcb_via_1", x: 0, y: 0,
outer_diameter: 0.6, hole_diameter: 0.3, layers: ["top", "bottom"] }
const render = (is_tented: boolean) => convertCircuitJsonToPcbSvg(
[board, { ...via, is_tented }] as any,
{ showSolderMask: true, layer: "top" })
console.log(render(true) === render(false)) // true in the versions above
Expected acceptance checks
- A single board prop tents every manual and autorouted via, including vias inside nested components, without repeating props. Explicit per-via overrides take precedence; a separate child PCB has its own policy.
- TSX manual vias and board defaults for routed vias preserve explicit mask intent in circuit JSON.
- Mask-aware top/bottom SVGs and GLB textures show mask coverage on the selected faces. Copper inspection views can still show via copper and drills.
- KiCad exports preserve front/back tenting; Gerber mask output has no aperture at a tented via. Drill files retain the original plated hole. Tenting must not silently imply filled or plugged vias.
- Exposed connector pads/plated holes are unaffected.
- Test omitted settings, explicit false, both sides, one side, and overridden board defaults.
Local workaround: retain real pcb_via records with is_tented: true, set KiCad front/back tenting through its native API, and use mask-covered circular surfaces only in the rendering input. The workaround is not an upstream PR. This issue tracks the requested implementation so another agent need not rediscover the gap.
Related ground-plane workflow issues (different defects): #3901 and #3902.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the ViaProps/viaProps schema and trace how board defaults, nested components, and autorouter-generated vias become Circuit JSON pcb_via records. Inspect createSvgObjectsFromPcbVia in circuit-to-svg and the convertCircuitJsonToPcbSvg path used by circuit-json-to-gltf, then follow the manufacturing export paths. Done means global and per-via settings preserve explicit mask intent across JSON, SVG, GLB, KiCad, and Gerber outputs without changing drills or connector exposure.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- computer-graphics, embedded-iot
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100