Skip to content

[pull] main from tldraw:main#600

Merged
pull[bot] merged 6 commits into
code:mainfrom
tldraw:main
Jun 17, 2026
Merged

[pull] main from tldraw:main#600
pull[bot] merged 6 commits into
code:mainfrom
tldraw:main

Conversation

@pull

@pull pull Bot commented Jun 17, 2026

Copy link
Copy Markdown

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 6 commits June 17, 2026 10:02
In order to keep workspace dialogs open while their nested controls are
in use and to tidy up the new sidebar, this PR generalizes dialog
dismissal and reorganizes the sidebar actions. Portalled controls can
now opt out of dismissing a dialog by adding a
`data-tlui-dialog-prevent-dismiss` attribute, so interacting with a
`TlaMenuSelect` popup inside the workspace settings dialog no longer
registers as a background click and closes it — replacing the previous
all-or-nothing `preventBackgroundClose` workaround.
`TlaSidebarWorkspaceActions` is extracted into its own component and
rendered directly from `TlaSidebar`, the user settings menu opens on
right-click, and clearing the sidebar search blurs the input instead of
refocusing it.

### Change type

- [x] `improvement`

### Test plan

1. Open a workspace's settings dialog from the sidebar.
2. Open one of the role/permission selects and pick an option — the
dialog should stay open.
3. Click the dialog overlay — the dialog should close.
4. Right-click the user settings row in the sidebar — the user settings
menu should open.
5. Type in the sidebar search, then click the clear (X) button — the
input should clear and lose focus.

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

### Code changes

| Section        | LOC change  |
| -------------- | ----------- |
| Core code      | +18 / -1    |
| Tests          | +27 / -12   |
| Apps           | +197 / -177 |

### Release notes

- Keep tldraw.com workspace dialogs open when interacting with nested
select menus.
- Open the sidebar user settings menu on right-click.
In order to make switching files feel instant while keeping the editor
chrome stable, this PR shows an inert editor placeholder as soon as a
file opens, instead of showing a spinner on a blank screen. Previously
the real editor only mounted once the sync connection completed, so
clicking a sidebar file could show nothing but a spinner until the
document loaded.

Now `ReadyWrapper` accepts an optional `loadingScreen`, and `TlaEditor`
passes a `TlaEditorLoadingPlaceholder`: a visual-only `<Tldraw>`
rendering the editor chrome (toolbar, menus, panels) over its own empty
local store. The placeholder never autofocuses, and both the placeholder
and not-yet-ready real editor are marked inert while loading, so they
cannot receive focus or input. It matches the user's theme to avoid a
light/dark flash. Once the real store reaches `synced-remote`, the
placeholder unmounts and the real editor remains visible, with
file-specific canvas content (shapes, overlays, and front-of-canvas
content) fading in. The placeholder path is the only one that uses this
content-only transition; the legacy and anon editor flows keep their
existing fade-in.

### Change type

- [x] `improvement`

### Test plan

1. Sign in to tldraw.com and open a file from the sidebar.
2. Throttle the network in DevTools to lengthen the loading window.
3. Click between files and confirm an empty editor with chrome appears
immediately, remains non-interactive while loading, and the document
content fades in once connected.
4. Run `yarn workspace dotcom lint`.
5. Run `yarn typecheck`.

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

### Release notes

- Show an editor placeholder immediately when opening a file on
tldraw.com, so the canvas appears instantly and the document content
fades in once it connects.

### Code changes

| Section | LOC change |
| ------- | ---------- |
| Apps    | +93 / -5   |
In order to simplify the dotcom sidebar and fix a few rough edges, this
PR bundles several small fixes.

- **Native link dragging for files.** Dragging a file in the sidebar now
just drags its URL, like dragging a link, so you can drop it into a new
tab or another app. The old drag-to-reorder and drag-to-(un)pin tracking
system is removed — pinning and unpinning now happen through the file
menu. This deletes the `useDragTracking`/`useIsDragging` hooks, the
`ReorderCursor` overlay, the sidebar `dragState`, and the
`handleFileDragOperation` reorder mutator.
- **Truncate sidebar labels.** Workspace switcher items, the "New
workspace" buttons, and the sidebar action rows now ellipsis-truncate
their labels instead of wrapping onto multiple lines. The ellipsis
styles previously lived on a flex container, where `text-overflow` has
no effect; the text is now wrapped in its own truncating span.
- **Cap the "Move to" submenu width.** The file menu's "Move to" submenu
lists workspace names, which can be long. It's now capped at 260px so
long names truncate instead of stretching the menu across the screen.
- **Reject empty workspace names.** The `createWorkspace` mutator now
rejects an empty or whitespace-only name (matching `updateWorkspace`),
closing a gap where a blank workspace name was technically allowed
server-side.
- **Cap workspace names at 100 characters.** Enforced in the
`createWorkspace`/`updateWorkspace` mutators and surfaced in the create
and rename inputs via a new `maxLength` prop on `TldrawUiInput`.
- **Tidy dropdown alignment and spacing.** The file menu and user
settings menu dropdowns are realigned to their triggers, and the
workspace switcher menu now keeps a minimum 260px width so its contents
don't get cramped.
- **Center the Clerk CAPTCHA challenge.** When Clerk injects a visible
CAPTCHA challenge into `#clerk-captcha`, it's now centered over the app
at the blocker layer with panel styling, instead of rendering inline
wherever the empty mount point happens to sit.

### Change type

- [x] `improvement`

