feat: enable copy to clipboard - #488
Merged
ilteoood merged 4 commits intoAug 19, 2026
Merged
Conversation
Issue fastify#487: docs pages had no copy buttons on their code blocks while the landing page already had them on npm install commands and the quick-start snippet. This extracts the duplicated copy logic into a shared CopyButton primitive and covers all <pre> blocks on docs pages via runtime DOM injection. Changes: - Add src/lib/copy.ts: copyText() with navigator.clipboard + execCommand fallback; shared wireCopyButton() helper. - Add src/components/CopyButton.astro: shared primitive with icon-swap and label-swap variants, lets the host specify a literal text or a selector resolved against data-copy-root. - Refactor InstallCommand and CodeTabs to use CopyButton; both preserve their prior visuals (icon-swap and label-swap respectively) and lose ~25 lines of inline script each. - Wire DOM injection in DocsShell.astro: wrap each <pre> in article.prose-fastify in a .docs-pre-wrap div and inject a copy button that reads textContent via the shared helper. Wrapper carries data-pagefind-ignore. Idempotent. - Add .docs-pre-wrap and .docs-copy-btn rules to prose.css so the injected buttons are positioned top-right and stay visible across horizontal pre scroll; works in both light and dark themes.
Single-line code blocks (curl examples, single npm commands, etc.) have the copy icon floated to the top-right corner where it sits above blank padding. Multi-line snippets still benefit from that position because there's lots of code below the button. Detect by counting <span class="line"> children (Shiki emits one per source line, falling back to textContent split by \n) and toggle an is-single-line class on the button that re-positions it to the pre's vertical center via top: 50% + translateY(-50%).
Removes the multi-line JSDoc-style blocks and tutorial comments added with the original implementation. Inline "why" notes for non-obvious decisions are kept (secure-context fallback, Shiki <span class="line"> fallback, pagefind-ignore rationale); block banners and prose explanations are dropped. Net: -37 lines of comments across src/lib/copy.ts, src/components/CopyButton.astro, src/components/DocsShell.astro, and src/styles/prose.css. No behavior change.
Puppo
marked this pull request as ready for review
August 19, 2026 17:00
ilteoood
reviewed
Aug 19, 2026
ilteoood
reviewed
Aug 19, 2026
Wrap documentation code blocks during Markdown processing, clone shared copy-button markup, and handle clipboard actions through one delegated listener. Use SVG assets for copy states and initialize the listener globally so documentation buttons remain functional.
Contributor
Author
|
@ilteoood I addressed your feedback and pushed the updated implementation. Could you please take another look when you have a chance? |
ilteoood
self-requested a review
August 19, 2026 18:48
ilteoood
approved these changes
Aug 19, 2026
ilteoood
enabled auto-merge (squash)
August 19, 2026 18:48
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.
Description
Adds copy-to-clipboard buttons on every code snippet in the docs (
/docs/...) by reusing the same logic as the existing buttons on the landing page (npm install fastifyand the QuickStart snippet).What changed
src/lib/copy.ts(new): sharedcopyText()(withnavigator.clipboard+document.execCommandfallback),wireCopyButton(), text-resolution + state-flash helpers.src/components/CopyButton.astro(new): shared primitive with two visual variants —icon-swap(copy ↔ check icons) andlabel-swap(icon + "Copy" → "Copied"). Hosts pass a literal text viatext, or a CSS selector viatextSelectorresolved against the nearest[data-copy-root].src/components/InstallCommand.astroandsrc/components/CodeTabs.astro: refactored to use the primitive. Visuals and behavior are unchanged.src/components/DocsShell.astro+src/styles/prose.css: runtime script wraps every<pre>in.docs-pre-wrapand injects a copy button using[data-copy-idle]/[data-copy-done](matching the existing icon-swap pattern, soflashCopyStateworks without further changes). Wrapper isdata-pagefind-ignore. Single-line snippets center the icon vertically alongside the code; multi-line snippets anchor it top-right.<pre>itself).execCommand('copy')via temporary off-screen textarea.Out of scope
fastify/fastify).InstallCommand,CodeTabs) keep their existing visuals.Verification
npm run lintclean (Biome).npm run check: same 17 pre-existing baseline errors (missing git-ignored data files) + 1 new intentional-deprecation hint forexecCommandlegacy fallback. CI only gates on lint.npm run build:websitesucceeds; static HTML on the landing page carries the newdata-copy-root/data-copy-btnhooks; docs HTML still has plain<pre>blocks for the runtime script to enhance.Related Issues
Closes #487
Check List