openpencil/packages/fig/docs
Danila Poyarkov c47b5f8d1d
fix(fig): read, render, and write Figma slots (#850)
* fix(fig): read, render, and write Figma slots

Instances of a component with a slot showed the component's default
content instead of their own, and saving to .fig dropped slot properties,
their settings, and every instance's content.

Figma stores an instance's slot content as a frame on the internal canvas
and assigns the slot property that frame's GUID. The reader follows the
assignment while expanding the slot frame and pulls content frames into
the dependency closure without making them layers. The scene graph gains
a SLOT property type with its settings, a SLOT_CONTENT binding, and the
rule that an assigned slot's content belongs to the instance, which
component sync now leaves alone. The writer emits content frames on the
internal canvas and binds slot frames through the parameter map, as
Figma does.

The occurrence and diagnostic types move from the interpreter to
instance-overrides/occurrence.ts to keep it under the size limit.

* fix(fig): keep slot content through swaps and missing content frames

A slot assignment whose content frame the archive lacks no longer refuses
the document: the reader reports it through onMissingSlotContent, like a
missing component, and the slot keeps its component's content.

Swapping an instance's component, which variant switches do, now carries
the instance's own slot content to the new component's slot of the same
name instead of dropping it, as Figma does.

Component sync reads which slot a frame is from the component, whose
bindings instance copies do not receive. Clipboard export numbers slot
content after the other records on its dependency canvas, and the reader
and writer share Figma's default slot value.

* docs: note slot content kept across variant switches

* fix(fig): pair clipboard text by record and drop dangling slot assignments

The Figma clipboard paired text records with source text nodes by
traversal order, but instance-owned slot content is written after the
selected layers, so slotted text and the text after it swapped shaping
data. Records are now paired with their nodes through their GUIDs.

An instance assignment whose slot content frame is missing is dropped
along with the reported diagnostic, so the slot keeps following its
component instead of looking instance-owned.

* ci: pull the slots fixture for unit tests

* test: use GUID and Array.from in the slot tests

* refactor(fig): group occurrence types and paths in one folder

occurrence.ts and occurrence-path.ts became sibling prefixes when the
occurrence types moved out of the interpreter; they now live in
instance-overrides/occurrence/ as types.ts and path.ts.
2026-10-04 00:45:10 +04:00
..
observations feat(design-jsx): export every property the renderer accepts (#814) 2026-10-03 15:40:21 +04:00
architecture.md feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00
document-sessions.md feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00
export.md feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00
instance-evaluation.md fix(fig): read, render, and write Figma slots (#850) 2026-10-04 00:45:10 +04:00
materialization.md feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00
README.md feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00
source-model.md feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00
validation.md feat(fig): occurrence-scoped instance interpretation as the single .fig reader 2026-10-01 11:20:27 +04:00

FIG package architecture

These documents explain the .fig reader and its editing/export contracts. They are package implementation documentation, not a release-status log.

Reading order

Document Question
Architecture Which package owns each stage?
Source model What are records, resources, and identities?
Instance evaluation How do bindings and overrides resolve?
Materialization How do occurrences become editable nodes?
Document sessions How do incremental loads and recovery work?
Export How are runtime identities and claims encoded?
Validation What constitutes compatibility evidence?
archive -> source model -> instance evaluation -> materialization
                                                    |
                                  document sessions + editor actions
                                                    |
                                                  export
                                                    |
                                            Figma validation

Status vocabulary

  • Required invariant: a correctness constraint, whether or not all cases satisfy it yet.
  • Implemented: behavior present in the linked modules and covered by the cited tests.
  • Known limitation: a boundary not yet implemented or validated; not a supported fallback.

Every consumer uses this reader; the previous importer and its repair pipeline are gone, so there is one interpretation path, not a legacy mode. Remaining work is fidelity and performance acceptance against Figma, tracked per document as known limitations.

Keep temporary file keys, benchmark runs, experimental findings, and current blockers in ignored scratch/ notes or the integration PR. Fixture provenance belongs alongside fixtures. The public roadmap owns product-level direction.