Skip to content

Commit

Permalink
Fix aligning multiple text nodes within <Box>
Browse files Browse the repository at this point in the history
If there were mulitple text nodes within `<Box>` container and `alignItems` or
`justifyContent` were applied, that text was not aligned and always had
coordinates of x=0 y=0.

The reason is in that case these text nodes are treated as separate nodes in the
tree, so they have their own coordinates. In other words, `alignItems` or
`justifyContent` affected and laid out each text node individually.

This change fixes it by taking the X and Y first text node in `<Box>` and
offsetting all text nodes by that distance.
  • Loading branch information
Vadim Demedes committed Sep 29, 2019
1 parent ad7160e commit 1f96300
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 2 deletions.
11 changes: 10 additions & 1 deletion src/render-node-to-output.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,16 @@ const isAllTextNodes = node => {
// Also, this is necessary for libraries like ink-link (https://github.com/sindresorhus/ink-link),
// which need to wrap all children at once, instead of wrapping 3 text nodes separately.
const squashTextNodes = node => {
let text = '';
// If parent container is `<Box>`, text nodes will be treated as separate nodes in
// the tree and will have their own coordinates in the layout.
// To ensure text nodes are aligned correctly, take X and Y of the first text node
// and use them as offset for the rest of the nodes
// Only first node is taken into account, because other text nodes can't have margin or padding,
// so their coordinates will be relative to the first node anyway
const offsetX = node.childNodes[0].yogaNode.getComputedLeft();
const offsetY = node.childNodes[0].yogaNode.getComputedTop();

let text = '\n'.repeat(offsetY) + ' '.repeat(offsetX);

for (const childNode of node.childNodes) {
let nodeText;
Expand Down
20 changes: 20 additions & 0 deletions test/flex-align-items.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ test('row - align text to center', t => {
t.is(output, '\nTest\n');
});

test('row - align multiple text nodes to center', t => {
const output = renderToString(
<Box alignItems="center" height={3}>
A{'B'}
</Box>
);

t.is(output, '\nAB\n');
});

test('row - align text to bottom', t => {
const output = renderToString(
<Box alignItems="flex-end" height={3}>
Expand All @@ -23,6 +33,16 @@ test('row - align text to bottom', t => {
t.is(output, '\n\nTest');
});

test('row - align multiple text nodes to bottom', t => {
const output = renderToString(
<Box alignItems="flex-end" height={3}>
A{'B'}
</Box>
);

t.is(output, '\n\nAB');
});

test('column - align text to center', t => {
const output = renderToString(
<Box flexDirection="column" alignItems="center" width={10}>
Expand Down
33 changes: 32 additions & 1 deletion test/flex-justify-content.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from 'react';
import test from 'ava';
import chalk from 'chalk';
import renderToString from './helpers/render-to-string';
import {Box} from '..';
import {Box, Color} from '..';

test('row - align text to center', t => {
const output = renderToString(
Expand All @@ -13,6 +14,16 @@ test('row - align text to center', t => {
t.is(output, ' Test');
});

test('row - align multiple text nodes to center', t => {
const output = renderToString(
<Box justifyContent="center" width={10}>
A{'B'}
</Box>
);

t.is(output, ' AB');
});

test('row - align text to right', t => {
const output = renderToString(
<Box justifyContent="flex-end" width={10}>
Expand All @@ -23,6 +34,16 @@ test('row - align text to right', t => {
t.is(output, ' Test');
});

test('row - align multiple text nodes to right', t => {
const output = renderToString(
<Box justifyContent="flex-end" width={10}>
A{'B'}
</Box>
);

t.is(output, ' AB');
});

test('row - align two text nodes on the edges', t => {
const output = renderToString(
<Box justifyContent="space-between" width={4}>
Expand All @@ -45,6 +66,16 @@ test('row - align two text nodes with equal space around them', t => {
t.is(output, ' A B');
});

test('row - align colored text node when text is squashed', t => {
const output = renderToString(
<Box justifyContent="flex-end" width={5}>
<Color green>X</Color>
</Box>
);

t.is(output, ` ${chalk.green('X')}`);
});

test('column - align text to center', t => {
const output = renderToString(
<Box flexDirection="column" justifyContent="center" height={3}>
Expand Down

0 comments on commit 1f96300

Please sign in to comment.