Skip to content

feat: render Figma library components with correct z-ordering#30

Merged
trmquang93 merged 6 commits intomainfrom
feat/figma-library-component-rendering
Apr 11, 2026
Merged

feat: render Figma library components with correct z-ordering#30
trmquang93 merged 6 commits intomainfrom
feat/figma-library-component-rendering

Conversation

@trmquang93
Copy link
Copy Markdown
Collaborator

Summary

  • Render shared library component instances from Figma clipboard paste by resolving derivedSymbolData into full child trees
  • Fix vector icon rendering with proper stroke and fill paint extraction from kiwi format
  • Fix text wrapping by preserving kiwi text sizing properties (textAutoResize, maxWidth)
  • Fix z-ordering: Replace localeCompare with byte-level ASCII comparison for Figma's fractional position indices, which use mixed-case characters (!iRTY9 vs !P) that localeCompare sorts incorrectly
  • Bump mcp-server version to 1.1.1

Test plan

  • Paste a Figma frame containing shared library components from Figma Web
  • Verify popup overlays render in front of content (not behind)
  • Verify nav bar icons appear in correct left-to-right order
  • Verify all menu items are contained within their popup card
  • Compare HTML-rendered paste against Figma Desktop PNG paste for visual parity
  • All 628 tests pass

Library components (e.g. iOS status bars from Apple's UI Kit) were
invisible after pasting from Figma because their derivedSymbolData
contains rendering hints (fill geometry paths, glyph outlines, color
overrides) instead of full node trees.

- Add binary vector command blob decoder (MoveTo, LineTo, CubicBezier)
- Detect rendering-hint format derivedSymbolData (guidPath vs guid)
- Build approximate SVG from decoded geometry as generic fallback
- Add clean HTML/CSS renderer for iOS status bars with system icons
- Extract container background fills from unused symbolOverrides
- Embed derived content in figmaToHtml.js for INSTANCE nodes
The kiwi parser produces vectorNetwork data in a different format than
the REST API: vertices as {x, y} objects and segments as {start, end}
with nested vertex/tangent properties. The vectorNetworkToSvgPath
converter now detects and handles both formats, fixing icons that
previously rendered as blank colored squares.

Also preserves stroke properties (strokePaints, strokeWeight, strokeCap,
strokeJoin, fillPaints) from raw kiwi nodeChanges that the @grida/refig
factory drops, and renders proper SVG stroke attributes including
linecap, linejoin, fill-rule from winding rules, and overflow:visible
to prevent stroke clipping at viewBox edges.
Preserve textAutoResize from kiwi nodeChanges (dropped by @grida/refig
factory) and use it in figmaToHtml to control text sizing:
- WIDTH_AND_HEIGHT (auto-width): white-space nowrap, no fixed width
- HEIGHT (fixed-width): add 1px buffer for CSS font metric differences
The @grida/refig library sorts Figma node children using
String.localeCompare(), but Figma's fractional index strings
(parentIndex.position) use mixed-case ASCII characters designed for
byte-level comparison. localeCompare is case-insensitive and
alphabetical, producing wrong order (e.g. "i" < "P" alphabetically,
but "P" < "i" in ASCII byte order). This scrambles both z-index for
absolutely-positioned children and visual flow for auto-layout children.

Fix by:
- Preserving kiwi parentIndex.position on each factory node
- Re-sorting the entire _figFile tree after parsing with byte-level
  comparison (< / >) instead of localeCompare
- Using the same corrected comparator in buildDerivedTree for shared
  library component children
@trmquang93 trmquang93 merged commit e85b7d4 into main Apr 11, 2026
1 check passed
@trmquang93 trmquang93 deleted the feat/figma-library-component-rendering branch April 11, 2026 08:48
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