Skip to content

Commit ddcd8fc

Browse files
feat(scratchpad): improve UX with autofocus and dynamic button states
- Add `autofocus` to scratchpad textarea to reduce friction on open. - Disable Copy/Remove/Clear buttons when scratchpad is empty to prevent useless interactions. - Add visual disabled state (opacity, cursor) to buttons. - Fix CSS issue where disabled buttons would swallow mouse events (restoring `cursor: not-allowed`).
1 parent ba2d7d9 commit ddcd8fc

1 file changed

Lines changed: 33 additions & 2 deletions

File tree

src/features/scratchpad/scratchpad.html

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,17 @@
7272
outline: 1px solid var(--vscode-focusBorder);
7373
outline-offset: 1px;
7474
}
75+
.btn:disabled {
76+
opacity: 0.5;
77+
cursor: not-allowed;
78+
}
7579

7680
/* Secondary Button (Standard) */
7781
.btn-secondary {
7882
color: var(--vscode-button-secondaryForeground);
7983
background-color: var(--vscode-button-secondaryBackground);
8084
}
81-
.btn-secondary:hover {
85+
.btn-secondary:not(:disabled):hover {
8286
background-color: var(--vscode-button-secondaryHoverBackground);
8387
}
8488
/* Destructive State for Secondary Button */
@@ -95,7 +99,7 @@
9599
color: var(--vscode-button-foreground);
96100
background-color: var(--vscode-button-background);
97101
}
98-
.btn-primary:hover {
102+
.btn-primary:not(:disabled):hover {
99103
background-color: var(--vscode-button-hoverBackground);
100104
}
101105
</style>
@@ -106,6 +110,7 @@
106110
aria-label="Scratchpad Input"
107111
placeholder="Scratchpad: Type your temporary notes here... (Content is cleared on reload)"
108112
spellcheck="false"
113+
autofocus
109114
></textarea>
110115
<div class="footer">
111116
<span id="char-count" class="char-count" aria-live="polite">0 chars</span>
@@ -146,6 +151,25 @@
146151
charCount.textContent = `${length} char${length !== 1 ? 's' : ''}`;
147152
}
148153

154+
function updateButtonStates() {
155+
const hasContent = textarea.value.length > 0;
156+
btnCopy.disabled = !hasContent;
157+
btnRemoveEmpty.disabled = !hasContent;
158+
// Clear button should also be disabled if there's no content
159+
// However, we need to respect the "confirm" state if it was active,
160+
// but if content is empty, confirm state is irrelevant as we can't clear empty.
161+
// If we just cleared it, it becomes disabled.
162+
btnClear.disabled = !hasContent;
163+
164+
// If disabled, we should probably reset any pending states (like Confirm?)
165+
// to avoid weird states when re-enabling.
166+
if (!hasContent) {
167+
if (btnClear.dataset.state === 'confirm') {
168+
resetClearButton();
169+
}
170+
}
171+
}
172+
149173
function resetClearButton() {
150174
if (clearTimeoutId) {
151175
clearTimeout(clearTimeoutId);
@@ -185,6 +209,7 @@
185209

186210
textarea.addEventListener('input', () => {
187211
updateCharCount();
212+
updateButtonStates();
188213
onInput();
189214
});
190215

@@ -224,6 +249,7 @@
224249
// Second click: Perform action
225250
textarea.value = '';
226251
updateCharCount();
252+
updateButtonStates();
227253
onInput();
228254
textarea.focus();
229255
resetClearButton();
@@ -247,6 +273,7 @@
247273
} else {
248274
textarea.value = newContent;
249275
updateCharCount();
276+
updateButtonStates();
250277
onInput();
251278

252279
const removedCount = lines.length - nonEmptyLines.length;
@@ -269,9 +296,13 @@
269296
case 'restoreContent':
270297
textarea.value = message.content;
271298
updateCharCount();
299+
updateButtonStates();
272300
break;
273301
}
274302
});
303+
304+
// Initialize button states
305+
updateButtonStates();
275306
</script>
276307
</body>
277308
</html>

0 commit comments

Comments
 (0)