v5.3.0
This release adds commenting: a set of new packages for anchored comment threads on the canvas, backed by comment records in the schema and sync support for non-document data. Commenting is the first piece of our new collaboration package, a separately licensed section of the SDK for premium collaboration features. The release also adds flipping for geo shapes, snapping and symmetric resizing while cropping images, an assets prop for TldrawImage, and a reactive Editor.getIsMounted() with a new unmount event. Viewport culling is faster on large pages, and there's a batch of fixes for crashes and interaction bugs across arrows, groups, and text.
Comments are now a first-class primitive in the SDK. @tldraw/commenting ships a batteries-included canvas comments layer: threads anchor to a point, a shape (precisely or imprecisely), a text range, a region, or the page. You can reply, edit, react, resolve, and delete comments. The pins drag to re-anchor, and ?comment=<id> deep links open a thread and bring the camera to its pin. Comment pins cluster together as you zoom out and separate back out as you zoom in.
Comment records live in @tldraw/tlschema as TLCommentThread, TLComment, and TLCommentReaction, and sync over a new generic object store in @tldraw/sync-core, so they ride alongside the document rather than inside it. On the server, @tldraw/sync-collaboration enforces write authorization, with a canModifyComment rule that lets a host widen the default owner-only permission. That way a workspace admin can moderate comments they don't own without granting anything beyond edit, delete, and resolve.
One rollout note: the comment record types ship with guard migrations, so once your server registers them, clients on an older SDK are rejected as too old and prompted to refresh. Roll out the upgraded client before or alongside the server change.
The layer is built to be taken apart. ThreadRow and ThreadActions are component slots, CommentListItem and sortSidebarRows are exported so a hand-built list can match the built-in one, and a host that supplies getThreadHref gets copy-link in the thread menu. On phones, the composer and the open thread stay above the software keyboard.
New packages
| Package | What it provides |
|---|---|
@tldraw/commenting |
Canvas comments layer, comment UI components, and the comment tool |
@tldraw/mentions |
@-mention picker and TipTap node, shared by comments and shape rich text |
@tldraw/collaboration |
Umbrella package for the collaboration pieces |
@tldraw/sync-collaboration |
Server-side write authorization for collaboration features |
See the commenting docs for setup.
-
💥 Remove
usePassThroughMouseOverEventsfrom@tldraw/editor. It re-dispatchedmouseoverat.tl-canvasso shapes under a floating panel stayed hovered, but the canvas only wiresonPointerEnter, so the re-dispatched event arrived at an element with no listener for it. (#9782) -
Add
TLCommentThread,TLComment, andTLCommentReactionrecords to@tldraw/tlschema, withcreateCommentThreadandcreateCommenthelpers, id helpers, validators, andcommentSchemaRecordsfor registering them. (#9471, #9782) -
Add a generic object store to
@tldraw/sync-corefor syncing non-document records:objectTypeson the room and storage constructors, per-sessionTLObjectStoreAccess,getObjectsSnapshot(),onCommittedChanges, and an optionalTLSyncStorage.getObjectsByIds(ids)for callers that need a few object-lane records rather than the whole lane. (#9471, #9782) -
Add
objectAccessto thesynced-remotemember ofRemoteTLStoreWithStatus, so a store fromuseSyncreports whether the session can write object-lane records such as comments. If you construct that type yourself, in test mocks for example, you now need to supplyobjectAccess. (#9471) -
Add
EditorPortal,EditorPortalProps, anduseEditorPortalHostto@tldraw/editor, for portalling canvas-anchored content into a host the editor renders last so its DOM order doesn't depend on mount timing. (#9782) -
Add
renderHtmlFromRichTextWithExtensions(richText, extensions)for rendering rich text outside a shape's editor config.renderHtmlFromRichTextnow fills every empty paragraph with a<br />and keeps the paragraph's attributes, so an empty paragraph renders as<p dir="auto"><br /></p>— worth knowing if you snapshot that output. (#9782) -
Add
flipXandflipYtoTLGeoShapeProps, with anAddFlipPropsmigration defaulting both tofalse, and addPathBuilder.transform(mat)for producing a transformed copy of a path. (#9530) -
Add an optional
sizeToContentAspectRatiotoEmbedDefinitionand a publicEmbedShapeUtil.resolveAspectRatio(shape). When set, an embed corrects its size after creation to its content's real aspect ratio, resolved from the URL's OpenGraph metadata via the editor's url asset handler. Existing custom embed definitions are unaffected. (#9613) -
Add
ExportAsMenuGroup, mirroringCopyAsMenuGroup, for the "Export as" submenu. (#9589) -
Add
EditorManager, a public abstract base class for editor managers that own a subscription or resource, so they share one teardown contract.InputsManager,TickManager,FocusManager, andTextManagernow extend it. (#9204) -
Populate
TLBaseExternalContent.sourcesfor file pastes, where it was previously always undefined, so customfileshandlers andonBeforePasteFromClipboardcan inspect the text, HTML, and url content that came alongside the files. (#9763) -
Add an
assetsprop toTldrawImage, so a snapshot's images render from a custom asset store the same way they do inTldraw. PreviouslyTldrawImagealways used the inline base64 asset store, so images kept anywhere else were missing. (#9697) (based on an implementation by @jon-dez)<TldrawImage snapshot={snapshot} assets={assetStore} />
-
Add an
unmountevent toTLEventMapand makeEditor.getIsMounted()a reactive value that tracks whether the editor's component is currently mounted. (#9472, #9483) -
Make the shape hit-test margin pointer-aware and add a
coarseHitTestMarginoption: fine pointers (mouse and trackpad) use a tighter 3px default, coarse pointers (touch and pen) use 4px. (#9492) -
Add a
ShapeUtil.onDuplicate(source, duplicate)callback, invoked byEditor.duplicateShapesandEditor.putContentOntoCurrentPage, so a shape can adjust its props when it is copied. Sticky notes now use it to attribute duplicated or pasted text to the current user instead of carrying over the original author. (#9566)
- Geo shapes now flip. Previously flipping a selection left directional shapes such as the rhombus, trapezoid, and arrow geo shapes looking exactly the same on the other side of the mirror.
TLGeoShapegainsflipXandflipYprops, matching the image shape, and a flip mirrors the shape's generated path. Geometry, hit-testing, the selection indicator, the canvas render, and SVG export all read from that path, so they stay in agreement. (#9530) - When cropping an image, crop edges now snap to other shapes and the grid, with the usual snapping guidelines. Holding Alt resizes the crop region symmetrically from its center. (#9424)
- Size embeds from providers that report their content's dimensions (currently Vimeo) to that content's real aspect ratio, so a video is no longer letterboxed inside a 16:9 box. The corrected embed keeps the area of the original box, so a portrait video doesn't balloon over whatever sits above and below it. (#9613, #9756)
- Hide the "Copy as", "Export as", and "Export file" submenus, and the main menu's export group, when a consumer has removed all of their actions through
overrides, instead of leaving an empty submenu trigger behind. (#9589) - Improve viewport culling performance on large pages: the spatial index now rechecks only the shapes affected by a change instead of every shape on the page. Custom shapes whose geometry depends on unrelated shapes (outside parent/child and binding relationships) are no longer automatically rechecked for culling when those shapes change; built-in shapes and standard patterns are unaffected. (#9093)
- Improve performance when deleting many shapes at once by batching page state cleanup. (#9456)
- Make long toast and dialog content wrap instead of overflowing, so long strings like URLs stay within the toast or dialog. (#9546)
- Delay the appearance of the "back to content" button by about a second so it no longer flickers during normal panning and zooming. Hiding stays immediate. (#9448)
- Remove the unnecessary ellipsis from the "Keyboard shortcuts" menu item. (#9570)
- Fix the
tldrawpackage failing to resolve@tldraw/stateand@tldraw/tlschemaon package managers that enforce strict dependency isolation, such as pnpm. Both were imported without being declared as dependencies. (#9762) - Fix the zoom keyboard shortcuts (
shift+1,shift+2, andshift+0) not working on non-US keyboard layouts. They matched on the typed character, so on layouts whose shifted number row differs from US QWERTY — British PC and German, for example — zoom to selection did nothing and zoom to 100% zoomed in instead. Number-row shortcuts now resolve by physical key. (#9863) - Fix comments folded into a cluster badge lagging behind their shape while the shape is dragged. A clustered pin now pops out of its badge on the drag's first movement and rides its anchor, instead of correcting only on pointer up. (#9878)
- Fix
usePassThroughWheelEventslosing its listener when the element its ref points at unmounts and remounts while the component stays mounted. Comment pins that had scrolled off-screen and back swallowed wheel events instead of passing them through to the canvas. (#9882) - Fix zooming and panning not working while the cursor is over a non-scrollable UI overlay. The wheel pass-through guard treated any element whose content overflowed as scrollable, and a hover transform on a small overlay was enough to trigger that. Overlays now count as scrollable only when their computed
overflowsays so. (#9698) - Fix a crash when dragging content from another browser tab whose URL isn't a valid link, which happens when an ad blocker rewrites the dragged URL to something like
about:blank#blocked. Dropping one now shows an error toast instead of failing validation on the bookmark shape. (#9598) - Fix the "URL" label wrapping onto two lines in the edit link and embed dialogs. (#9663)
- Fix rich text headings (H1–H6) rendering with their line-height too tight, causing overlapping lines. (#9543)
- Fix the style panel not highlighting the active fill correctly when the current fill lives in the overflow dropdown. (#9509)
- Fix the style panel Shape, Line, and spline dropdown popovers so they open with the same gap as the other dropdowns. (#9491)
- Fix double-clicking a shape inside an unfocused group immediately editing it; a double-click now drills one level into the group. (#9488)
- Fix selected clipped arrows so they can be dragged when their geometry extends outside a clipping parent. (#9479)
- Fix arrows bound to frames so they duplicate and delete with the frame without being clipped. (#9470)
- Fix a shape dragged from the toolbar to a frame beneath the toolbar not being parented to the frame. (#9458)
- Fix a missing
onChildrenChangecall when creating a shape directly within a parent shape. (#9455) - Fix the reactive Meta (Cmd) key state not clearing on keyup until a pointer event on macOS, which affected
getMetaKey()andgetAccelKey(). (#9404) - Fix a crash when dragging a handle on a line whose point keys differed from their indices. (#9299)
- Fix arrow bindings floating outside a geo shape after changing its geo type; precise bindings now re-snap to the nearest point on the new shape. (#9281)
- Fix an occasional crash in text measurement by iterating over grapheme clusters instead of individual characters, keeping emoji, flags, and accented characters intact. (#9266)
- Fix a crash ("Shape not found") when dragging a tool from the toolbar in a read-only room. (#9225)
- Fix sync clients not recovering from a malformed WebSocket message; they now restart the connection so a corrupt frame can no longer silently leave the client out of sync. (#9380)
- Fix uploaded asset handling for invalid R2 object names. (#9495)
- Fix a crash when a custom font failed to load after its editor had been disposed. (#9494)
- Fix license expiry being evaluated in local time, which could deactivate a license a calendar day early for users west of UTC; the expiry date is now treated as the last fully usable day in UTC. (#9475)
@quasar/app-vite-v3.4.1
- Security: bumped
@fastify/staticfrom^9.1.1to^10.1.2in the SSR Fastify template — fixes a route-guard bypass via path traversal (high severity) and an authorization bypass via non-canonical URL paths. - This only affects newly generated SSR projects using the Fastify variant. Existing projects should manually bump
@fastify/staticto^10.1.2insrc-ssr/package.json. The only breaking change in v10 is thesetHeaderscallback signature (now receives aFastifyReplyinstead of a rawResponse) — the template doesn't use it, so no code changes are needed unless you added it yourself. - Upgraded more template spawned deps
Quasar Framework is an open-source MIT-licensed project made possible due to the generous contributions by sponsors and backers. If Quasar is useful in your workflow and you want to support ongoing maintenance, please consider the following:
@quasar/icongenie-v6.1.3
- refactor(icongenie): Replaced the third-party update-notifier dependency with the new in-house @quasar/update-notifier package — same daily, non-blocking update checks with a noticeably lighter install (~40 fewer transitive packages). Update checks still respect CI environments and npm scripts, and can be disabled with the NO_UPDATE_NOTIFIER env var. The notification banner now follows the CLI's color settings (FORCE_COLOR, NO_COLOR, --no-color). Custom registries (npm_config_registry) are supported; prerelease versions are never suggested as update targets.
Quasar Framework is an open-source MIT-licensed project made possible due to the generous contributions by sponsors and backers. If Quasar is useful in your workflow and you want to support ongoing maintenance, please consider the following:
@quasar/cli-v5.0.5
This is the optional globally-installed part of the Quasar CLI
- feat(cli): upgraded deps
- refactor(cli): Replaced the third-party update-notifier dependency with the new in-house @quasar/update-notifier package — same daily, non-blocking update checks with a noticeably lighter install (~40 fewer transitive packages). Update checks still respect CI environments and npm scripts, and can be disabled with the NO_UPDATE_NOTIFIER env var. The notification banner now follows the CLI's color settings (FORCE_COLOR, NO_COLOR, --no-color). Custom registries (npm_config_registry) are supported; prerelease versions are never suggested as update targets.
Quasar Framework is an open-source MIT-licensed project made possible due to the generous contributions by sponsors and backers. If Quasar is useful in your workflow and you want to support ongoing maintenance, please consider the following:
3.50.0 - 2026.08.05
- Changes v3.49.0...v3.50.0 (138 commits)
- Joint iteration proposal:
- Built-ins:
Iterator.zipIterator.zipKeyed
- Moved to stable ES, May 2026 TC39 meeting
- Added
es.namespace modules,/es/and/stable/namespace entries
- Built-ins:
Iteratorchunking proposal:- Built-ins:
Iterator.prototype.chunksIterator.prototype.windows
- Throw a
TypeErrorinstead ofRangeErroron non-integer numberchunkSize/windowSize, following tc39/proposal-iterator-chunking/#30 - Moved to stage 3, May 2026 TC39 meeting
- Added
/actual/namespace entries, unconditional forced replacement changed to feature detection
- Built-ins:
- Added
Iteratorincludes stage 3 proposal:- Added built-in:
Iterator.prototype.includes
- Added built-in:
- Added
Iteratorjoin stage 3 proposal:- Added built-in:
Iterator.prototype.join
- Added built-in:
- Added Await dictionary of Promises stage 3 proposal:
- Added built-ins:
Promise.allKeyedPromise.allSettledKeyed
- Added built-ins:
- Throw a
RangeErroron finite unsafe integerlimitinIterator.prototype.{ drop, take }, following tc39/ecma262/#3776 - Use
PromiseResolvesemantics inPromise.try, following tc39/ecma262/#3883 - Added detection of missed Webkit ~ Safari < 26.2
Iterator.prototype.flatMapbug case, #1538 - Deno 2.9+ replaces
Object.prototype.__proto__instead of removing it, so the feature detection updated - Fixed
JSON.stringifypolyfill with an array replacer - keys order now follows the replacer, inherited and non-enumerable properties are no longer ignored, #1539 - Make
URL/URLSearchParamsparsing a little more correct (char sets, percent coding, etc) - Ensure opaque paths always roundtrip in URL polyfill (still without adding to feature detection), whatwg/url#844
- Fix
URL#toJSONwhenURL#toStringis reassigned after core-js is imported - Fixed possible crash on some keys in
Symbol.for - Some
get-iterator/get-iterator-methodfixes - Fixed
String.prototype.{ match, search }polyfills conversion order - Added missed
MAX_SAFE_INTEGERexcess check inArray.fromand{ Map, Object }.groupBypolyfills - Improved the way of inner iterators cleaning in iterator helpers
- Improved accuracy of
Math.{ asinh, cbrt, log1p }polyfills with big and small values - Improved performance of
Uint8Arraybase64 methods - Improved performance of
escape - Slight performance improvement for engines with native
Array.prototype.fillonArrayBufferconstructor and%TypedArray%.prototype.fill - Clarify supported Node versions in
package.jsonof some missed packages (just to satisfypublint) - Compat data improvements:
- Following tc39/ecma262/#3776,
Iterator.prototype.{ drop, take }properly supported from:- V8 ~ Chrome 150
- Safari 27.0
- Bun 1.4.0
- Following tc39/ecma262/#3883,
Promise.trymarked as not properly supported in all engines Iterator.prototype.{ chunks, windows }marked as shipped in FF154Iterator.prototype.includesmarked as shipped in FF154Iterator.prototype.includesmarked as shipped in Bun 1.4.0Iterator.prototype.joinmarked as shipped in FF154Array.prototype.includesWebKit bug marked as fixed in:- Safari 27.0
- Bun 1.3.12
queueMicrotaskBun bug marked as fixed in Bun 1.4.0- Added Node 26.0 compat data mapping
- Added Deno 2.7.8, Deno 2.8.0, and Deno 2.9.4 compat data mapping
- Updated Electron 42 and added 43, 44, and 45 compat data mapping
- Added Samsung Browser 30 compat data mapping
- Added Oculus Quest Browser 144+ compat data mapping
- Added Opera for Android 97, 98, 99, and 100 compat data mapping
- Following tc39/ecma262/#3776,
v9.3.0
A big thanks to the 18 contributors who made this release possible. Here are some highlights ✨:
- ♿️ Keyboard navigation in the Toggle Button Group now follows the roving tabindex pattern.
- ♿️ The Autocomplete announces its loading and no options messages through a new
statusslot.
- [autocomplete] Wrap the no results and loading messages in an aria live region (#48690) @silviuaavram
- [buttongroup] Respect global disableRipple / disableFocusRipple in grouped buttons (#48762) @siriwatknp
- [checkbox][radio] Respect global disableRipple from MuiButtonBase defaultProps (#48795) @siriwatknp
- [formcontrollabel] Add missing
labelPlacementEndclass (#48843) @siriwatknp - [listitembutton] Fix typos in component code (#48868) @ZeeshanTamboli
- [menuitem] Add
aria-checkedfor checkbox and radio menu items (#48651) @siriwatknp - [modal] Replace custom findIndexOf with findIndex (#48827) @ZeeshanTamboli
- [modal][dialog] Fix scrollbar compensation in Shadow DOM (#48826) @ZeeshanTamboli
- [select] Fix endAdornment overlapping the open indicator (#48723) @siriwatknp
- [tablepagination] Add focus style to default InputBase used in Select (#48871) @silviuaavram
- [togglebuttongroup] Add roving tabindex keyboard navigation (#48849) @silviuaavram
- Prevent prototype pollution in cssVarsParser (#48822) @Janpot
- Don't leak state between files in v5.0.0/path-imports (#48797) @manbearwiz
- Remove use of eval() (#48701) @oliviertassinari
- Transform all style exports in
v5.0.0/path-importscodemod (#48800) @manbearwiz
- Clarify
containerprop inheritance for Shadow DOM (#48670) @Juan-C-Ceballos - Clarify third-party script risk in CSP unsafe-inline note (#48787) @Janpot
- Document
box-sx-propcodemod (#48888) @SR0725 - Document Grid direction column removal in v9 upgrade guide (#48880) @kalayciburak
- Fix color contrast in GitHub labels example (#48844) @silviuaavram
- Fix per-page canonical URL and stale SEO link (#48789) @brijeshb42
- Fix redirect loop on the Design Kits page (#48869) @Janpot
- Fix typo 'overriden' -> 'overridden' in CHANGELOG (#48785) @ZhouYinLong-lab
- Improve TransferList examples (#48845) @silviuaavram
- Link a new theme generator tool (#48847) @mansourcodes
- Remove broken learning resource links (#48598) @morning-verlu
- Update the 9.2.0 changelog (#48763) @silviuaavram
- [autocomplete] Clarify how to render custom start and end adornments (#48883) @DebadityaHait
- [drawer] Clarify clipped AppBar spacing (#48887) @rushijagani-dev
- [menu] Fix stale
selectedprop reference in Selected menu section (#48879) @LukasTy - [skeleton] Document preserving typography sizing with custom border radius (#48596) @meaqua9420
- [blog] Fix caret annotation broken by Prettier wrapping (#48884) @bernardobelchior
- [code-infra] Automate team sync on about page (#48794) @brijeshb42
- [code-infra] Bump @mui/internal-code-infra to 0.0.4-canary.101 (#48878) @Janpot
- [code-infra] Fix Dependabot alerts (#48756) @Janpot
- [code-infra] Fix team sync PR creation (#48911) @brijeshb42
- [code-infra] Pin node version in publish CI (#48799) @brijeshb42
- [core-docs] Tighten service worker host check (#48581) @Janpot
- [docs-infra] Change branch name to the allowed one (#48910) @brijeshb42
All contributors of this release in alphabetical order: @bernardobelchior, @brijeshb42, @DebadityaHait, @Janpot, @Juan-C-Ceballos, @kalayciburak, @LukasTy, @manbearwiz, @mansourcodes, @meaqua9420, @morning-verlu, @oliviertassinari, @rushijagani-dev, @silviuaavram, @siriwatknp, @SR0725, @ZeeshanTamboli, @ZhouYinLong-lab
v3.5.41
For stable releases, please refer to CHANGELOG.md for details. For pre-releases, please refer to CHANGELOG.md of the minor branch.
v3.5.41
For stable releases, please refer to CHANGELOG.md for details. For pre-releases, please refer to CHANGELOG.md of the minor branch.