Base props

Every node accepts these, whatever component it names. A component page lists what that component adds; this is the set underneath all of them.

import { Panel } from '@textui/core';

<Panel
  title="Services"
  padding={1}
  gap={1}
  border="single"
  focusable
  label="service list"
  onKey={(event) => event.name === 'r' && void app.execute('services.refresh')}
/>

Four things are worth knowing before the tables.

Style arrives three ways

The same declaration can be written inline, as an object, or as a stateful map, and they compose rather than compete:

<>
  <box gap={1} padding={1} border="single" />
  <box style={{ gap: 1, padding: 1 }} />
  <box style={{ base: { fg: 'muted' }, focus: { fg: 'accent', bold: true } }} />
</>

Inline keys are the convenience form for the common case. Reach for style when a value is stateful - base / focus / disabled - or when it is computed and passing twenty props would be worse than passing one object.

label and role are not decoration

They are what the test harness queries by, and what future accessibility work will read. A node with an interactive role is focusable without saying so:

<box role="button" label="Restart the server" onClick={() => {}} />

That is a working button - focusable, in the tab order, named - without importing Button. Button exists because it also draws a ring, states a tone, and inverts when focused.

onKey normally needs focus

A handler runs while its node is focused. global opts out of that, for a node that wants the keys its children decline:

<box global onKey={(event) => event.name === 'escape'} />

Use it for a wrapper - a dropdown taking left and right while the menu inside keeps up and down. Everywhere else, focus is what decides who gets a key, and global throws that away.

breakpoints are per node, not per screen

A node renders compact below the first width and minimal below the second. The widths are its own, not the terminal’s, so a panel in a narrow column degrades while the same component in the main pane does not.

The tables

BaseProps

Props every node accepts. Style arrives three ways on purpose: the full style object for anything stateful, a merged list for composition, and the individual style keys inline as convenience props - <box gap={1} border="single"> rather than <box style={{ gap: 1, border: 'single' }}> for the common case.

Prop Type  
id string  
key string \| number  
style StyleInput  
role SemanticRole Semantic metadata. Drives the test harness, and future a11y work.
label string  
description string  
disabled boolean  
selected boolean  
focusable boolean Participates in tab order. Implied by an interactive role.
focusScope string The focus scope this node belongs to.
autoFocus boolean  
global boolean onKey runs whether or not this node is focused. For a node that wraps something else and wants the keys that thing declines - a dropdown panel taking left and right while the menu inside it keeps up and down. Without this a handler only runs while focused, which is what focus means.
onKey (event: KeyEvent) => boolean \| void  
onFocus () => void  
onBlur () => void  
onMouse (event: MouseEvent) => boolean \| void  
onClick Action \| ((event: MouseEvent) => void)  
onHover (hovering: boolean) => void  
link string OSC 8 link target, where the terminal supports hyperlinks.
breakpoints { compact?: number; minimal?: number } Below this width the node renders compact; below that, minimal.

BoxProps

Prop Type  
children unknown  
title string Header text drawn into the top border. Needs a border to land on.
titleAlign 'left' \| 'center' \| 'right'  
footer string Footer text drawn into the bottom border.
footerAlign 'left' \| 'center' \| 'right'  
scrollTop number Scroll offset in cells, when overflow is ‘scroll’.
scrollLeft number  

TextProps

Prop Type  
children unknown  
content string The string to draw. children is accepted as a shorthand.
truncate 'end' \| 'start' \| 'middle' \| false Where to cut when the text does not fit.
ellipsis string  

CanvasProps

Prop Type  
draw (surface: PaintSurface, ctx: RenderContext) => void Paint directly. The escape hatch charts and gauges use; everything else should compose box and text so the layout engine can reason about it.
intrinsic { width?: number; height?: number } Intrinsic size when the style does not fix one.

SpacerProps

| Prop | Type | | | — | — | — | | size | number | |


Back to top

MIT licensed. Pre-1.0 - the surface is still moving.