-
Notifications
You must be signed in to change notification settings - Fork 279
Open
Description
When multiple text elements overflow a fixed-height box, the text becomes scrambled with characters overlapping. This happens because flexbox shrinks text elements to fit, causing them to render on top of each other.
Example without flexShrink={0}:
<box flexDirection="column" height={10} border>
<text>Line 1: Short text</text>
<text>Line 2: Another line</text>
<text fg="red">Line 3: Red text</text>
<text fg="green">Line 4: Green text</text>
<text>Line 5: More content</text>
<!-- more lines that overflow -->
</box>Result - scrambled text with characters from different lines overlapping:
┌────────────────────────────────────────┐
│Line 2: Anothereshort line │
│Line 5: GreenocoloredeteXtf the box │
│Liner7: Bluetextchere it is quite long │
│Line 12:lAlmostpatnthe end │
│Line 15: Definitelysoverflowinglnow │
└────────────────────────────────────────┘
Adding flexShrink={0} fixes it:
<box flexDirection="column" height={10} border>
<text flexShrink={0}>Line 1: Short text</text>
<text flexShrink={0}>Line 2: Another line</text>
<!-- ... -->
</box>Result - clean text that overflows correctly:
┌────────────────────────────────────────┐
│Line 1: Short text │
│Line 2: Another line │
│Line 3: Red text │
│Line 4: Green text │
│Line 5: More content │
└────────────────────────────────────────┘
Line 6: Overflow renders outside box
Full reproduction code
import { createCliRenderer } from "@opentui/core"
import { createRoot } from "@opentui/react"
function App() {
return (
<box flexDirection="column" height={15} border title="Overflow Text Example">
<text>Line 1: Short text</text>
<text>Line 2: Another short line</text>
<text>
Line 3: This is a much longer line of text that should wrap to the next line when it reaches the edge of the
box container
</text>
<text fg="red">Line 4: Red colored text</text>
<text fg="green">Line 5: Green colored text</text>
<text>
Line 6: Another wrapping line with lots of content that will definitely need to wrap around because it is quite
long and verbose
</text>
<text fg="blue">Line 7: Blue text here</text>
<text>Line 8: Regular text</text>
<text fg="yellow">Line 9: Yellow warning style</text>
<text>Line 10: More content</text>
<text>Line 11: This wrapping text contains styled parts</text>
<text>Line 12: Almost at the end</text>
<text fg="brightRed">Line 13: Bright red text</text>
<text>Line 14: This line should overflow</text>
<text>Line 15: Definitely overflowing now</text>
<text>Line 16: Way past the box height</text>
<text>Line 17: Still going</text>
<text fg="brightGreen">Line 18: Bright green at the bottom</text>
<text>Line 19: Final line of overflow content</text>
<text>Line 20: The very last line</text>
</box>
)
}
const renderer = await createCliRenderer()
createRoot(renderer).render(<App />)flexShrink={0} should be the default for text elements:
- Current behavior produces garbled output that looks like a rendering bug
- Text shrinking vertically to fit a container doesn't make sense - text should wrap, truncate, or overflow
- Users who want shrinking behavior can wrap text in a box
- Matches browser behavior - in CSS, text nodes don't shrink to fit their container, they overflow
Related to #96. I can open a PR for this.
Metadata
Metadata
Assignees
Labels
No labels