Ink: Table example

Created on 25 Apr 2019  路  9Comments  路  Source: vadimdemedes/ink

Hi,

I mentioned this on Twitter, but I'd really love to see an example of displaying tabular data with Ink.

I've figured out how to get tabular columns aligned using flexBasis/minWidth, but it's a hack--I have to find the max string length of all table headers and data in table cells (for each column), then share this number among each cell in the column & the associated header.

e.g. (pseudo-jsx):

<!-- colSizes must be manually computed -->
<Box flexDirection="column">
  <Box>
    <Box flexBasis={colSize[0]}>HeaderA</Box>
    <Box flexBasis={colSize[1]}>HeaderB</Box>  
    <Box flexBasis={colSize[2]}>HeaderC</Box>  
  </Box>
  <Box>
    {rows.map(row => (
      <Box flexBasis={colSize[0]}>{row[0]}</Box>
      <Box flexBasis={colSize[1]}>{row[1]}</Box>
      <Box flexBasis={colSize[2]}>{row[2]}</Box>
    ))}
  </Box>
</Box>

My feeling is that <Box> is perhaps not well-suited to this task, but could be wrong--I'm inexperienced with both React and flexbox.

question

Most helpful comment

One thing you could do is split up into columns manually, e.g. left, middle, right arrays, then render them into separate <Box flexDirection="column"> and wrap that whole thing into a <Box flexDirection="row">

import React from "react";
import { render, Box, Text, Color } from "ink";

const left = ["Rule", "cpu usage", "library-mismatch", "long-timeout"];
const middle = ["ID", "id 1", "id 2", "id 3"];
const right = [
  "Description",
  "description 1",
  "description 2",
  "description 3"
];

function App() {
  return (
    <Box flexDirection="row">
      <Box flexDirection="column">
        {left.map((e, i) => {
          if (i === 0) return <Text underline>{e}</Text>;

          return <Color blue>{e}</Color>;
        })}
      </Box>
      <Box flexDirection="column" paddingX={1}>
        {middle.map((e, i) => {
          if (i === 0) return <Text underline>{e}</Text>;

          return <Text>{e}</Text>;
        })}
      </Box>
      <Box flexDirection="column">
        {right.map((e, i) => {
          if (i === 0) return <Text underline>{e}</Text>;

          return (
            <Color yellow underline>
              {e}
            </Color>
          );
        })}
      </Box>
    </Box>
  );
}

render(<App />);

image

I don't know if that's something that should be encouraged, but it works at least 馃檪

All 9 comments

Try <Box flex={1} textWrap="wrap">Text</Box> for each of your cells and see if that works.

That doesn't seem to align any columns.

Here's the real code:

    <Box flexDirection="column">
      <Box>
        {HEADERS.map(header => (
          <Box key={header} flex={1} marginRight={1}>
            <Color underline>{header}</Color>
          </Box>
        ))}
      </Box>
      <Box flexDirection="column">
        {rows.map(row => (
          <Box key={row.id}>
            <Box marginRight={1} flex={1}>
              <Color blue>{row.id}</Color>
            </Box>
            <Box textWrap="wrap" flex={1}>
              {row.meta.docs.description}
              <Box marginLeft={1}>
                <Link url={row.meta.docs.url}>
                  (<Color yellow>docs</Color>)
                </Link>
              </Box>
            </Box>
          </Box>
        ))}
      </Box>
    </Box>

output:

image

One thing you could do is split up into columns manually, e.g. left, middle, right arrays, then render them into separate <Box flexDirection="column"> and wrap that whole thing into a <Box flexDirection="row">

import React from "react";
import { render, Box, Text, Color } from "ink";

const left = ["Rule", "cpu usage", "library-mismatch", "long-timeout"];
const middle = ["ID", "id 1", "id 2", "id 3"];
const right = [
  "Description",
  "description 1",
  "description 2",
  "description 3"
];

function App() {
  return (
    <Box flexDirection="row">
      <Box flexDirection="column">
        {left.map((e, i) => {
          if (i === 0) return <Text underline>{e}</Text>;

          return <Color blue>{e}</Color>;
        })}
      </Box>
      <Box flexDirection="column" paddingX={1}>
        {middle.map((e, i) => {
          if (i === 0) return <Text underline>{e}</Text>;

          return <Text>{e}</Text>;
        })}
      </Box>
      <Box flexDirection="column">
        {right.map((e, i) => {
          if (i === 0) return <Text underline>{e}</Text>;

          return (
            <Color yellow underline>
              {e}
            </Color>
          );
        })}
      </Box>
    </Box>
  );
}

render(<App />);

image

I don't know if that's something that should be encouraged, but it works at least 馃檪

We can use ink-table for render a table. I have already submitted the migration pull request (https://github.com/maticzav/ink-table/pull/31).

ink-table 2.0 released.

Having learned a little bit about flexbox and CSS grid, it would seem to me that CSS grid would be a more appropriate abstraction for tables. But this seems like it'd be a significant implementation.

CSS grid is probably far off: https://github.com/facebook/yoga/issues/867. It would be sweet though 馃榾

Any news of this, at least an estimated date ?, some year? XD

Was this page helpful?
0 / 5 - 0 ratings