diff --git a/TUI.Test/BorderElementRenderTests.cs b/TUI.Test/BorderElementRenderTests.cs index bd91f53..325f94e 100644 --- a/TUI.Test/BorderElementRenderTests.cs +++ b/TUI.Test/BorderElementRenderTests.cs @@ -206,4 +206,28 @@ public void TitleIsSuppressedWhenTheBorderIsTooNarrow() // Assert Assert.IsEmpty(provider.WritesOf(" Title ")); } + + /// + /// A title containing a line break stays on the top border row: no write carries the break to + /// the terminal, and each break is drawn as a space (ktsu-dev/TUI#151). + /// + /// The title under test. + [TestMethod] + [DataRow("ab\ncd")] + [DataRow("ab\rcd")] + [DataRow("ab\r\ncd")] + public void TitleWithALineBreakIsDrawnOnOneRow(string title) + { + // Arrange + BorderElement element = CreateElement(width: 12, height: 4); + element.Title = title; + RecordingConsoleProvider provider = new(); + + // Act + element.Render(provider); + + // Assert + Assert.IsFalse(provider.Writes.Any(w => w.Text.Contains('\r') || w.Text.Contains('\n')), "A write carried a line break"); + Assert.AreEqual(0, provider.WritesOf(" ab cd ").Single().Position.Y); + } } diff --git a/TUI/Elements/Primitives/BorderElement.cs b/TUI/Elements/Primitives/BorderElement.cs index 20ef551..c318779 100644 --- a/TUI/Elements/Primitives/BorderElement.cs +++ b/TUI/Elements/Primitives/BorderElement.cs @@ -150,7 +150,11 @@ protected override void OnRender(IConsoleProvider provider) if (!string.IsNullOrEmpty(Title) && dimensions.Width > 4) { int maxTitleWidth = dimensions.Width - 4; // Leave space for border and padding - string displayTitle = Title.Length > maxTitleWidth ? Title[..maxTitleWidth] : Title; + + // A line break written to the terminal would move the rest of the title off the top + // border row and over the left edge, so each break becomes a space (ktsu-dev/TUI#151). + string singleLineTitle = Title.Replace("\r\n", " ", StringComparison.Ordinal).Replace('\r', ' ').Replace('\n', ' '); + string displayTitle = singleLineTitle.Length > maxTitleWidth ? singleLineTitle[..maxTitleWidth] : singleLineTitle; string titleWithPadding = $" {displayTitle} "; int titleX = TitleAlignment switch