[pull] main from tldraw:main#600
Merged
Merged
Conversation
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 : )