Skip to content

figma-transformer: decode stroke weight/align/dashes so borders render at design width#335

Merged
chubes4 merged 1 commit into
trunkfrom
cook/figma-decode-strokes
Jun 29, 2026
Merged

figma-transformer: decode stroke weight/align/dashes so borders render at design width#335
chubes4 merged 1 commit into
trunkfrom
cook/figma-decode-strokes

Conversation

@chubes4

@chubes4 chubes4 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Per coverage issue #328, the Kiwi decoder's NodeChange field policy never whitelisted the stroke geometry fields, so strokeWeight/strokeAlign/dashPattern were dropped during selective decode. The emitter's strokeStyles() already read strokeWeight/strokeAlign, but with those fields gone every border rendered at the 1px default regardless of the design.

Changes

  • FigKiwiDecoder — whitelist strokeWeight, strokeAlign, strokeCap, strokeJoin, dashPattern, and the per-side border weights on the NodeChange policy. Per-side names are over-listed across both border*Weight/stroke*Weight shapes; unlisted fields are skipped (not mis-read), so the over-list is safe.

  • ScenegraphNormalizer — carry the stroke fields through component-instance resolution and instance-child override merges so instances render their own strokes.

  • StaticHtmlEmitter::strokeStyles() — honour the decoded geometry:

    • real strokeWeight on the border / outside box-shadow ring
    • per-side border-*-width when independent weights are present
    • box-sizing:border-box for INSIDE strokes so the box isn't grown
    • border-style:dashed for a non-empty dashPattern

    CSS borders can't reproduce exact Figma dash lengths (border-style only exposes the dashed keyword); precise dashes would need an SVG/background stroke, which is out of scope here.

Test

php tests/contract/run.php — all pass. New coverage:

  • A real Kiwi decode fixture (schema + message through the generic decoder) proving strokeWeight=3, strokeAlign=INSIDE and dashPattern=[4,2] survive the field policy.
  • An emitter fixture asserting an INSIDE stroke emits the exact border:3px solid #000000;box-sizing:border-box (no longer the 1px default).
  • An emitter fixture asserting a dashPattern emits border-style:dashed at the design width.

Refs #328

AI assistance

  • AI assistance: Yes
  • Tool(s): Claude Sonnet 4.6 via Claude Code
  • Used for: Implementation

…r at design width

The Kiwi decoder's NodeChange field policy never whitelisted the stroke
geometry fields, so strokeWeight/strokeAlign/dashPattern were skipped during
selective decode. The emitter's strokeStyles() already reads strokeWeight and
strokeAlign, but with the fields dropped at decode time every border fell back
to the 1px default regardless of the design (coverage issue #328).

- Whitelist strokeWeight, strokeAlign, strokeCap, strokeJoin, dashPattern, and
  the per-side border weights on the NodeChange policy. Per-side names are
  over-listed across both border*Weight/stroke*Weight shapes; unlisted fields
  are skipped, not mis-read, so the over-list is safe.
- Carry the same stroke fields through component-instance resolution and
  instance-child override merges so instances render their own strokes.
- Extend strokeStyles() to honour the decoded geometry: real weight on the
  border/box-shadow, per-side border-*-width when independent weights are
  present, box-sizing:border-box for INSIDE strokes, and border-style:dashed
  for a non-empty dashPattern (CSS borders can't express exact dash lengths;
  precise dashes would need an SVG/background stroke, out of scope).
- Add contract coverage: a real Kiwi decode fixture proving strokeWeight=3,
  strokeAlign=INSIDE and dashPattern=[4,2] survive the field policy, plus
  emitter fixtures asserting an INSIDE stroke emits border:3px (not 1px) and a
  dashPattern emits border-style:dashed.

Refs #328
@chubes4 chubes4 force-pushed the cook/figma-decode-strokes branch from cd272a7 to 1468889 Compare June 29, 2026 01:09
@chubes4 chubes4 merged commit 0a8d624 into trunk Jun 29, 2026
@chubes4 chubes4 deleted the cook/figma-decode-strokes branch June 29, 2026 01:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant