diff --git a/bindery/static/js/stories.js b/bindery/static/js/stories.js index d040961..dac29b4 100644 --- a/bindery/static/js/stories.js +++ b/bindery/static/js/stories.js @@ -227,6 +227,13 @@ export function storiesPage(main, _params, config) { rows: 3, placeholder: 'https://www.royalroad.com/fiction/… (one URL per line)', 'aria-label': 'Story URLs', + // Phones give no handle to resize a textarea, so the field grows to fit its URLs. It never + // shrinks, so a size set with the handle on a desktop stays. + oninput: () => { + if (urls.scrollHeight > urls.clientHeight) { + urls.style.height = `${urls.scrollHeight + urls.offsetHeight - urls.clientHeight}px`; + } + }, }); const add = button( 'Add', @@ -237,6 +244,7 @@ export function storiesPage(main, _params, config) { if (result.jobs.length) { toast(`Queued ${result.jobs.length} ${result.jobs.length === 1 ? 'story' : 'stories'}`); urls.value = ''; + urls.style.height = ''; refreshJobs(); } }, diff --git a/tests/js/flow-helpers.mjs b/tests/js/flow-helpers.mjs index 36adbed..00fd0c8 100644 --- a/tests/js/flow-helpers.mjs +++ b/tests/js/flow-helpers.mjs @@ -12,6 +12,7 @@ export class Element { this.checked = false; this.disabled = false; this.files = []; + this.style = {}; } append(...children) { for (const child of children) { diff --git a/tests/js/flows.test.mjs b/tests/js/flows.test.mjs index a19212b..0c0148b 100644 --- a/tests/js/flows.test.mjs +++ b/tests/js/flows.test.mjs @@ -88,7 +88,12 @@ test('failed settings saves retain edits and re-enable the action', async () => test('adding stories keeps input on rejection and clears it after a mixed result', async () => { await mountStories({ ...config, library_available: false }); const urls = nodes(main).find((el) => el.tagName === 'textarea'); - urls.value = ' https://site.test/1\n\nhttps://site.test/2 '; + Object.assign(urls, { scrollHeight: 90, clientHeight: 60, offsetHeight: 62 }); + input(urls, ' https://site.test/1\n\nhttps://site.test/2 '); + assert.equal(urls.style.height, '92px'); + Object.assign(urls, { scrollHeight: 50, clientHeight: 90, offsetHeight: 92 }); + input(urls, urls.value); + assert.equal(urls.style.height, '92px'); api.on('POST', 'stories', { error: 'Unavailable' }, 503); await click(main, 'Add'); assert.match(urls.value, /site.test/); @@ -96,6 +101,7 @@ test('adding stories keeps input on rejection and clears it after a mixed result await click(main, 'Add'); assert.deepEqual(api.sent('POST', 'stories').at(-1).body, { urls: ' https://site.test/1\n\nhttps://site.test/2 ' }); assert.equal(urls.value, ''); + assert.equal(urls.style.height, ''); assert.match(ui.toasts.textContent, /Unsupported URL/); await click(main, 'Add'); assert.equal(api.sent('POST', 'stories').length, 2);