Make the metadata fields readable on a phone

Each field was a row of a four-column table: name, lock, value and the
site's current value. On a narrow screen the columns squeezed the
inputs down to a few characters wide.

Each field is now a card with its name and lock on one line and the
input below at full width. The site's value shows only when it
differs, folded behind a line that opens on tap, instead of always
taking its own column. The lock is a labelled toggle instead of a
bare checkbox, and Save stays disabled until something changes.

On a wide screen, the label sits beside the field instead of above
it, and a single-line input no longer stretches to fill the card.
This commit is contained in:
tim
2026-09-27 23:38:28 +02:00
parent 1a10fe53f3
commit 5ef68fb240
3 changed files with 167 additions and 55 deletions
+20
View File
@@ -321,6 +321,26 @@ test('metadata saves skip unchanged drafts, allow edits without a rebuild, and r
assert.deepEqual(api.sent('PUT', 'stories/1/metadata').at(-1).body, { values: { title: null } });
});
test('the metadata card shows the site value only when it differs, and drops the button once locked', async () => {
await mountStory();
const card = section(main, 'Metadata');
assert.match(card.textContent, /Site value differs/);
assert.equal(nodes(card).filter((el) => el.tagName === 'summary').length, 1);
assert.ok(find(card, 'button', 'Use the site value'));
change(field(main, 'Lock Title'), true);
assert.match(card.textContent, /Site value differs/);
assert.equal(find(card, 'button', 'Use the site value'), undefined);
});
test('the Save button of the metadata card is disabled until something changes', async () => {
await mountStory();
const save = find(section(main, 'Metadata'), 'button', 'Save');
assert.equal(save.disabled, true);
input(field(main, 'Authors'), 'Someone else');
assert.equal(save.disabled, false);
assert.match(section(main, 'Metadata').textContent, /Unsaved changes/);
});
test('failed rule saves do not queue a rebuild', async () => {
await mountStory();
const card = section(main, 'Replacement rules');