v5.6.0
This release introduces ICU MessageFormat and react-intl for translations, action-driven menu gating, and a ThrottledFunction type in @tldraw/utils. It also improves commenting, canvas navigation, and the select tool, and includes a broad set of bug fixes across selection, undo/redo, local persistence, sync, and the store.
What's new
ICU MessageFormat and react-intl for translations (#8036)
The SDK's UI strings now use ICU MessageFormat, allowing messages to support pluralization, selections, and values interpolation cleanly across languages. We've also added react-intl authoring on top: defineMessages and <F> declare and render messages with their default English next to the code that uses them.
Existing translations overridden by ID through overrides.translations continue to work unchanged.
API changes
- Add ICU MessageFormat translation support with
defineMessages,<F>, anduseTldrawI18n.useTranslation'smsgnow supports interpolating values through an optional second argument and accepts declared message descriptors. (#8036) - Add
isAvailable(editor),isEnabled(editor)andisChecked(editor)to actions. Menu items built withTldrawUiMenuActionItemandTldrawUiMenuActionCheckboxItemread them: an unavailable action is hidden, a disabled one is greyed out or hidden depending onwhenDisabled: 'hide' | 'disable'.useSomeActionsEnabledreturns whether any of the given actions is available and enabled, so a submenu can hide when none of its items can run. If you replace a built-in action with a new object instead of spreading it, it loses its gating, and a toggle's checkbox always shows as unchecked. (#11038) TldrawUiMenuActionItemnow disables itself when its action'sisEnabledreturns false, so custom menus that render built-in actions grey them out when they can't run. The public menu item wrappers, such asGroupMenuItem,FrameSelectionMenuItemandArrangeMenuSubmenu, now also hide outside the select tool, where their actions do nothing. (#11038)- Add a
ThrottledFunction<T>type to@tldraw/utilsfor annotating the result ofthrottle.throttlenow returns this type, with the same runtime behavior. (#10927) - Add
startCommentAt(editor, point)to@tldraw/commentingfor starting a comment thread at a specific canvas location from outside the comment tool. (#10970) TLSocketRoom.handleSocketMessage(sessionId, message, socket?),handleSocketClose(sessionId, socket?), andhandleSocketError(sessionId, socket?)now accept an optional originating socket parameter so messages and events from superseded connections are ignored. (#11067)- Add
LaserTool.startScribble()which adds a laser scribble to the current session, starting a fresh session if none is active. (#10781)
Improvements
- Menus no longer offer actions that would do nothing: grouping locked shapes, flipping a locked shape, unlocking when nothing is locked, exporting all shapes on an empty page, moving to a new page at the page limit, and grouping an arrow away from a shape it's bound to. The main menu hides Paste, instead of disabling it, in browsers that can't read the clipboard. (#11038)
- Allow keyboard navigation (Tab, Ctrl/Cmd+arrow, and the "Move focus to canvas" button) to reach locked shapes again, so keyboard users can select and unlock them. (#11134)
- Add a Comment item to the default canvas context menu when commenting is configured. It opens the comment composer where you right-clicked. (#11095)
- Move the comments filter menu to the right of the hide comments toggle in the comments panel header. (#11135)
- Cancel comment draft placement and return to the select tool when clicking the canvas, instead of moving the draft comment. (#10969)
- Draw the hinted outline around shapes, such as a frame you're dragging a shape into, at 2px instead of 2.5px. (#10952)
- Speed up
store.query.index()andstore.query.ids()updates by no longer allocating for each change. (#10228)
Bug fixes
- Fix the edge scrolling preference showing as off when edge scrolling is on at a speed other than 1, such as 0.5 or 2. (#11038)
- Fix edge scrolling jumping to partial speed after its start delay. (#11126)
- Fix three resize issues: flipping a rotated selection gave its children the wrong rotation, shapes not aligned with the selection received
onResizeStartandonResizeEndmore than once, andresizeBoxslid the fixed edge when a shape hit itsmaxWidthormaxHeight. (#10351) - Fix duplicating a page moving its shapes when they were off screen, and starting the new page with the current page's camera instead of the duplicated page's. (#10465)
- Fix the page menu closing and getting stuck mid-drag when Escape is pressed while reordering pages. (#11115)
- Fix an empty line under a heading in a text shape that could not be deleted. (#11114)
- Fix the "rhombus-2" (rhombus left) geo tool showing a raw translation key as its label. (#11062)
- Fix the keyboard shortcuts dialog opening via keyboard shortcut when
KeyboardShortcutsDialogis overridden withnull. (#11019) - Fix the rich text toolbar reporting the wrong operation in
onUiEventfor italic, code, and highlight. (#11018) - Fix undo after double-clicking a frame's corner or edge to fit it to content creating an inconsistent history step. (#11075)
- Fix undo reverting an earlier edit after brushing to select, right-clicking an empty canvas to deselect, pressing Enter on a group, or navigating the selection with the keyboard. (#10476)
- Fix clicking a child of a locked group selecting the locked group. (#10180)
- Fix bookmarks, notes, and other non-resizing shapes being mispositioned when their containing group is resized or flipped. (#10619)
- Fix bounds snapping not engaging while resizing or cropping shapes inside slightly rotated frames or groups. (#10181)
- Fix the arrow tool's precise mode carrying over when you move to a different target shape. (#10244)
- Fix holding Cmd/Ctrl+Shift+Arrow switching from selecting a parent or child to selecting the adjacent shape once the key starts repeating. (#10184)
- Fix arrow-key nudging moving diagonally after using a Cmd+Arrow shortcut on macOS. (#10892)
- Fix the eraser sometimes dropping a highlighted shape when dragging near a group. (#10182)
- Fix
editor.setCursorthrowing for the rotate and resize cursor types, and hex cursor colors breaking SVG cursors. (#10350) - Fix
editor.animateShapesthrowing aTypeErrorwhen interpolating draw or highlight shapes to or from empty segments. (#10771) - Fix the laser tool crashing when its scribble session times out mid-stroke. (#10781)
- Fix scribbles added without points disappearing after one idle frame before points could be added on pointer move. (#10336)
- Fix hit testing and viewport culling using stale bounds when text fonts finish loading after measurement, and fix container descendants retaining stale current-page membership when reparented to another page. (#10341)
- Fix edits being lost when an editor remounts with the same
persistenceKeywhile the previous one is still saving. (#10752) - Fix the comment composer requiring a second tap before focusing and raising the software keyboard on iOS. (#9957)
- Fix store changes made in the last frame before a listener is removed never reaching that listener. (#10802)
- Fix a reaction that writes to the store re-running on every unrelated store change. (#10236)
- Fix undo restoring an in-between state after a single
putupdated the same record twice. (#10203) - Fix store listeners and
extractingChangesreceiving changes from transactions that rolled back. (#10205) - Fix computed caches in
store.querynot re-running their derive functions when a previously removed record is recreated with the same ID. (#10225) - Fix
migrateStoreSnapshotthrowing on a malformed persisted schema instead of returning a migration error. (#10220) - Fix migrations rerunning on records when a persisted schema's sequence version isn't a number. (#10917)
- Fix a record deleted while offline occasionally reappearing after reconnecting. (#10997)
- Fix large chunked sync messages being dropped and active sessions being cancelled by a previous socket's late close or error when reconnecting with the same session ID. (#11067)
- Fix a resumed sync session on a hibernating host skipping the version checks made on first connect, so after a server redeploy a client could be sent changes its schema couldn't handle. It's now rejected with
SERVER_TOO_OLDorCLIENT_TOO_OLD, as on connect. (#10122) - Fix a record field set to
undefinedgetting the sync session kicked withINVALID_RECORD, and ignore__proto__keys in incoming changes. (#10118) - Fix older sync clients (protocol version 7) silently falling out of sync when the server sent them text-append changes they don't support. (#10095)
Prev
Next releaseNext
Migration skill