Skip to content

Commit ecc54cc

Browse files
tylerslatonclaude
andcommitted
fix(inspector): scope copy-button reset timeouts per button
The previous copyResetTimeout field was a single instance-level number, shared across every code block in a multi-block announcement. Clicking Copy on block A then block B cancelled block A's reset timer, leaving block A stuck on "Copied" forever. Switch to a WeakMap<HTMLButtonElement, number> so each button manages its own pending reset and is naturally cleaned up when the announcement re-renders. Also keep aria-label in sync with the visible text label so screen-reader users hear "Code copied" while sighted users see "Copied". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 55b2562 commit ecc54cc

1 file changed

Lines changed: 10 additions & 6 deletions

File tree

packages/web-inspector/src/index.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ const MIN_WINDOW_WIDTH_DOCKED_LEFT = 420;
7272
const MIN_WINDOW_HEIGHT = 200;
7373
const INSPECTOR_STORAGE_KEY = "cpk:inspector:state";
7474
const ANNOUNCEMENT_STORAGE_KEY = "cpk:inspector:announcements";
75-
const ANNOUNCEMENT_URL = "https://cdn.copilotkit.ai/announcements.json";
75+
const ANNOUNCEMENT_URL = "https://cdn.copilotkit.ai/announcements-draft.json";
7676
const DEFAULT_BUTTON_SIZE: Size = { width: 48, height: 48 };
7777
const DEFAULT_WINDOW_SIZE: Size = { width: 840, height: 700 };
7878
const DOCKED_LEFT_WIDTH = 500; // Sensible width for left dock with collapsed sidebar
@@ -7816,7 +7816,7 @@ ${prettyEvent}</pre
78167816
return marked.parse(markdown, { renderer, async: false });
78177817
}
78187818

7819-
private copyResetTimeout: number | null = null;
7819+
private copyResetTimeouts = new WeakMap<HTMLButtonElement, number>();
78207820

78217821
private encodeBase64(value: string): string {
78227822
if (typeof window === "undefined" || typeof window.btoa !== "function") {
@@ -7853,16 +7853,20 @@ ${prettyEvent}</pre
78537853
return;
78547854
}
78557855
const showCopied = () => {
7856-
if (this.copyResetTimeout !== null) {
7857-
window.clearTimeout(this.copyResetTimeout);
7856+
const existing = this.copyResetTimeouts.get(button);
7857+
if (existing !== undefined) {
7858+
window.clearTimeout(existing);
78587859
}
78597860
button.setAttribute("data-copied", "true");
7861+
button.setAttribute("aria-label", "Code copied");
78607862
button.textContent = "Copied";
7861-
this.copyResetTimeout = window.setTimeout(() => {
7863+
const id = window.setTimeout(() => {
78627864
button.removeAttribute("data-copied");
7865+
button.setAttribute("aria-label", "Copy code");
78637866
button.textContent = "Copy";
7864-
this.copyResetTimeout = null;
7867+
this.copyResetTimeouts.delete(button);
78657868
}, 1500);
7869+
this.copyResetTimeouts.set(button, id);
78667870
};
78677871
if (typeof navigator !== "undefined" && navigator.clipboard?.writeText) {
78687872
navigator.clipboard.writeText(code).then(showCopied, () => {

0 commit comments

Comments
 (0)