fix(entries): size the multiline field from its content instead of a fixed height
A manual resize was lost on reopen: the row is rebuilt on every open, and remembering the height would not survive a restart either since localStorage is wiped when the ephemeral port changes the origin. Deriving it from the content removes the state entirely - the field is always the right size.
This commit is contained in:
@@ -4161,6 +4161,12 @@ function soCustomFieldsField() {
|
||||
return wrap;
|
||||
}
|
||||
|
||||
// Grow a textarea to fit its content, up to a cap past which it scrolls.
|
||||
function autoSizeTextarea(ta, maxPx = 320) {
|
||||
ta.style.height = 'auto';
|
||||
ta.style.height = Math.min(ta.scrollHeight, maxPx) + 'px';
|
||||
}
|
||||
|
||||
function buildCustomFieldRow(field, idx, rerender) {
|
||||
const row = el('div', { class: 'so-custom-row' });
|
||||
const labelInput = el('input', {
|
||||
@@ -4189,10 +4195,18 @@ function buildCustomFieldRow(field, idx, rerender) {
|
||||
if (field.multiline) {
|
||||
valueInput = el('textarea', {
|
||||
class: 'so-input so-custom-value so-custom-multiline',
|
||||
rows: 5, placeholder: 'Value',
|
||||
rows: 3, placeholder: 'Value',
|
||||
autocomplete: 'off', autocorrect: 'off', spellcheck: 'false',
|
||||
});
|
||||
valueInput.classList.toggle('is-masked', !!field.is_secret);
|
||||
// Height follows the content instead of being remembered: a manual
|
||||
// resize would be lost anyway (re-rendered on every open, and
|
||||
// localStorage is wiped each launch when the port changes).
|
||||
const grow = () => autoSizeTextarea(valueInput);
|
||||
valueInput.addEventListener('input', grow);
|
||||
// scrollHeight reads 0 until the element is in the DOM — same
|
||||
// render-time vs DOM-attachment trap as renderSoChips (CLAUDE.md).
|
||||
setTimeout(grow, 0);
|
||||
} else {
|
||||
valueInput = el('input', {
|
||||
type: field.is_secret ? 'password' : 'text',
|
||||
|
||||
Reference in New Issue
Block a user