Form view: multiline auto-growing value textareas (cap 180px)
This commit is contained in:
+21
-12
@@ -57,11 +57,12 @@
|
|||||||
font: 12.5px/1.45 ui-monospace, Menlo, monospace; color: #9aa4b2;
|
font: 12.5px/1.45 ui-monospace, Menlo, monospace; color: #9aa4b2;
|
||||||
word-break: break-word; padding-top: 8px; user-select: text;
|
word-break: break-word; padding-top: 8px; user-select: text;
|
||||||
}
|
}
|
||||||
.entry .v input {
|
.entry .v textarea {
|
||||||
width: 100%; background: #0d0f12; color: #e6e8eb; border: 1px solid #2a313a;
|
width: 100%; background: #0d0f12; color: #e6e8eb; border: 1px solid #2a313a;
|
||||||
border-radius: 8px; padding: 7px 9px; font-size: 14px;
|
border-radius: 8px; padding: 7px 9px; font-size: 14px; line-height: 1.45;
|
||||||
|
min-height: 40px; resize: none; overflow-y: auto; max-height: 180px;
|
||||||
}
|
}
|
||||||
.entry .v input:focus { border-color: #1f7a3d; outline: none; }
|
.entry .v textarea:focus { border-color: #1f7a3d; outline: none; }
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
/* Mobile: key on top, value below */
|
/* Mobile: key on top, value below */
|
||||||
.entry { grid-template-columns: 1fr; gap: 3px; }
|
.entry { grid-template-columns: 1fr; gap: 3px; }
|
||||||
@@ -174,21 +175,23 @@ function renderForm() {
|
|||||||
k.textContent = b.key; // read-only by design
|
k.textContent = b.key; // read-only by design
|
||||||
const v = document.createElement("div");
|
const v = document.createElement("div");
|
||||||
v.className = "v";
|
v.className = "v";
|
||||||
const input = document.createElement("input");
|
const area = document.createElement("textarea");
|
||||||
input.type = "text";
|
area.rows = 1;
|
||||||
input.spellcheck = false;
|
area.spellcheck = false;
|
||||||
input.autocapitalize = "off";
|
area.autocapitalize = "off";
|
||||||
input.autocorrect = "off";
|
area.autocorrect = "off";
|
||||||
input.value = b.value;
|
area.value = b.value;
|
||||||
input.addEventListener("input", () => {
|
area.addEventListener("input", () => {
|
||||||
b.value = input.value;
|
b.value = area.value;
|
||||||
localDirty = true;
|
localDirty = true;
|
||||||
updateBanner();
|
updateBanner();
|
||||||
|
autoGrow(area);
|
||||||
});
|
});
|
||||||
v.appendChild(input);
|
v.appendChild(area);
|
||||||
row.appendChild(k);
|
row.appendChild(k);
|
||||||
row.appendChild(v);
|
row.appendChild(v);
|
||||||
el.appendChild(row);
|
el.appendChild(row);
|
||||||
|
autoGrow(area);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Unparseable data line — never let the form clobber a file we don't
|
// Unparseable data line — never let the form clobber a file we don't
|
||||||
@@ -201,6 +204,12 @@ function renderForm() {
|
|||||||
$("notice").style.display = "none";
|
$("notice").style.display = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Grow a value textarea to fit its content (cap at 180px, then scroll).
|
||||||
|
function autoGrow(el) {
|
||||||
|
el.style.height = "auto";
|
||||||
|
el.style.height = Math.min(el.scrollHeight + 2, 180) + "px";
|
||||||
|
}
|
||||||
|
|
||||||
function switchMode(m) {
|
function switchMode(m) {
|
||||||
mode = m;
|
mode = m;
|
||||||
$("btnForm").classList.toggle("on", m === "form");
|
$("btnForm").classList.toggle("on", m === "form");
|
||||||
|
|||||||
Reference in New Issue
Block a user