Repository navigation
Conversation
The controller is created in an effect, after the first render, and was only kept in a ref. The returned `controller` was therefore always null on the first render and never updated, so components couldn't render anything that needs it. Mirror it in state: components re-render once it exists, and again when it's disposed or recreated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`<ContentLink toggle />` shows a floating toolbar that tells editors whether click-to-edit is on, and lets them turn it on and off, highlight editable elements and, with `exitDraftModeUrl`, exit draft mode. - Remembers the editor's choice, collapsed state and position (localStorage). With the toolbar, `enableClickToEdit` is only the starting state. - Reflects the temporary Alt/Option state, through the `datocms:click-to-edit:toggle` event the controller already dispatches. - Draggable, kept inside the viewport; arrow keys / Home on the grip. - Rendered in a Shadow DOM through a portal, in the overlays' color (`hue`). Nothing inside iframes, where Web Previews has its own toggle. `VisualEditingToggle` is exported for `useContentLink` users. The portal makes `react-dom` a peer dependency; the toolbar needs React 17+. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On Node 16/18, jsdom's window.parent doesn't return window anymore after restoring its original descriptor, so every later test thought it was inside an iframe. Check the iframe through a helper and mock that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit: |
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What
A floating toolbar, shown only where
<ContentLink />is rendered (i.e. in draft mode), that tells editors whether click-to-edit is on and lets them change it:flashAll(true).exitDraftModeUrl, only when it's passed.localStorage. With the toolbar,enableClickToEdit(includinghoverOnlyandscrollToNearestTarget) is only the starting state for editors who haven't chosen yet.hue).role="switch"+aria-checked,aria-expandedon collapse, changes (including the temporary state) announced through a polite live region.VisualEditingToggleis also exported, foruseContentLinkusers:Things to review
useContentLinknow re-renders once the controller exists (separate commit). It was only in a ref, so the returnedcontrollerwas alwaysnullon the first render and never updated. Needed by the toolbar; also makes the documentedcontrollerreturn value usable.react-domis now a peer dependency (>= 16.12.0), forcreatePortal. Only the rootpeerDependenciesentry changed inpackage-lock.json.document, where events from inside a Shadow DOM are retargeted to the host, so clicks wouldn't reach the handlers. Documented; the package still supports React 16 otherwise.ContentLink's return type is nowReactElement | null(wasnull).datocms:click-to-edit:toggleevent that@datocms/content-linkdispatches ondocument, which isn't documented or exported there. The overlay color is a copy of the library'sbuildOverlayColors, which isn't exported either. Both would be better as public API in content-link.ContentLink, even withouttoggle(~6KB gzipped before minification). AReact.lazysplit is possible if that matters.Related: datocms/content-link#5 moves the "Open in DatoCMS" label inside the overlay box (visible in the screenshots once released).
Testing
npm test: 73 passed, 19 new (src/ContentLink/__tests__/): default and saved state,defaultEnabled,hoverOnly, switch + persistence + announcements, Alt temporary state vs. app-driven changes, flash, collapse persistence, exit link, keyboard moves + Home, clamping an off-screen saved position, iframe, unmount;ContentLinkwith and withouttoggle.npm run build,tsc,biome checkon the changed files: pass.@datocms/content-link0.3.23: real clicks on the switch, drag, position restored after reload, double-click reset, collapse restored after reload, Exit preview navigation, Alt (synthetic key events) with the real controller, page CSS (button { … !important }) not leaking in.Screenshots
toolbar:

compressed:

with Alt held:

🤖 Generated with Claude Code