### Test plan

1. With a long workspace name, open the workspace switcher and confirm
the name truncates with an ellipsis instead of wrapping.
2. In a narrow sidebar, confirm the "New workspace" button and the
search/new file/settings rows truncate.
3. Open a file's menu and hover "Move to" with a long-named workspace;
confirm the submenu stays at 260px wide and the name truncates.
4. Drag a file from the sidebar into a new browser tab and confirm it
opens the file; confirm dragging a pinned file no longer unpins it.
5. Try entering a workspace name longer than 100 characters in the
create and rename inputs and confirm it stops at 100.
6. Open the file menu and user settings menu and confirm each dropdown
aligns to its trigger.
7. Trigger a visible Clerk CAPTCHA challenge and confirm it appears
centered over the app.

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

### API changes

- Added `maxLength` prop to `TldrawUiInput` (`TLUiInputProps`).

### Release notes

- Sidebar: dragging a file now drags its URL (like a link) instead of
reordering; pin and unpin from the file menu.
- Sidebar: workspace names and action button labels truncate with an
ellipsis instead of wrapping.
- The file menu's "Move to" submenu no longer stretches for long
workspace names.
- Limit workspace names to 100 characters.
- Reject empty workspace names when creating a workspace.
- Center the Clerk CAPTCHA challenge over the app when one appears.
In order to stop a file name from jumping ~1px vertically when you start
renaming it in the sidebar, this PR sizes the inline rename input by its
line box instead of giving it an explicit 36px height.

The input had `height: 36px`, so the underlying `.tlui-input` flex box
centered its text internally, which rounds ~1px lower than the file
label (which sizes by its line box). The result was a small downward
shift when entering rename mode. Now the input sizes to its content and
the surrounding 36px wrapper centers it via `align-items: center`,
exactly how the label is centered in its row. This is the same fix
previously applied to the sidebar search field in #9243.

### Change type

- [x] `bugfix`

### Test plan

1. Open tldraw.com and look at the file list in the sidebar.
2. Double-click a file (or use the file menu → Rename) to enter rename
mode.
3. Confirm the file name does not shift up or down when the input
appears, and does not shift back when you commit or cancel.

### Release notes

- Fix a 1px vertical shift of the file name when renaming a file in the
sidebar.
In order to give workspace owners a clearer place to manage their
workspace, this PR reworks the "Workspace settings" dialog into a tabbed
"Manage workspace" dialog and adds an enable/disable toggle for the
invite link. Follow-up to #9106; closes #9131.

The dialog now has a shared header (name + invite link) above two tabs:

- **Members** — each member shows a role dropdown; owners can change
roles or remove members. Your own row's action is **Leave**; it (and
removing the last owner) is disabled with a tooltip when it would leave
the workspace without an owner.
- **Settings** (owners only) — enable/disable the invite link,
regenerate it, leave, or delete the workspace.

Other changes:

- **Capabilities** — the per-action capabilities (`manageInvites`,
`editMembers`, `editWorkspace`, `deleteWorkspace`) are consolidated into
a single owner-only `manageWorkspace`. Members can no longer manage the
invite link, roles, name, or deletion.
- **Invite link toggle** — like file sharing, turning the link off
*keeps* it (so it can be turned back on) rather than clearing it. Backed
by a `group.inviteLinkEnabled` column (migration 035), a mutator, and
gating on the invite-accept path; the user durable-object state version
is bumped so clients refetch.
- **SDK dialog fix** — `TldrawUiDialog` now closes on a backdrop click
only when the press both starts and ends on the overlay, and no longer
auto-dismisses when a portaled popover opened inside it (e.g. a Select)
is used. Without this, opening/dismissing the role dropdown tore down
the whole dialog.



https://github.com/user-attachments/assets/a9571f8d-546f-42b6-add7-eee1cfdca956



### Change type

- [x] `feature`

### Test plan

1. As an **owner**, open Manage workspace → **Members**: every member
has a role dropdown; your own row's dropdown has "Leave" (disabled with
a tooltip if you're the only owner), other members have "Remove".
2. **Settings** tab: toggle "Enable invite link" off → the copy button
becomes a disabled "Invites are disabled"; toggle on → the same link
returns. Regenerate / Leave / Delete each open a confirm dialog
(descriptive title, short action button).
3. As a **member**: roles are read-only, your own row offers "Leave",
and there's no settings management.
4. Open a role dropdown, then click elsewhere in the dialog or on the
backdrop: the dropdown closes; the dialog only closes on a deliberate
backdrop click (and Escape).

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

### Release notes

- Fix a dialog unexpectedly closing when a popover (e.g. a select)
opened inside it is dismissed.

### Code changes

| Section         | LOC change  |
| --------------- | ----------- |
| Core code       | +64 / -39   |
| Tests           | +90 / -15   |
| Automated files | +102 / -75  |
| Apps            | +373 / -302 |
@pull pull Bot locked and limited conversation to collaborators Jun 17, 2026
@pull pull Bot added the ⤵️ pull label Jun 17, 2026
@pull
pull Bot merged commit abfa9f5 into code:main Jun 17, 2026
@pull
pull Bot had a problem deploying to bemo-canary June 17, 2026 15:13 Failure
@pull
pull Bot had a problem deploying to deploy-staging June 17, 2026 15:13 Error
@pull
pull Bot had a problem deploying to deploy-staging June 17, 2026 15:13 Error
@pull
pull Bot had a problem deploying to deploy-production June 17, 2026 15: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