From b8778c18472fb76cb70fd973cd9660bfdac8c2d4 Mon Sep 17 00:00:00 2001 From: Yunfei He Date: Tue, 26 May 2026 00:52:37 +0800 Subject: [PATCH] fix: Text node defaults to flexDirection='row' matching Ink's ink-text Set flexDirection=row, flexShrink=1, flexGrow=0 on text yoga nodes at creation time, matching Ink's style defaults. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../layout/text-flex-direction.test.tsx | 40 +++++++++++++++++++ packages/runtime/src/host/yoga.ts | 8 ++++ 2 files changed, 48 insertions(+) create mode 100644 packages/runtime-tests/integration/layout/text-flex-direction.test.tsx diff --git a/packages/runtime-tests/integration/layout/text-flex-direction.test.tsx b/packages/runtime-tests/integration/layout/text-flex-direction.test.tsx new file mode 100644 index 0000000..c70577e --- /dev/null +++ b/packages/runtime-tests/integration/layout/text-flex-direction.test.tsx @@ -0,0 +1,40 @@ +import { defineComponent } from "vue"; +import { expect, test } from "vite-plus/test"; +import { render } from "@vue-tui/testing"; +import { Box, Text } from "@vue-tui/runtime"; + +test("nested top-level Text nodes flow horizontally (row direction)", async () => { + // In Ink, renders with flexDirection='row' so that sibling + // top-level elements within a row-direction display inline. + const { lastFrame } = await render( + defineComponent(() => () => ( + + A + B + + )), + { columns: 100 }, + ); + // Box defaults to row, so A and B should be on the same line + expect(lastFrame({ trimLines: true })).toBe("AB"); +}); + +test("top-level Text renders with flexDirection='row' for nested Text", async () => { + // Two children inside a column : each is its own yoga node. + // Within a single , nested renders as virtual-text (no yoga). + // This test confirms that top-level Text nodes participate in the parent's + // flex layout with row direction by default. + const { lastFrame } = await render( + defineComponent(() => () => ( + + + A + B + + + )), + { columns: 100 }, + ); + // Nested Text within a single Text renders inline (virtual-text), so "AB" + expect(lastFrame({ trimLines: true })).toBe("AB"); +}); diff --git a/packages/runtime/src/host/yoga.ts b/packages/runtime/src/host/yoga.ts index 2fd3f48..c7359d7 100644 --- a/packages/runtime/src/host/yoga.ts +++ b/packages/runtime/src/host/yoga.ts @@ -59,6 +59,14 @@ export function attachYoga(node: YogaCarrier): void { (node.yoga as YogaNode).setFlexWrap(Yoga.WRAP_NO_WRAP); (node.yoga as YogaNode).setFlexGrow(0); } + // Text nodes match Ink's defaults: row direction, shrinkable. + // Although text nodes rarely have yoga-carrying children, this ensures + // consistent layout behavior matching Ink. + if (node.type === "text") { + (node.yoga as YogaNode).setFlexDirection(Yoga.FLEX_DIRECTION_ROW); + (node.yoga as YogaNode).setFlexShrink(1); + (node.yoga as YogaNode).setFlexGrow(0); + } } export function detachYoga(node: YogaCarrier): void {