Skip to content

Commit 652681e

Browse files
fix(form): shrink forceLabelWidth column under pressure when responsive (CUI-32)
A section with forceLabelWidth froze its label column to an exact pixel width, so in a responsive Form the label never shrank — only the field track did, until the row flipped to stacked. Treat forceLabelWidth as the column's upper bound instead: responsive wraps it in minmax(min-content, Npx) so the column keeps Npx while there is room and shrinks down to its longest word as the field is squeezed, with rows staying aligned. Non-responsive stays pinned to the exact width (unchanged). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 8bc97ab commit 652681e

1 file changed

Lines changed: 17 additions & 16 deletions

File tree

src/lib/components/form/Form.component.tsx

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,11 @@ type FormSectionProps = {
391391
children: ReactElement<FormGroupProps> | ReactElement<FormGroupProps>[];
392392
title?: { name: string; icon?: IconName; helpTooltip?: string };
393393
/**
394-
* Freezes the label column to exactly this pixel width — a hard cap: labels
395-
* wider than it wrap rather than widening the column. When unset, the column
396-
* auto-sizes to the widest label in the section.
394+
* Caps the label column at this pixel width: labels wider than it wrap rather
395+
* than widening the column. In a `responsive` Form the column keeps this width
396+
* while there is room but shrinks below it (down to the longest word) as the
397+
* field track is squeezed, so rows stay aligned; otherwise it is pinned to this
398+
* exact width. When unset, the column auto-sizes to the widest label.
397399
*/
398400
forceLabelWidth?: number;
399401
rightActions?: ReactNode;
@@ -411,20 +413,19 @@ const FormSection = ({
411413
isValidElement(child) ? child.props.required === true : false,
412414
);
413415

414-
// The label column. `forceLabelWidth` is a hard cap that freezes it to an exact
415-
// pixel width (long labels then wrap, mirroring how `Input`'s `size` fixes the
416-
// field width); it also makes every FormGroup row self-sufficient, so nesting a
417-
// group inside another element no longer breaks its layout. When unset, the
418-
// column auto-sizes to the widest label from content, shared across rows via
419-
// `subgrid` — no measurement. Responsive lets the track shrink to its longest
420-
// word (min-content) before the section flips; non-responsive hugs it
421-
// (max-content).
416+
// The label column. `forceLabelWidth` sets the column's upper bound to an exact
417+
// pixel width (labels wider than it wrap, mirroring how `Input`'s `size` fixes
418+
// the field width); it also makes every FormGroup row self-sufficient, so nesting
419+
// a group inside another element no longer breaks its layout. When unset, the
420+
// column's cap is its widest label (`max-content`), shared across rows via
421+
// `subgrid` — no measurement. Responsive then lets the column shrink from its
422+
// longest word (`min-content`) up to that cap before the section flips;
423+
// non-responsive pins it to the cap.
422424
const fixedLabel = forceLabelWidth != null;
423-
const labelTrack = fixedLabel
424-
? `${forceLabelWidth}px`
425-
: responsive
426-
? 'minmax(min-content, max-content)'
427-
: 'max-content';
425+
const labelWidthCap = fixedLabel ? `${forceLabelWidth}px` : 'max-content';
426+
const labelTrack = responsive
427+
? `minmax(min-content, ${labelWidthCap})`
428+
: labelWidthCap;
428429

429430
return (
430431
<FormSectionContext.Provider value={{ labelTrack, fixedLabel }}>

0 commit comments

Comments
 (0)