Skip to content

feat: enable copy to clipboard - #488

Merged
ilteoood merged 4 commits into
fastify:mainfrom
Puppo:fix-487-getting-started-copy-buttons
Aug 19, 2026
Merged

feat: enable copy to clipboard#488
ilteoood merged 4 commits into
fastify:mainfrom
Puppo:fix-487-getting-started-copy-buttons

Conversation

@Puppo

@Puppo Puppo commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

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 fastify and the QuickStart snippet).

What changed

  • src/lib/copy.ts (new): shared copyText() (with navigator.clipboard + document.execCommand fallback), wireCopyButton(), text-resolution + state-flash helpers.
  • src/components/CopyButton.astro (new): shared primitive with two visual variants — icon-swap (copy ↔ check icons) and label-swap (icon + "Copy" → "Copied"). Hosts pass a literal text via text, or a CSS selector via textSelector resolved against the nearest [data-copy-root].
  • src/components/InstallCommand.astro and src/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-wrap and injects a copy button using [data-copy-idle] / [data-copy-done] (matching the existing icon-swap pattern, so flashCopyState works without further changes). Wrapper is data-pagefind-ignore. Single-line snippets center the icon vertically alongside the code; multi-line snippets anchor it top-right.
  • Buttons are kept visible across horizontal scroll (the wrap is the positioning context, not the <pre> itself).
  • Plain HTTP / older browsers fall back to execCommand('copy') via temporary off-screen textarea.

Out of scope

  • No changes to the upstream MDX sources (fetched at build time from fastify/fastify).
  • No new runtime dependencies.
  • The two landing-page copy buttons (InstallCommand, CodeTabs) keep their existing visuals.

Verification

  • npm run lint clean (Biome).
  • npm run check: same 17 pre-existing baseline errors (missing git-ignored data files) + 1 new intentional-deprecation hint for execCommand legacy fallback. CI only gates on lint.
  • npm run build:website succeeds; static HTML on the landing page carries the new data-copy-root / data-copy-btn hooks; docs HTML still has plain <pre> blocks for the runtime script to enhance.

Related Issues

Closes #487

Check List

  • I have read the Contributing Guidelines

Puppo added 2 commits August 19, 2026 15:26
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
Puppo marked this pull request as ready for review August 19, 2026 17:00
Comment thread src/components/DocsShell.astro Outdated
Comment thread src/components/DocsShell.astro Outdated
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.
@Puppo
Puppo deployed to sandbox August 19, 2026 18:25 — with GitHub Actions Active
@Puppo

Puppo commented Aug 19, 2026

Copy link
Copy Markdown
Contributor Author

@ilteoood I addressed your feedback and pushed the updated implementation. Could you please take another look when you have a chance?

@ilteoood
ilteoood enabled auto-merge (squash) August 19, 2026 18:48
@ilteoood
ilteoood merged commit 4792b1d into fastify:main Aug 19, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: enable copy to clipboard

2 participants