Design for text you didn't write
I shipped the same layout bug twice, in the same component, months apart. Both times the cause was identical: I sized a container for text a human would write, and a model wrote something longer.
What it looked like
A card showing a product recommendation. Name on the left, commission figure on
the right. In every example I built against, the figure was short —
20–40%, $30–80 per sale. It fit comfortably.
Then a run came back with $1,000–$5,000 per booking (or per
charter). The card's right-hand block was marked shrink-0,
so it refused to compress. The block pushed the card wider than its grid
column. The figure was cut off mid-word against the card edge. The dialog grew
a horizontal scrollbar. And the product name — squeezed into whatever width
was left — wrapped into a ribbon one or two words per line.
One long string, and the entire card fell apart.
The mechanical cause
shrink-0 (flex-shrink: 0) tells a flex child never to
compress below its natural size. For a long unbroken run of text, natural size
is the whole line. The track sizes to min-content, min-content is
enormous, and everything else in the row gets whatever remains.
The rule I now hold: a flex child only wraps if it is allowed to
shrink. So the fix is min-w-0 on both sides — permitting
compression — plus a maximum width so one column cannot eat the row:
<!-- before: refuses to compress, overflows on long values -->
<div class="text-right shrink-0">
<!-- after: allowed to wrap, capped -->
<div class="text-right min-w-0 max-w-[45%]">
The first time this bit me, in the same dialog, it hid controls off the right edge — a "Queue posts" button a user could not see or reach. Different symptom, identical mechanism.
Why generated text keeps finding this
Every layout carries implicit assumptions about content length. When you write the copy, those assumptions hold trivially, because you write to fit. You would never type a forty-character commission figure into a slot built for eight.
A model has no such feedback. It emits whatever the prompt and the data suggest, and the distribution has a long tail. Most outputs are short. Some are not. And the ones that are not appear only when a real run happens to produce them — which is exactly why this survives testing. My fixtures had short values, because I wrote the fixtures.
Wherever generated text meets layout, ask: what happens at ten times this length? If the answer is "it overflows," that is not an edge case. It is a scheduled outage waiting for the right prompt.
The second bug in the same card
Worth mentioning because it has the same root. The card drew a dollar-sign icon beside the commission figure. Reasonable — until a value arrives that already carries its own symbol. Users saw:
$ $1,000–$5,000 per booking
Again: I assumed a shape for text I did not write. The fix suppresses the icon when the value already starts with a currency symbol, and — this part matters — never edits the number itself. Rewriting a figure someone is about to make a financial decision on would be a worse defect than the one being fixed. Decorate around generated content; do not silently correct it.
What I do now
-
Never
shrink-0on generated text. It is fine on an icon, a badge, a fixed-width control. On model output it is a bug with a delay fuse. - Look at real output, not fixtures. Both bugs were found by opening the actual product and reading the actual screen. Neither was reachable from the test suite, because the suite used data I invented.
-
Write the rule at the call site. There is now a comment
above that block explaining why it is
min-w-0and what happens if someone "tidies" it back. I shipped this twice; the third time should cost somebody a comment rather than an afternoon.