voxal docs
SDK · CoreSDK · UI (React)

Styling

Colors, border styles, and flexbox layout for voxal terminal UIs

Styling a voxal UI is colors, borders, and flexbox layout. Colors apply to <Text> and <Box>, borders to <Box>, and layout to every <Box> through the same props Yoga gives the web. This page covers the formats and a few recipes.

Colors

The color, backgroundColor, and borderColor props (and the per-edge border colors) all accept the same color formats.

FormatExample
Named color'green', 'brightRed', 'redBright', 'default'
Hex'#0f0', '#00ff00'
RGB string'rgb(255, 128, 0)'
ANSI 256 string'ansi256(208)'
Palette index208 (a number 0 to 255)
RGB array[255, 128, 0]

The named colors are black, red, green, yellow, blue, magenta, cyan, white, and gray (also spelled grey), plus the bright variants written either way, like brightRed or redBright. 'default' resets to the terminal's own default.

<Text color="cyan">named</Text>
<Text color="#ff8800">hex</Text>
<Text color="rgb(255, 136, 0)">rgb</Text>
<Text color={[255, 136, 0]}>array</Text>
<Box backgroundColor="ansi256(236)" padding={1}>
  <Text>panel</Text>
</Box>

Downsampling

Not every terminal renders 24-bit color. The colors render option sets the output depth and downsamples everything you write to it:

ValueOutput
'truecolor'Full 24-bit color (default).
'256'The 256-color palette.
'16'The 16 standard ANSI colors.
'none'No color; styles like bold still apply.
serve(() => <App />, { colors: '256' });

Author in truecolor and let downsampling handle older terminals. You do not pick palette indices by hand unless you want to.

Border styles

Set borderStyle on a <Box> to one of these names:

NameLook
single┌─┐ │ └─┘
double╔═╗ ║ ╚═╝
round╭─╮ │ ╰─╯
bold┏━┓ ┃ ┗━┛
singleDoublesingle sides, double top and bottom
doubleSingledouble sides, single top and bottom
classic`+-+
arrowcorners drawn with arrows
<Box borderStyle="round" padding={1}>
  <Text>rounded</Text>
</Box>

You can also pass a custom object with the keys topLeft, top, topRight, right, bottomRight, bottom, bottomLeft, and left:

<Box
  borderStyle={{
    topLeft: '*', top: '-', topRight: '*', right: '|',
    bottomRight: '*', bottom: '-', bottomLeft: '*', left: '|',
  }}
  padding={1}
>
  <Text>custom border</Text>
</Box>

Color the border with borderColor (or per edge with borderTopColor and friends), dim it with borderDimColor, and drop edges with borderTop={false} and the other per-edge toggles. See Box borders.

Layout with flexbox

Layout is real flexbox, powered by Yoga. Every <Box> is a flex container, and you compose rows and columns by nesting boxes. The properties are the web's, applied to cells instead of pixels.

  • flexDirection sets the main axis: 'row' (default) lays children left to right, 'column' top to bottom.
  • justifyContent distributes children along the main axis: 'flex-start', 'center', 'flex-end', 'space-between', 'space-around'.
  • alignItems aligns children along the cross axis: 'flex-start', 'center', 'flex-end', 'stretch'.
  • gap puts space between children without adding it at the edges.
  • padding adds space inside the border; margin adds it outside.
  • width and height take cells (20), a percent of the parent ('50%'), or 'auto'.
  • flexGrow lets a box absorb free space; <Spacer /> is shorthand for flexGrow: 1.

Recipe: a centered box

Fill the viewport, then center on both axes.

function Centered({ children }) {
  const { columns, rows } = useWindowSize();
  return (
    <Box width={columns} height={rows} justifyContent="center" alignItems="center">
      <Box borderStyle="round" padding={1}>{children}</Box>
    </Box>
  );
}

Recipe: a two-column row

Two panels side by side. flexGrow splits the width; gap keeps them apart.

<Box gap={1}>
  <Box flexGrow={1} borderStyle="single" padding={1}>
    <Text>left</Text>
  </Box>
  <Box flexGrow={1} borderStyle="single" padding={1}>
    <Text>right</Text>
  </Box>
</Box>

A full-height column with a <Spacer /> that pushes the footer to the bottom.

function Layout() {
  const { rows } = useWindowSize();
  return (
    <Box flexDirection="column" height={rows}>
      <Box borderStyle="single" paddingX={1}>
        <Text bold>header</Text>
      </Box>
      <Box paddingX={1}>
        <Text>body content</Text>
      </Box>
      <Spacer />
      <Box paddingX={1}>
        <Text dimColor>footer</Text>
      </Box>
    </Box>
  );
}

Tip

For a deeper walkthrough of composing layouts, see the building UIs guide.

On this page