apps/docs/content/releases/v5.2.0.mdx
This release brings in performance improvements across tldraw. The freehand ink algorithm now computes strokes 2–3x faster, shape resizing is quicker, and editor load time is reduced. Multi-click handling was simplified to double-click only to support improved mobile gestures. Plus it's easier to add shapes to frames, and dozens of bugs were fixed.
We rewrote the freehand ink algorithm. Draw and highlighter strokes now compute about 2x faster (up to 3x for long strokes) and produce 57% smaller SVG path data, with no visible change to how strokes look. The rewrite removes two rarely-used stroke APIs; see the breaking changes in API changes.
A new "Frame selection" action wraps the selected shapes in a frame with cmd+shift+f. When a frame is selected, the same shortcut removes it.
💥 Simplify multi-click handling to double-click only. ClickManager no longer tracks triple or quadruple clicks: the triple_click and quadruple_click events and the onTripleClick / onQuadrupleClick handlers have been removed, and TLClickEventName is now just 'double_click'. (#8897)
💥 Move ShapeIndicatorOverlayUtil and TLShapeIndicatorOverlay from @tldraw/editor to tldraw. Both are still exported from tldraw; update any imports of these symbols that came directly from @tldraw/editor. (#9018)
💥 Drop support for the EOL Node 20. The minimum supported Node is now >=22.12.0, the first version with native require() of ES modules, so tldraw can depend on ESM-only packages. (#9098)
💥 Type the collaborator user-id APIs as TLUserId instead of string. TLInstancePresence.userId / followingUserId, TLInstance.followingUserId / highlightedUserIds, Editor.startFollowingUser(), Editor.zoomToUser(), usePresence(), usePeerIds(), and the people-menu prop types now use TLUserId. Runtime behavior is unchanged: TLUserId is a branded string, so cast plain strings at the call site, for example editor.startFollowingUser(userId as TLUserId). (#9002)
💥 Remove StrokePoint.vector and setStrokePointRadii from the freehand stroke pipeline. The vector is derivable from consecutive points and radius/taper computation now happens inside getStroke and svgInk; nothing in the SDK consumed these outside the pipeline itself. (#9154)
💥 Remove the obsolete selection-background slot from @tldraw/editor: DefaultSelectionBackground, TLSelectionBackgroundProps, TLEditorComponents.SelectionBackground, and the useTransform helper. These were unused and have no replacement; remove any references to them. (#9362)
Add an embedConfig option to EmbedShapeUtil for passing per-embed configuration such as API keys. The default Google Maps embed no longer reads process.env.NEXT_PUBLIC_GC_API_KEY — pass the key explicitly instead. (#9068)
EmbedShapeUtil.configure({
embedConfig: { google_maps: { apiKey: '...' } },
})
Add an allowVideoAutoplay option to TldrawOptions. When set to false, no video shape autoplays regardless of its per-shape autoplay prop — including pasted and restored shapes. Defaults to true. (#8943)
Add ShapeUtil.getContentElement and ShapeUtil.onReleaseContentElement, an app-owned content element lifecycle that lets stateful shape content (such as cross-origin iframes) survive unmounting the editor. (#9167)
shift+q shortcut that copies the styles of the hovered shape and applies them to the next shapes you create. (#9028)title tooltips on menu items. (#9315)@tldraw/mermaid now loads its ESM-only mermaid dependency lazily, so the package is requirable from CommonJS and mermaid only loads when a diagram is created. (#9100)DOCS.md documentation in published npm packages, and a generated docs and release notes rollup in the tldraw package, so documentation is available when browsing package artifacts. (#8503)jittered-fractional-indexing dependency and speed up index key generation and validation; newly generated index keys are slightly shorter. (#9352)Tab while editing a list inside a note shape created a new note instead of indenting the list item. (#8958)debounce(...).cancel() leaving an awaited call hanging forever; it now rejects the pending promise. (#8683)cmd+shift+z) not firing after an undo (cmd+z) on macOS when cmd is kept held. (#9139)createBindings after createShapes). (#9183)moving when the editor is disposed during camera movement (e.g. React strict mode with a shared store). (#9201)CLIENT_TOO_OLD when the server is the one running an older version; it now correctly reports SERVER_TOO_OLD. (#9212)localhost (such as 127.0.0.1 and ::1) as production environments. (#9384)