fix(apollo-wind): stop FormField overflowing on truncating controls - #1112
fix(apollo-wind): stop FormField overflowing on truncating controls#1112BenGSchulz wants to merge 2 commits into
Conversation
…ellipsize FormField's implicit `auto` column floors at its widest child's min-content. A control containing a `truncate` span is `white-space: nowrap`, so its min-content is the entire string, and the field pushed past a width-constrained host instead of ellipsizing. This reached every standard-typed field, since field-renderer wraps each one in FormField. Pinning the track to `minmax(0, 1fr)` bounds it. A `1fr` track still resolves against max-content when the host width is indefinite, so shrink-to-fit hosts measure identically; the two diverge only where the width is definite, which is the broken case. `className` merges last, so `grid-cols-2` still overrides. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A bare `<label>` is `display: inline`, and vertical margins have no effect on a non-replaced inline box. Tailwind v4 changed `space-y-*` to emit `margin-block-end` on every child but the last, so the margin now lands on the Label and is discarded: a `space-y-*` wrapper produces no gap at all, with nothing to indicate the wrapper is the problem. `inline-block` fixes it while preserving inline-flow use, which `block` would not. Grid and flex items are blockified anyway, so nothing changes inside FormField, and a consumer needing another display passes one. Consumers that wrapped a bare Label in `space-y-*` will see the previously swallowed gap appear. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Apollo Coded App preview deployments are ready.
|
There was a problem hiding this comment.
🟢 Approval recommended
The changes are small, well-scoped CSS utility adjustments with explicit regression tests verifying both the new defaults and consumer override behavior.
Pull request overview
This PR addresses two Tailwind/CSS layout edge cases in apollo-wind that caused (1) FormField to overflow instead of truncating in width-constrained hosts and (2) Label to ignore space-y-* vertical spacing under Tailwind v4 due to being display: inline.
Changes:
- Pin
FormField’s single grid column togrid-cols-[minmax(0,1fr)]to allow truncating controls to shrink/ellipsis in definite-width containers. - Make
Labelrender asinline-blockso Tailwind v4space-y-*margins apply, while still allowing consumers to override display viaclassName. - Add regression tests asserting the default classes and that consumer overrides win (via
cn+ tailwind-merge behavior).
File summaries
| File | Description |
|---|---|
| packages/apollo-wind/src/components/ui/label.tsx | Sets default Label display to inline-block and documents the Tailwind v4 spacing rationale. |
| packages/apollo-wind/src/components/ui/label.test.tsx | Adds tests for the new default display and consumer display override behavior. |
| packages/apollo-wind/src/components/ui/form-field.tsx | Pins the single grid column to minmax(0,1fr) to prevent overflow from truncating controls in definite-width hosts. |
| packages/apollo-wind/src/components/ui/form-field.test.tsx | Adds tests for the pinned grid column and for consumer grid-cols-* override behavior. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Dependency License Review
License distribution
Excluded packages
|
📊 Coverage + size by packagePer-package coverage and bundle size on this PR. New-line coverage = of the source lines this PR adds or changes, the % hit by tests.
"Coverage" is each package's own |
Storybook visual diffBaseline is the deployed main Storybook, so changes merged to main after this branch was last updated can also appear here. Logs Updated (PT): Sep 01, 2026, 06:31:55 PM |
Two related layout fixes in
apollo-wind, reported against 2.43.1.1.
FormField's grid floors at min-contentFormFieldrenderedgrid gap-1.5. Its implicit column track isauto, whose minimum is the item's automatic minimum size, and grid items getmin-width: auto. So the track could never be narrower than its widest child's min-content.A control containing a
truncatespan iswhite-space: nowrap, which makes its min-content the entire string. Any such control forced the track wider than the form and overflowed its container instead of ellipsizing.This was not limited to custom fields:
field-rendererwraps every standard-typed field inFormField, soMetadataFormcarried it too. It showed up wherever a form lives in a width-constrained surface, such as a properties panel, sidebar, or narrow dialog.Fix: pin the single column to
minmax(0, 1fr).Measured, against the compiled Tailwind build
Same markup, same text, in a 320px host (304px content box):
grid(before)grid-cols-[minmax(0,1fr)](after)inline-block(shrink-to-fit)flex: 0 1 autoAn
frtrack resolves against the max-content constraint when the container's width is indefinite, so shrink-to-fit hosts are byte-identical. The two behaviours diverge only when the width is definite, which is exactly the broken case, so no consumer depends on today's behaviour who isn't already looking at an overflowing control.The escape hatch survives, since
classNameis merged last:flex flex-colwould also have fixed this, and arguably more honestly, since the automatic-minimum-size rule applies only to the flex main axis. It was rejected because it silently breaks any consumer passinggrid-cols-2/grid-cols-[auto_1fr], as those utilities do not restoredisplay: grid. One extra class is the cheaper trade.2.
Labelhad no display, sospace-y-*silently did nothingLabelrendered a bare Radix<label>with typography classes and no display utility, so it wasdisplay: inline. Tailwind v4 changedspace-y-*to emitmargin-block-endon every child but the last (v3 emittedmargin-topon every child but the first). Vertical margins have no effect on non-replaced inline boxes, so the margin landed on theLabeland was discarded.Confirmed in the browser: the
space-y-1.5rule does emitmargin-block-end, theLabelcomputed todisplay: inline,margin-block-endcomputed to6px, and the measured gap was3.5px(pure line-box leading).Fix:
inline-block. It preserves inline-flow use, such as checkbox rows and inline hints, in a wayblockwould not.Anywhere a consumer wrapped a bare
Labelinspace-y-*, the previously swallowed gap now appears. One instance exists in our own stories (Basic Contact Form, the "Urgent Request" toggle under aspace-y-0.5wrapper).Inside
FormFieldnothing changes: grid items are blockified, so the label already computed toblock. Verified in the DOM. Thedatetime-pickerlabel that passesflex items-center gap-2staysflexvia tailwind-merge. No consumer putstruncateon aLabel.Verification
apollo-windsuite: 1437 tests / 93 files passing. Four new regression tests covering the pinned column, the consumer column override, the label display, and the label display override.biome checkclean on all four files;tsc --noEmitclean.test:visualis declared inturbo.jsonbut no package implements it, so there is no visual suite to run. The pixel diff noted above is worth a manual look if snapshots exist elsewhere.Notes for the reporter
The local
@layer baseworkaround can be deleted once this lands:It composes with this fix rather than fighting it, so there is no version gate on removing it.
🤖 Generated with Claude Code