Skip to content

[pull] main from tldraw:main#473

Merged
pull[bot] merged 4 commits intocode:mainfrom
tldraw:main
Apr 1, 2026
Merged

[pull] main from tldraw:main#473
pull[bot] merged 4 commits intocode:mainfrom
tldraw:main

Conversation

@pull
Copy link
Copy Markdown

@pull pull Bot commented Apr 1, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

steveruizok and others added 4 commits April 1, 2026 07:40
In order to give tldraw.com a distinctive, warm visual identity inspired
by [Granola's design
system](https://www.granola.ai/blog/a-new-look-for-granola), this PR
replaces the default cool blue/gray UI theme with Granola's olive green
and warm neutral palette across both light and dark modes.

Key changes:
- **Editor theme overrides** in `globals.css` — warm off-white surfaces
(`#f7f7f2`), olive green accents (`#576f00` / `#788c15`), warm gray text
hierarchy, and warm-tinted shadows. Applied site-wide via
`.tl-theme__light` / `.tl-theme__dark` selectors.
- **App chrome colors** in `tla.css` — updated all `--tla-*` variables
(sidebar, buttons, CTAs, borders) to match the Granola palette for the
authenticated app UI.
- **Flash-prevention colors** in `theme-init.js` and `globals.css` —
hardcoded background/text values updated to match the new theme.
- **Favicons** — dotcom and examples app favicons updated to olive green
(`#b2c248`) background with dark icon (`#292929`).

The SDK-level defaults in `packages/editor/editor.css` are untouched —
these overrides are scoped entirely to the dotcom app.

### Change type

- [x] `improvement`

### Test plan

1. Run `yarn dev-app` and verify light mode: warm off-white canvas,
olive green selection/focus, warm gray panels
2. Toggle to dark mode: charcoal surfaces, olive green accents, warm
white text
3. Open a shared/public room (non-authenticated) and verify the theme
applies there too
4. Check favicon in browser tab shows olive green background

- [ ] Unit tests
- [ ] End to end tests

### Release notes

- Update tldraw.com color theme to a warm, Granola-inspired palette with
olive green accents and warm neutrals

### Code changes

| Section         | LOC change  |
| --------------- | ----------- |
| Apps            | +176 / -82  |
#8388 changed the dotcom color palette but didn't update the e2e test
that asserts background colors in light/dark mode. This PR updates those
assertions to match the new Granola-inspired colors.

### Change type

- [x] `bugfix`

### Test plan

- [x] End to end tests

### Code changes

| Section | LOC change |
| ------- | ---------- |
| Tests   | +4 / -4    |
In order to verify no permission regressions after the Zero 0.25
migration (PR #7731), this PR adds comprehensive unit tests for all
mutator permission logic in `packages/dotcom-shared`.

Relates to #7731

### What's tested

- **User mutations**: self-update, cross-user forbidden, immutable
fields, flags mutability
- **File mutations**: group-member update, shared-user write forbidden,
immutable fields (ownerId, owningGroupId, isDeleted), non-member
forbidden
- **File creation**: group membership check, non-member forbidden
- **File state**: self-update, cross-user forbidden, server-side
inaccessible file forbidden
- **onEnterFile**: server access check, no-access forbidden, no
duplicate group_file
- **Group CRUD**: create group, owner update/delete, admin forbidden
- **Membership**: owner sets roles, admin forbidden, last owner
demotion/leave forbidden, member leave
- **Cross-group file ops**: moveFileToGroup, removeFileFromGroup,
addFileLinkToGroup with various access levels
- **Home group shortcut**: userId === groupId bypass for member/owner
checks
- **Invite secret**: admin regenerate, non-admin forbidden
- **Immutable column bypass attempts**: ownerId, owningGroupId,
isDeleted (including falsy values), firstVisitAt
- **Cross-user isolation**: unrelated users cannot access each other's
files

### Scope note

TLDrawDurableObject's room access logic (the code that checks file
ownership, group membership, and shared status when a user opens a file
in the editor) was not changed by the Zero 0.25 migration — it uses
Kysely queries directly, not the mutator layer. File room access should
remain the same.

### Bug fix

Fixed `disallowImmutableMutations` truthiness bug: was using
`!data[col]` which allowed falsy values like `false`, `0`, `null` to
bypass the immutable guard. Now uses `!(col in data)` to check key
presence instead.

### Change type

- [x] `improvement`

### Test plan

1. `cd packages/dotcom-shared && yarn test run`

- [x] Unit tests

### Code changes

| Section    | LOC change  |
| ---------- | ----------- |
| Source     | +1 / -1     |
| Tests      | +1100 / -0  |
…state (#8396)

Fixes #8386

When using deep links with React strict mode (or any scenario where the
editor is disposed mid-camera-transition), the camera state can get
permanently stuck at `'moving'`. This keeps the `tl-hit-test-blocker`
div covering the entire canvas with `pointer-events: all`, blocking all
shape interactions (resize, rotate, select, etc.).

**Root cause:** When the editor is disposed, `TickManager.dispose()`
stops the tick loop, but the camera decay callback (subscribed to the
`'tick'` event) never fires, leaving `cameraState` stuck at `'moving'`
in the shared store. The next editor instance inherits this stale state.

**Fix:** Add a disposable that resets `cameraState` to `'idle'` and
unsubscribes the decay callback when the editor is torn down. This
follows the React cleanup pattern — each editor instance properly cleans
up its transient state on dispose.

### Change type

- [x] `bugfix`

### Test plan

1. In `apps/examples/src/index.tsx`, set `ENABLE_STRICT_MODE = true`
2. Run `yarn dev`, go to
`http://localhost:5420/configuration/deep-links/full`
3. Draw a shape → verify resize/rotate handles work (cursor changes on
hover, can drag)
4. Copy a deep link, move camera, paste the deep link URL
5. Verify handles still work after navigation
6. Verify `editor.getCameraState()` returns `'idle'` after navigation
completes

To reproduce the bug on `main`:
1. Set `ENABLE_STRICT_MODE = true` in `apps/examples/src/index.tsx`
2. Run `yarn dev`, go to
`http://localhost:5420/configuration/deep-links/full`
3. Draw a shape → resize/rotate handles will NOT work (cursor doesn't
change, can't drag)
4. `editor.getCameraState()` returns `'moving'` and never transitions to
`'idle'`

- [ ] Unit tests
- [ ] End to end tests

### Release notes

- Fixed camera state getting stuck at 'moving' when using deep links
with React strict mode, which blocked all pointer interactions on the
canvas.

### Code changes

| Section    | LOC change |
| ---------- | ---------- |
| Core code  | +6 / -0    |
@pull pull Bot locked and limited conversation to collaborators Apr 1, 2026
@pull pull Bot added the ⤵️ pull label Apr 1, 2026
@pull pull Bot merged commit 5c0db60 into code:main Apr 1, 2026
@pull pull Bot had a problem deploying to bemo-canary April 1, 2026 09:13 Failure
@pull pull Bot had a problem deploying to bemo-canary April 1, 2026 09:13 Failure
@pull pull Bot had a problem deploying to deploy-production April 1, 2026 09:13 Failure
@pull pull Bot had a problem deploying to vsce publish April 1, 2026 09:13 Failure
@pull pull Bot had a problem deploying to deploy-staging April 1, 2026 09:13 Error
@pull pull Bot had a problem deploying to deploy-staging April 1, 2026 09:13 Failure
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants