Skip to content

chore(content): keep home copy button working after client-side navigation - #1975

Merged
dinwwwh merged 1 commit into
middleapi:mainfrom
BeLazy167:fix/home-copy-button-soft-nav
Sep 2, 2026
Merged

chore(content): keep home copy button working after client-side navigation#1975
dinwwwh merged 1 commit into
middleapi:mainfrom
BeLazy167:fix/home-copy-button-soft-nav

Conversation

@BeLazy167

@BeLazy167 BeLazy167 commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

What happens

The install command copy button on the home page does nothing if you reach the home page through a link inside the site. Open any docs page, click the logo to come back, click the button. Nothing is copied and the icon never flips to the check. Reload the page and it works again.

Why

Hero.astro binds a click listener to each [data-copy] button from a hoisted script. Astro runs that script once per real page load. The site uses ClientRouter, so going from docs back to home does not reload. It fetches the new HTML and swaps the body in place. The button in that new body is a fresh element. The script that bound the old listener already ran and does not run again, so the new button has no listener.

The change

The listener now sits on document instead of on each button. document survives the swap. When a click lands, the handler walks up from the target with closest('button[data-copy]') and looks up [data-copy-status] at that moment, so it always sees the current elements. The per-button reset timer moved into a WeakMap keyed by button. That keeps the double-click guard and lets swapped-out buttons be garbage collected. The copied state, the aria-live announcement, the failure text and the 1.6s reset are unchanged.

How I checked

On orpc.dev I hooked navigator.clipboard.writeText, soft navigated from /docs/getting-started back to / and clicked. No write, no is-copied. With this branch in blume dev the same steps write npx skills add middleapi/orpc and the status reads "Copied", both on first load and after the soft navigation.

The Showcase tabs and the blog filter bind listeners the same way and probably have the same problem. I left them out to keep this small.

…ation

The install copy button bound a click listener per button from a hoisted
script, which Astro runs once per full load. With ClientRouter, entering the
home page from another page swaps the DOM and the new button has no listener,
so clicking it does nothing. Delegate a single click listener on the document
and resolve the button and status node at click time.

Claude-Session: https://claude.ai/code/session_01GWZkDPigd3w6kov2DsnSrV

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

  • Rewrote the Hero.astro install-copy script from per-button listeners bound at module init to a single delegated click listener on document, resolving the button via closest('button[data-copy]') and the status node via querySelector at click time; reset timers moved into a per-button WeakMap.
  • Verified the fix's premise against the installed Astro 7.2.8 ClientRouter (dist/transitions/router.js runScripts() + data-astro-exec tracking) and Blume's own client-router documentation (blume/src/components/layout/head-scripts.ts): page scripts execute once per real page load, module execution is deduped by URL via the browser module map, so the delegated listener binds exactly once per document — no accumulation on repeated soft navigations, and it survives the swap because document persists across swaps while the old per-button bindings were wiped with the body. Resolving both nodes at click time also sidesteps the stale-node trap the old module-init capture would have had after a swap.
  • Behavior is otherwise preserved line-for-line: is-copied, aria-live status announctet (success + failure), and the 1.6s reset (comment, logic, and the double-click window clear are all carried over), and the instanceof Element guard matches the existing delegated-listener idiom in components/blume/NavTree.astro:397.

The chore(content) scope follows the repo's commit convention (docs-site-internal change, chore type). Noted that the Showcase tabs and blog filter scripts share the same soft-nav pattern — properly left for a follow-up to keep this PR scoped.

Pullfrog  | View workflow run | Using DeepSeek Flash (free via Pullfrog for OSS) | 𝕏

@pkg-pr-new

pkg-pr-new Bot commented Sep 2, 2026

Copy link
Copy Markdown
More templates

@orpc/ai-sdk

npm i https://pkg.pr.new/@orpc/ai-sdk@1975

@orpc/arktype

npm i https://pkg.pr.new/@orpc/arktype@1975

@orpc/bun

npm i https://pkg.pr.new/@orpc/bun@1975

@orpc/client

npm i https://pkg.pr.new/@orpc/client@1975

@orpc/cloudflare

npm i https://pkg.pr.new/@orpc/cloudflare@1975

@orpc/contract

npm i https://pkg.pr.new/@orpc/contract@1975

@orpc/experimental-effect

npm i https://pkg.pr.new/@orpc/experimental-effect@1975

@orpc/evlog

npm i https://pkg.pr.new/@orpc/evlog@1975

@orpc/hibernation

npm i https://pkg.pr.new/@orpc/hibernation@1975

@orpc/json-schema

npm i https://pkg.pr.new/@orpc/json-schema@1975

@orpc/experimental-msw

npm i https://pkg.pr.new/@orpc/experimental-msw@1975

@orpc/nest

npm i https://pkg.pr.new/@orpc/nest@1975

@orpc/next

npm i https://pkg.pr.new/@orpc/next@1975

@orpc/node

npm i https://pkg.pr.new/@orpc/node@1975

@orpc/openapi

npm i https://pkg.pr.new/@orpc/openapi@1975

@orpc/opentelemetry

npm i https://pkg.pr.new/@orpc/opentelemetry@1975

@orpc/pinia-colada

npm i https://pkg.pr.new/@orpc/pinia-colada@1975

@orpc/pino

npm i https://pkg.pr.new/@orpc/pino@1975

@orpc/publisher

npm i https://pkg.pr.new/@orpc/publisher@1975

@orpc/ratelimit

npm i https://pkg.pr.new/@orpc/ratelimit@1975

@orpc/server

npm i https://pkg.pr.new/@orpc/server@1975

@orpc/shared

npm i https://pkg.pr.new/@orpc/shared@1975

@orpc/swr

npm i https://pkg.pr.new/@orpc/swr@1975

@orpc/tanstack-query

npm i https://pkg.pr.new/@orpc/tanstack-query@1975

@orpc/trpc

npm i https://pkg.pr.new/@orpc/trpc@1975

@orpc/valibot

npm i https://pkg.pr.new/@orpc/valibot@1975

@orpc/zod

npm i https://pkg.pr.new/@orpc/zod@1975

commit: ea9d62d

@codecov

codecov Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@dinwwwh
dinwwwh merged commit 617ac7a into middleapi:main Sep 2, 2026
10 checks passed
@codspeed-hq

codspeed-hq Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 30 untouched benchmarks


Comparing BeLazy167:fix/home-copy-button-soft-nav (ea9d62d) with main (d21ca76)

Open in CodSpeed

dinwwwh added a commit that referenced this pull request Sep 2, 2026
… client-side navigation (#1976)

The code example tabs on the home page stopped responding after
navigating to another page and coming back through the header logo. The
blog index tag filter had the same problem. Both scripts bound their
listeners once per full page load, but Astro's ClientRouter replaces the
page body on every soft navigation, so the fresh markup came back
without any handlers. Each script now re-resolves its elements in an
`init` that runs at load and again on `astro:after-swap`, matching how
Blume's own components handle re-entry.

## Fixes

- Home showcase: tab clicks, ArrowLeft/ArrowRight/Home/End, the overflow
fade hints, and the wheel-to-horizontal scroll all work after
re-entering the home page.
- Blog index: tag filter buttons work after re-entering `/blog`.
- A single ResizeObserver re-targets the current tab strip after each
swap instead of leaving a new observer per visit.

## Testing

- Dev server, all soft navigations (confirmed by a window global
surviving every hop): home → docs → home, home → blog → home → blog, and
a second round trip.
- Tab click, ArrowRight, ArrowLeft, and End switch the selected tab and
panel after re-entry; blog tags filter the cards after re-entry; the
copy button from #1975 still fires.
- No server errors, no new console errors.
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