Tailwind v4 drops theme variables no utility uses, but page code also
reads tokens through var() and (--name) utilities, so the export keeps
them all. Two test assertions mixed && and || without parentheses.
- Text that already fits keeps its exact size; shrunk sizes round to a
tenth but never below minSize (per run, its share of it).
- A last line after a hard break is not an orphan, and the no-break space
is only placed inside the last paragraph.
- docs: data.fill documents formats? and errors?.
On a device, a presented frame bigger than the screen now scrolls through
its whole size whatever its overflow, as Figma documents for top-level
frames. Before, "No scrolling" frames only clipped, so the landing page
template's long Phone frame couldn't be scrolled in Present. Content past
a frame's own edges still scrolls only on the axes its overflow allows.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Board files (File > New board) with sticky notes, shapes with text, connectors that follow what they join (straight or elbow, arrowheads, labels), marker, highlighter and eraser, and stamps; a board toolbar and a contextual bar; the Design panel hidden on boards, Prototype and Dev Mode refused there. Boards are ordinary FigCraft files built from ordinary layers, so saving, undo, export, MCP and live sessions work unchanged. File tabs, recent files and Open files show a pen nib for design files and a note for boards (original icons drawn in code).
Import lines for connected components inside generated layer trees; Compare changes against any saved version; a Dev Mode behaviour suite with an inspect-only canvas (menus, shortcuts, paste and Revert to saved refuse design edits; a drag under way is dropped on entering), Changed in the ready list, statuses only on top-level frames and sections; read-only plugins' panels from the Inspect tab.
* Dev profile: line tables for workspace crates, no debug info for dependencies
* Tests: one integration-test binary per crate with several test files
* xtask ci: nextest, doctests, tests without examples, --keep-going; add xtask test
Adds crates/ui-egui/locales/it.toml: all 1747 UI strings (42 plural entries,
one/other), 574 command labels and 31 menu wordings, marked as a draft awaiting
native review like the other machine-drafted catalogs. Adds a resolve/plural
test for Italian locales and lists Italian in docs/translating.md.
Not compiled locally; the catalog was validated with a script (same keys as
en.toml, identical placeholders and ellipses per entry).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fr2xzM8A8RiUwZWddELBCt
With points selected in more than one edited layer the transform box now
wraps them all, in the page's axes since the layers can be turned
differently. Its corners and edges scale them, outside a corner rotates
them and inside drags them; each layer's points are mapped in its own
coordinates and the whole drag is one undo step. A click inside clears
every layer's points.
Review: " . .name. . " kept inner dots at the edges; trim spaces and dots
in one pass. docs/cli.md and safe_file_name's comment give the 100 and
200 character limits.
`figcraft-cli mcp --help` failed with "unknown option --help" and
exit code 2; only a leading --help worked. The argument parser now
returns CliError::Help for --help or -h among a subcommand's options
(not as an option's value), and main prints the usage on stdout with
exit code 0. docs/cli.md says so.
export into a folder replaced every character outside letters, digits,
'-', '_', space and '.' with '_', so a frame called
"Homepage - desktop (live + verbeteringen)" became
"Homepage - desktop _live _ verbeteringen_.png". The app's
file.exportLayers keeps those names and only replaces what file systems
refuse. The CLI now uses the engine's safe_file_name, and docs/cli.md
says which characters are replaced.
Also adds my own entry to contributors/people.toml.
node.create, node.set and the other prop appliers map fill/stroke
"none" (either case) and null to an empty fills/strokes list, as
fills: [] already did (undocumented), so an outline-only shape is one
call - agents write "none" for no paint. KEYS and docs/mcp.md
document it; the error names the accepted forms. fill_none_tests
covers create, set, undo, text and the error.
Change to rebuilt the instance from the new variant, and set variable
and set variable mode re-applied bindings, but the player never laid the
result out: no text sizing, no auto layout. A hugging button with a
longer label than its main showed the other variant at the main's width,
its label clipped, and a text bound to a variable kept its old size.
These actions now run the engine's normalize on the player's document
afterwards, the pass that follows every edit on the canvas: text resizes
to what it shows, instances follow and auto layout reflows.
A Button main's override on its icon instance's glyph (a red fill) was
lost when an instance swapped the icon: the outer rebuild re-copies the
glyph from the main's layer with no overrides of its own, so the nested
rebuild matched it by name and carried nothing. Before that rebuild, each
old layer of the swapped instance now takes the overrides held along the
source chain it had before this rebuild, through layers inside instances
in the mains that place the swapped instance. Geometry, slot content and
groups the layer overrides itself are left out. Matched by name, the
values carry onto the new main's layer as the instance's own: inherited
at the swap, frozen after, and back to the icon main's value on reset.
An icon main's own overrides stay with it.
apply_order gave fillStyle, strokeStyle, effectStyle, gridStyle and
textStyle the rank of plain values, so the JSON map's byte order decided:
fills, strokes, effects, grids, layoutGrids and variationSettings sort
after their link and overrode it (node.set then unlinked the style;
node.create kept a link its values contradicted). Style links now apply
after the values and x/y, just before boundVariables. A deviation set in a
later call still unlinks.
- inspect.code {language: "tailwind"}: a layer tree as a React component
styled with Tailwind CSS v4 utilities, no stylesheet. Auto layout maps to
flex utilities on the spacing scale; fixed-width auto layout frames, text
and wide layers become fluid (w-full max-w-[…]); instances are inlined
with their overrides, except those connected to code (codeConnect), which
are their snippet with one import each; bound variables are theme
utilities (bg-accent, rounded-card).
- mobile: <frame id> (same layer names): mobile-first code, desktop classes
that differ behind lg:, resets for desktop defaults, padding compared per
side; layers only on desktop are hidden below lg, those only on mobile are
listed in the header.
- variable.export {format: "tailwind"}: @import "tailwindcss" and an @theme
block (--color-*, --radius-*, --text-*, --spacing-*, --font-*), names
unique per file and shared with page code.
Builds on the token roles of the CSS export px fix (#1008).