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.
| Format | Example |
|---|---|
| Named color | 'green', 'brightRed', 'redBright', 'default' |
| Hex | '#0f0', '#00ff00' |
| RGB string | 'rgb(255, 128, 0)' |
| ANSI 256 string | 'ansi256(208)' |
| Palette index | 208 (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:
| Value | Output |
|---|---|
'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:
| Name | Look |
|---|---|
single | ┌─┐ │ └─┘ |
double | ╔═╗ ║ ╚═╝ |
round | ╭─╮ │ ╰─╯ |
bold | ┏━┓ ┃ ┗━┛ |
singleDouble | single sides, double top and bottom |
doubleSingle | double sides, single top and bottom |
classic | `+-+ |
arrow | corners 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.
flexDirectionsets the main axis:'row'(default) lays children left to right,'column'top to bottom.justifyContentdistributes children along the main axis:'flex-start','center','flex-end','space-between','space-around'.alignItemsaligns children along the cross axis:'flex-start','center','flex-end','stretch'.gapputs space between children without adding it at the edges.paddingadds space inside the border;marginadds it outside.widthandheighttake cells (20), a percent of the parent ('50%'), or'auto'.flexGrowlets a box absorb free space;<Spacer />is shorthand forflexGrow: 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>Recipe: header, body, footer
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.