Skip to content

Conversation

@jamiehenson
Copy link
Member

@jamiehenson jamiehenson commented Dec 12, 2025

"Copy as markdown" uses the modern navigator API to copy contents to the clipboard. This works poorly with asynchronous operations (i.e. in this case where we fetched markdown content and then copied it to clipboard) as it breaks the terms of what is considered a user interaction - and Safari is the most strict on this.

The solution here is suboptimal, but save for programatically creating a text area and then having the user click it (a previous approach), this PR makes the operation synchronous by fetching the markdown copy on load and then copying it to the clipboard without async. Naturally this is wasteful if only 1% of people click the markdown copy button, but the payload is very small and it allows for a smoother copy experience. If this is unsatisfactory my suggestion would be to drop the copy and just have the view link.

Tests have been added for PageHeader to represent this.

Also includes a very quick fix for the LeftSidebar overflow property (was getting horizontal scrolls on the bar)

To test: go here in Chrome and Safari and copying should work gracefully as elsewhere.

@coderabbitai
Copy link

coderabbitai bot commented Dec 12, 2025

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fallback-copy

Comment @coderabbitai help to get the list of available commands and usage tips.

@jamiehenson jamiehenson added the review-app Create a Heroku review app label Dec 12, 2025
@ably-ci ably-ci temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 12, 2025 16:17 Inactive
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 12, 2025 16:34 Inactive
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 12, 2025 16:43 Inactive
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 13:40 Inactive
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 14:14 Inactive
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 14:17 Inactive
@jamiehenson jamiehenson changed the title fix: fallback to older copy method for Safari markdown copying fix: prefetch page Markdown content for better cross-browser support Dec 15, 2025
@jamiehenson jamiehenson force-pushed the fallback-copy branch 2 times, most recently from 95c5d63 to 683b3e2 Compare December 15, 2025 16:02
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 16:02 Inactive
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 16:05 Inactive
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 16:12 Inactive
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 16:13 Inactive
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 16:27 Inactive
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 16:38 Inactive
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 16:46 Inactive
@jamiehenson jamiehenson changed the title fix: prefetch page Markdown content for better cross-browser support [FTF-431] fix: prefetch page Markdown content for better cross-browser support Dec 15, 2025
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 17:09 Inactive
try {
const response = await fetch(`${location.pathname}.md`);
useEffect(() => {
const abortController = new AbortController();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets us abort the fetch if dismounted, was playing with the tests a bit (and is a positive step)

</Tooltip.Portal>
</Tooltip.Root>
</div>
{markdownContent && (
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've made the choice to conditionally hide the markdown buttons if there's no content, since we now grab it ahead-of-time

@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 17:41 Inactive
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 17:46 Inactive
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 17:49 Inactive
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 17:54 Inactive
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 17:56 Inactive
@jamiehenson jamiehenson temporarily deployed to ably-docs-fallback-copy-zfp4r0 December 15, 2025 18:00 Inactive
@jamiehenson
Copy link
Member Author

@kennethkalmer Taken another swing at this (PR updated and puffed out a bit with tests), was an interesting problem. Sorry for the delay on it, the tests were a nightmare.

The main difference is that using navigator.clipboard.writeText() is fine in Safari, but only synchronously, which is why it works for api key selectors and the like where the data is already there to copy. My latest approach is to fetch the markdown content on load, which is more wasteful, but allows it to be done sync not async.

Given the tiny payload it seems like a lesser evil (and also allows a runtime check to see if we should render the markdown buttons at all).

Ready for a look at a point of convenience.

Copy link
Member

@kennethkalmer kennethkalmer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jamiehenson thanks, this is a good compromise for the moment and a fantastic learning! I think in the new year we could enhance it with a bit of "feature detection" and then only prefetch the markdown if async clipboard writing is not supported. But for now this creates equal access for everyone, thank you!

@jamiehenson jamiehenson merged commit ac832db into main Dec 16, 2025
7 checks passed
@jamiehenson jamiehenson deleted the fallback-copy branch December 16, 2025 09:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-app Create a Heroku review app

Development

Successfully merging this pull request may close these issues.

4 participants