Skip to content

Commit 5f3fab2

Browse files
feat(scratchpad): add copy to clipboard button
- Added a "Copy" button to the scratchpad UI - Implemented copy logic with visual feedback ("Copied!" state) - Added proper ARIA labels for accessibility - Used standard VS Code theme colors for consistent styling
1 parent e7ea972 commit 5f3fab2

1 file changed

Lines changed: 54 additions & 0 deletions

File tree

src/features/scratchpad/scratchpad.html

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,30 @@
8383
.btn-clear.confirm:hover {
8484
background-color: var(--vscode-button-destructiveHoverBackground);
8585
}
86+
.btn-copy {
87+
background: none;
88+
border: none;
89+
cursor: pointer;
90+
color: var(--vscode-button-foreground);
91+
background-color: var(--vscode-button-secondaryBackground);
92+
padding: 2px 6px;
93+
border-radius: 2px;
94+
font-size: 11px;
95+
display: flex;
96+
align-items: center;
97+
gap: 4px;
98+
}
99+
.btn-copy:hover {
100+
background-color: var(--vscode-button-secondaryHoverBackground);
101+
}
102+
.btn-copy:focus {
103+
outline: 1px solid var(--vscode-focusBorder);
104+
outline-offset: 1px;
105+
}
106+
.btn-copy.success {
107+
background-color: var(--vscode-charts-green);
108+
color: white;
109+
}
86110
</style>
87111
</head>
88112
<body>
@@ -95,6 +119,9 @@
95119
<div class="footer">
96120
<span id="char-count" class="char-count" aria-live="polite">0 chars</span>
97121
<div class="actions">
122+
<button id="btn-copy" class="btn-copy" aria-label="Copy to Clipboard" title="Copy content">
123+
Copy
124+
</button>
98125
<button id="btn-clear" class="btn-clear" aria-label="Clear Scratchpad" title="Clear all content">
99126
Clear
100127
</button>
@@ -105,6 +132,7 @@
105132
const textarea = document.getElementById('scratchpad');
106133
const charCount = document.getElementById('char-count');
107134
const btnClear = document.getElementById('btn-clear');
135+
const btnCopy = document.getElementById('btn-copy');
108136
let clearTimeoutId;
109137

110138
// Debounce function
@@ -169,6 +197,32 @@
169197

170198
textarea.addEventListener('focus', resetClearButton);
171199

200+
btnCopy.addEventListener('click', async () => {
201+
const content = textarea.value;
202+
if (!content) return;
203+
204+
try {
205+
await navigator.clipboard.writeText(content);
206+
const originalText = btnCopy.textContent;
207+
btnCopy.textContent = 'Copied!';
208+
btnCopy.classList.add('success');
209+
btnCopy.setAttribute('aria-label', 'Content copied successfully');
210+
211+
setTimeout(() => {
212+
btnCopy.textContent = originalText;
213+
btnCopy.classList.remove('success');
214+
btnCopy.setAttribute('aria-label', 'Copy to Clipboard');
215+
}, 2000);
216+
} catch (err) {
217+
console.error('Failed to copy:', err);
218+
const originalText = btnCopy.textContent;
219+
btnCopy.textContent = 'Error';
220+
setTimeout(() => {
221+
btnCopy.textContent = originalText;
222+
}, 2000);
223+
}
224+
});
225+
172226
// 接收来自扩展的消息
173227
window.addEventListener('message', (event) => {
174228
const message = event.data;

0 commit comments

Comments
 (0)