# Components

> Box, Text, Newline, Spacer, Static, and Transform, the building blocks of a voxal UI

The UI layer ships six components, all imported from `@voxalsh/sdk/ui`. `<Box>` lays out the screen with flexbox and `<Text>` styles inline text. The rest are small helpers for spacing, append-only output, and post-processing. They match Ink one to one.

```jsx

```

## Box

`<Box>` is a flexbox container. It is the only layout primitive: you nest boxes to build rows, columns, and grids, and you size, space, and border them with props. A box never holds text directly; put text in a `<Text>` child.

```jsx
<Box flexDirection="column" borderStyle="round" padding={1} gap={1}>
  <Text bold>Dashboard</Text>
  <Box gap={2}>
    <Text>left</Text>
    <Text>right</Text>
  </Box>
</Box>
```

### Layout props

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `flexDirection` | `'row' \| 'column' \| 'row-reverse' \| 'column-reverse'` | `'row'` | Main axis direction. |
| `flexWrap` | `'nowrap' \| 'wrap' \| 'wrap-reverse'` | `'nowrap'` | Whether children wrap onto new lines. |
| `alignItems` | flex value | | Cross axis alignment of children. |
| `alignSelf` | flex value | | Override the parent's `alignItems` for this box. |
| `alignContent` | flex value | | Alignment of wrapped lines. |
| `justifyContent` | flex value | | Main axis distribution of children. |
| `flexGrow` | `number` | `0` | Share of free space this box takes. |
| `flexShrink` | `number` | `1` | How much this box shrinks when space is tight. |
| `flexBasis` | `number \| string` | | Initial main axis size before grow/shrink. |

### Size props

`width`, `height`, `minWidth`, `minHeight`, `maxWidth`, `maxHeight`. A number means cells, a string like `'50%'` means percent of the parent, and `'auto'` is allowed. `aspectRatio` (a number) locks the width to height ratio.

```jsx
<Box width="50%" height={10} minWidth={20}>
  <Text>half the parent, ten rows tall</Text>
</Box>
```

### Spacing props

All spacing is in cells. Padding adds space inside the border, margin outside it.

- Padding: `padding`, `paddingX`, `paddingY`, `paddingTop`, `paddingBottom`, `paddingLeft`, `paddingRight`.
- Margin: `margin`, `marginX`, `marginY`, `marginTop`, `marginBottom`, `marginLeft`, `marginRight`.
- Gap between children: `gap`, `columnGap`, `rowGap`.

### Position props

`position` (`'relative'`, `'absolute'`, or `'static'`) with `top`, `bottom`, `left`, `right`. Use `'absolute'` to overlay a box on top of its siblings.

### Display and overflow

`display` (`'flex'` or `'none'`; `'none'` removes the box from layout). `overflow`, `overflowX`, `overflowY` (`'visible'` or `'hidden'`; clip children that exceed the box).

### Borders

| Name | Type | Description |
| --- | --- | --- |
| `borderStyle` | name or object | A named style (`single`, `double`, `round`, ...) or a custom box-drawing object. See [Styling](/sdk/ui/styling#border-styles). |
| `borderColor` | color | Color of all border edges. |
| `borderTopColor` `borderRightColor` `borderBottomColor` `borderLeftColor` | color | Per-edge border color. |
| `borderTop` `borderRight` `borderBottom` `borderLeft` | `boolean` | Toggle an edge. Default `true`; set `false` to drop that edge. |
| `borderDimColor` | `boolean` | Dim the border. |
| `borderBackgroundColor` | color | Background color behind the border characters. |

### Background

`backgroundColor` fills the box. Descendant `<Text>` elements inherit it unless they set their own.

<Callout>
`aria-*` props are accepted but ignored. There is no screen reader over SSH.
</Callout>

## Text

`<Text>` is styled inline text. It is the only component that renders characters. Nest `<Text>` inside `<Text>` to mix styles on one line.

```jsx
<Text>
  status: <Text color="green" bold>ok</Text> <Text dimColor>(updated now)</Text>
</Text>
```

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `color` | color | | Foreground color. |
| `backgroundColor` | color | | Background color. Inherited from an ancestor `<Box backgroundColor>`. |
| `dimColor` | `boolean` | `false` | Render at reduced intensity. |
| `bold` | `boolean` | `false` | Bold weight. |
| `italic` | `boolean` | `false` | Italic. |
| `underline` | `boolean` | `false` | Underline. |
| `strikethrough` | `boolean` | `false` | Strikethrough. |
| `inverse` | `boolean` | `false` | Swap foreground and background. |
| `wrap` | `'wrap' \| 'truncate' \| 'truncate-start' \| 'truncate-middle' \| 'truncate-end' \| 'hard'` | `'wrap'` | How text that exceeds its width is handled. |

If `children` is `null` or `undefined`, `<Text>` renders nothing, so `{cond && <Text>...</Text>}` is always safe.

See [Styling](/sdk/ui/styling) for color formats.

## Newline

A line break, for use inside `<Text>`.

```jsx
<Text>
  line one<Newline />line two<Newline count={2} />and a gap above this
</Text>
```

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `count` | `number` | `1` | Number of line breaks to insert. |

`<Newline>` must be used inside `<Text>`.

## Spacer

`<Spacer />` takes no props and is equivalent to `<Box flexGrow={1} />`. It expands to fill free space, pushing its siblings apart along the parent's main axis.

```jsx
<Box>
  <Text>left</Text>
  <Spacer />
  <Text>right</Text>
</Box>
```

In a `column` parent, `<Spacer />` pushes content to the top and bottom, which is how you pin a footer.

## Static

`<Static>` renders an array of items once, permanently, above the live region. The items scroll into the terminal's scrollback and are never repainted, which makes it ideal for append-only output: logs, chat history, completed tasks. Only ever add to the array; do not mutate items already rendered.

```jsx
<Static items={messages}>
  {(message, index) => (
    <Box key={message.id}>
      <Text color="green" bold>{message.role}</Text>
      <Text>{'  '}{message.text}</Text>
    </Box>
  )}
</Static>
```

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `items` | `array` | | The list to render. New entries are appended; existing ones are never re-rendered. |
| `children` | `(item, index) => ReactElement` | | Renders one item. Give each a stable `key`. |
| `style` | Box style | | Optional style object applied to the wrapping box. |

<Callout type="warn">
`Static` output is emitted in inline mode, not the fullscreen alternate screen. Pair it with an inline live region (the default), as in the [chat app guide](/guides/chat-app).
</Callout>

## Transform

`<Transform>` post-processes the rendered output of its `<Text>` children, one line at a time. The `transform` function receives each rendered line and its index and returns the replacement string. Use it for effects that are easier to express on the final string than as components, such as gradients or line numbering.

```jsx
<Transform transform={(line, index) => `${index + 1}  ${line}`}>
  <Text>first</Text>
  <Text>second</Text>
</Transform>
```

| Name | Type | Description |
| --- | --- | --- |
| `transform` | `(line: string, index: number) => string` | Maps each rendered line to its output. |

Like `<Text>`, `<Transform>` returns nothing if its children are `null` or `undefined`.

---

Source: https://docs.voxal.sh/sdk/ui/components
