Skip to content

Copy a code block without selecting it - #53

Merged
cevheri merged 2 commits into
mainfrom
seo/og-images-and-code-copy
Sep 20, 2026
Merged

cevheri merged 2 commits into
mainfrom
seo/og-images-and-code-copy

Conversation

@mfatihdayan

Copy link
Copy Markdown
Collaborator

Stacked on #52 — the base is that branch, so the diff here is one commit.

87 of the 104 posts carry code, and the point of publishing a connection string or a compose fragment is that someone runs it. Selecting a multi-line block by hand was the one part of that the page controlled and was not helping with.

The button is injected at runtime, not rendered into the markup. The alternative is a data-copy attribute holding a second copy of every block, which would roughly double the weight of a code-heavy page to save a few lines of script. Reading textContent at click time also guarantees the copied text is the code on screen. With JavaScript off the blocks render exactly as before — this adds an affordance, it does not carry content.

The clipboard write and its execCommand fallback moved to src/scripts/clipboard.ts, shared with the existing [data-copy] buttons, so the two cannot drift on the part that is easy to get subtly wrong off https.

Hidden until hover for a mouse; always visible under @media (hover: none) and on :focus-visible. An affordance that only appears on hover does not exist on a phone or to a keyboard.

Verified in a browser rather than asserted: all five blocks on /blog/postgresql-connect-docker-container/ get a button, positioned inside the <pre>, idle at opacity: 0, and on click the label becomes "copied" with the brand colour applied.

Two items from the same list I did not do, and why

Per-page OG images. The tooling exists (scripts/og/build-og.mjs renders the card in real Chrome). But public/og/default.png is 102 KB, so 104 post cards is about 10.4 MB committed — against a .git that is currently 3.8 MB. Quadrupling the repository, permanently, to improve share cards is the wrong trade. If the cards are wanted, generating them in CI before the build — so they reach dist/ without ever entering history — is the version worth doing, and that is a separate decision about adding Chrome to the deploy job.

Hero image as AVIF. 149 KB JPEG, and AVIF would save roughly 110 KB. But LCP is already 1,189 ms against a 2,500 ms threshold, there is no image pipeline in this repo to hang an encoder on, and re-compressing the JPEG locally gained 16 KB at visible quality cost. Adding a build dependency for one image that is not a problem is not worth it.

@cevheri
cevheri changed the base branch from seo/one-url-per-page-and-engine-archives to main September 20, 2026 15:58
mfatihdayan and others added 2 commits September 20, 2026 18:59
87 of the 104 posts carry code — connection strings, compose fragments,
SQL — and the point of publishing them is that someone runs them.
Selecting a multi-line block by hand was the one part of that the page
controlled and was not helping with.

The button is injected at runtime rather than rendered into the markup.
The alternative is a `data-copy` attribute holding a second copy of
every block, which would roughly double the weight of a code-heavy page
to save a few lines of script; reading `textContent` at click time also
guarantees the text is the code the reader is looking at. With
JavaScript off the blocks render exactly as before.

The clipboard write and its execCommand fallback moved to
scripts/clipboard.ts so the two callers cannot drift on the part that is
easy to get subtly wrong off https.

Hidden until hover for the mouse, and always visible where there is no
hover — an affordance that only appears on hover does not exist on a
phone.
Two defects in the button, both found by driving the built page rather than
reading it.

--radius-sm is not in the vocabulary — the scale is xs/s/m/l/xl/2xl — so the
declaration was invalid at computed-value time and the button rendered with
square corners. It is a small control, which the design system sizes at
--radius-s (6px).

The button sits inside the <pre>, so its label was part of the block's
selectable text: selecting the block by hand returned 'docker run ... postgres:18copy'.
That is the exact workflow the button was added to improve, and it broke it for
anyone who kept doing it the old way. user-select: none takes the label back
out. What the button itself copies was never affected — the source is read
before the button is appended — so only the manual path regressed.

Measured on dist: button radius 6px, prev/next card 12px, hand selection ends
at 'postgres:18', clipboard matches it. The test asserts the rule from the
emitted stylesheet and fails without the fix.
@cevheri
cevheri force-pushed the seo/og-images-and-code-copy branch from fa0d56d to 82c9ce5 Compare September 20, 2026 15:59
@cevheri
cevheri merged commit cf171c5 into main Sep 20, 2026
5 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.

2 participants