Skip to content

Commit 00e1b31

Browse files
committed
Add clear button to text inputs in HTML report
Show a circle-X clear button inside text inputs (Justification, Notes) when they contain text. Button uses transparent fill with border color matching input borders. Clicking clears the value, triggers change event for auto-save, and refocuses the input. https://claude.ai/code/session_01VHEe12W2fkQZ7xneXy8Wry
1 parent 0d8269e commit 00e1b31

3 files changed

Lines changed: 85 additions & 6 deletions

File tree

‎Services/HtmlReport/diff_report.css‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,13 +157,22 @@
157157
}
158158
/* ── Row hover highlight ─────────────────────────────────────────────── */
159159
:not(.stat-table):not(.legend-table):not(.il-ignore-table) > tbody tr:not(.diff-row):not(.diff-hunk-tr):not(.diff-del-tr):not(.diff-add-tr):hover { background: #f3eef8; }
160-
td input[type="text"] {
161-
width: 100%; border: 0; padding: 2px 4px; font-size: 12px;
160+
.input-wrap { position: relative; display: flex; align-items: center; }
161+
.input-wrap input[type="text"] {
162+
width: 100%; border: 0; padding: 2px 20px 2px 4px; font-size: 12px;
162163
background: transparent; outline: none; box-shadow: none;
163164
-webkit-appearance: none; -moz-appearance: none; appearance: none;
164165
font-family: inherit; }
165-
td input[type="text"]:focus {
166+
.input-wrap input[type="text"]:focus {
166167
background: #fffff8; outline: 1px solid #aaa; }
168+
.btn-clear {
169+
position: absolute; right: 2px; top: 50%; transform: translateY(-50%);
170+
display: none; border: 1.2px solid #aaa; background: transparent;
171+
border-radius: 50%; width: 14px; height: 14px; padding: 0;
172+
cursor: pointer; line-height: 1; color: #aaa;
173+
}
174+
.btn-clear svg { display: block; margin: auto; }
175+
.input-wrap.has-text .btn-clear { display: flex; align-items: center; justify-content: center; }
167176
input[type="checkbox"] { width: 1.1em; height: 1.1em; cursor: pointer; }
168177
/* ── Per-row copy path button ────────────────────────────────────────── */
169178
.btn-copy-path {

‎Services/HtmlReport/diff_report.js‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
syncTableWidths();
3838
syncScTableWidths();
3939
syncFilterRowHeight();
40+
initClearButtons();
4041
setupLazyDiff();
4142
setupLazySection();
4243
// Pre-create hidden file input for Verify integrity so the accept
@@ -285,6 +286,8 @@
285286
initColResizeSingle(th);
286287
});
287288
syncTableWidths();
289+
// Init clear buttons on new text inputs / 新規テキスト入力にクリアボタンを付与
290+
d.querySelectorAll('td input[type="text"]').forEach(wrapInputWithClear);
288291
// Wire up save events on new inputs / 新規inputにsaveイベントを接続
289292
if (__savedState__ === null) {
290293
d.querySelectorAll('input, textarea').forEach(function(el) {
@@ -412,6 +415,35 @@
412415
if (h > 0) document.documentElement.style.setProperty('--ft-row-h', h + 'px');
413416
}
414417

418+
// Wrap td text inputs with clear button / td テキスト入力にクリアボタンを付与
419+
function wrapInputWithClear(inp) {
420+
if (inp.parentElement.classList.contains('input-wrap')) return;
421+
var wrap = document.createElement('div');
422+
wrap.className = 'input-wrap';
423+
inp.parentNode.insertBefore(wrap, inp);
424+
wrap.appendChild(inp);
425+
var btn = document.createElement('button');
426+
btn.type = 'button';
427+
btn.className = 'btn-clear';
428+
btn.tabIndex = -1;
429+
btn.title = 'Clear';
430+
btn.innerHTML = '<svg width="8" height="8" viewBox="0 0 8 8" stroke="currentColor" stroke-width="1.5" fill="none"><line x1="1" y1="1" x2="7" y2="7"/><line x1="7" y1="1" x2="1" y2="7"/></svg>';
431+
wrap.appendChild(btn);
432+
function sync() { wrap.classList.toggle('has-text', inp.value.length > 0); }
433+
inp.addEventListener('input', sync);
434+
btn.addEventListener('click', function() {
435+
inp.value = '';
436+
sync();
437+
inp.dispatchEvent(new Event('change', { bubbles: true }));
438+
inp.focus();
439+
});
440+
sync();
441+
}
442+
443+
function initClearButtons() {
444+
document.querySelectorAll('td input[type="text"]').forEach(wrapInputWithClear);
445+
}
446+
415447
function initColResize() {
416448
document.querySelectorAll('th.th-resizable').forEach(function(th) {
417449
initColResizeSingle(th);

‎doc/samples/diff_report.html‎

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,22 @@
151151
}
152152
/* ── Row hover highlight ─────────────────────────────────────────────── */
153153
:not(.stat-table):not(.legend-table):not(.il-ignore-table) > tbody tr:not(.diff-row):not(.diff-hunk-tr):not(.diff-del-tr):not(.diff-add-tr):hover { background: #f3eef8; }
154-
td input[type="text"] {
155-
width: 100%; border: 0; padding: 2px 4px; font-size: 12px;
154+
.input-wrap { position: relative; display: flex; align-items: center; }
155+
.input-wrap input[type="text"] {
156+
width: 100%; border: 0; padding: 2px 20px 2px 4px; font-size: 12px;
156157
background: transparent; outline: none; box-shadow: none;
157158
-webkit-appearance: none; -moz-appearance: none; appearance: none;
158159
font-family: inherit; }
159-
td input[type="text"]:focus {
160+
.input-wrap input[type="text"]:focus {
160161
background: #fffff8; outline: 1px solid #aaa; }
162+
.btn-clear {
163+
position: absolute; right: 2px; top: 50%; transform: translateY(-50%);
164+
display: none; border: 1.2px solid #aaa; background: transparent;
165+
border-radius: 50%; width: 14px; height: 14px; padding: 0;
166+
cursor: pointer; line-height: 1; color: #aaa;
167+
}
168+
.btn-clear svg { display: block; margin: auto; }
169+
.input-wrap.has-text .btn-clear { display: flex; align-items: center; justify-content: center; }
161170
input[type="checkbox"] { width: 1.1em; height: 1.1em; cursor: pointer; }
162171
/* ── Per-row copy path button ────────────────────────────────────────── */
163172
.btn-copy-path {
@@ -1039,6 +1048,7 @@ <h2 style="color:#0051c3">[ ! ] Modified Files &#x2014; new file timestamps olde
10391048
syncTableWidths();
10401049
syncScTableWidths();
10411050
syncFilterRowHeight();
1051+
initClearButtons();
10421052
setupLazyDiff();
10431053
setupLazySection();
10441054
// Pre-create hidden file input for Verify integrity so the accept
@@ -1369,6 +1379,34 @@ <h2 style="color:#0051c3">[ ! ] Modified Files &#x2014; new file timestamps olde
13691379
if (h > 0) document.documentElement.style.setProperty('--ft-row-h', h + 'px');
13701380
}
13711381

1382+
function wrapInputWithClear(inp) {
1383+
if (inp.parentElement.classList.contains('input-wrap')) return;
1384+
var wrap = document.createElement('div');
1385+
wrap.className = 'input-wrap';
1386+
inp.parentNode.insertBefore(wrap, inp);
1387+
wrap.appendChild(inp);
1388+
var btn = document.createElement('button');
1389+
btn.type = 'button';
1390+
btn.className = 'btn-clear';
1391+
btn.tabIndex = -1;
1392+
btn.title = 'Clear';
1393+
btn.innerHTML = '<svg width="8" height="8" viewBox="0 0 8 8" stroke="currentColor" stroke-width="1.5" fill="none"><line x1="1" y1="1" x2="7" y2="7"/><line x1="7" y1="1" x2="1" y2="7"/></svg>';
1394+
wrap.appendChild(btn);
1395+
function sync() { wrap.classList.toggle('has-text', inp.value.length > 0); }
1396+
inp.addEventListener('input', sync);
1397+
btn.addEventListener('click', function() {
1398+
inp.value = '';
1399+
sync();
1400+
inp.dispatchEvent(new Event('change', { bubbles: true }));
1401+
inp.focus();
1402+
});
1403+
sync();
1404+
}
1405+
1406+
function initClearButtons() {
1407+
document.querySelectorAll('td input[type="text"]').forEach(wrapInputWithClear);
1408+
}
1409+
13721410
function initColResizeSingle(th) {
13731411
var label = document.createElement('span');
13741412
label.className = 'th-label';

0 commit comments

Comments
 (0)