ui: an input goes under its label, not beside it

InputForm returned a fragment, so its label and its field arrived as two
children of whatever contained them.  In a grid that is two cells: on
/videos/settings the "Video File Format" and "Extra yt-dlp Arguments"
inputs sat in the column to the right of their own labels.

The label is now block with the same 4px gap the migrated fields use
(FieldLabel in Download.js), so an InputForm and a DestinationForm side
by side start their inputs at the same height -- the Channel Name and
Directory fields on the Channel edit page were off by the difference.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Roland 2026-08-05 16:59:48 -06:00
parent 8c614989de
commit cd8a777caa
No known key found for this signature in database
GPG key ID: 1BA620CE6C9A4680
2 changed files with 48 additions and 3 deletions

View file

@ -356,8 +356,15 @@ export function InputForm({
</Message>;
}
return <>
<label htmlFor={`${name}_input`}>
/*
* One element, not a fragment: every caller that puts an InputForm in a grid or flex
* container was getting the label and the input laid out as two separate items -- the
* input beside its own label rather than under it. The label is block with the same
* 4px gap the migrated fields (Download.js FieldLabel) use, so an InputForm and a
* DestinationForm side by side line their inputs up at the same height.
*/
return <div>
<label htmlFor={`${name}_input`} style={{display: 'block', marginBottom: 4}}>
<b>{label} {required && <RequiredAsterisk/>}</b>
{helpContent &&
<InfoPopup
@ -375,7 +382,7 @@ export function InputForm({
/>
</div>
{messageElm}
</>
</div>
}
export function NumberInputForm({

View file

@ -944,6 +944,44 @@ describe('Form Components', () => {
const input = screen.getByRole('textbox');
expect(input).toBeDisabled();
});
it('puts the label and the input inside a single element', () => {
// A fragment made them two children of whatever contained them, so a grid or flex
// parent laid the input out beside its label instead of under it.
const form = createMockForm({file_name_format: ''});
renderWithProviders(
<div data-testid="grid">
<InputForm
form={form}
name="file_name_format"
label="Video File Format"
/>
</div>
);
const grid = screen.getByTestId('grid');
expect(grid.children).toHaveLength(1);
expect(grid.firstElementChild).toContainElement(screen.getByRole('textbox'));
expect(grid.firstElementChild).toContainElement(
screen.getByText(/Video File Format/).closest('label')
);
});
it('renders the label as a block above the input', () => {
const form = createMockForm({name: ''});
renderWithProviders(
<InputForm
form={form}
name="name"
label="Channel Name"
/>
);
const label = screen.getByText(/Channel Name/).closest('label');
expect(label).toHaveStyle({display: 'block'});
});
});
describe('NumberInputForm', () => {