Skip to main content

Control props

Common layout and styling properties shared by all components.

The library uses a flexbox-based layout system. You compose UIs by nesting Panel containers and letting the engine compute positions and sizes from flexDirection, gap, padding, flex, etc. To overlay an element use position={'absolute'} with top / left / right / bottom.

Props​

Sizing​

PropTypeDefaultDescription
widthnumber | Percent (e.g. 200 or '50%')—Width in pixels or as a percentage of the parent's content box. Omit to derive from content / flex rules
heightnumber | Percent—Height in pixels or as a percentage of the parent's content box. Omit to derive from content / flex rules
minWidth / minHeight / maxWidth / maxHeightnumber | Percent—Lower / upper bounds the layout engine will respect when sizing the element
aspectRationumber (width ÷ height)—Derives whichever axis you left auto from the one that is definite. Ignored when both width and height are set

Positioning​

PropTypeDefaultDescription
position'absolute' | 'relative''relative''relative' participates in flex flow. 'absolute' is removed from flow and positioned with top / left / right / bottom relative to the nearest positioned parent
top / right / bottom / leftnumber—Edge offsets used when position={'absolute'}. Setting both left and right without an explicit width stretches the element horizontally; same for top + bottom and height
zIndexnumber0Draw order, in a container screen only. There it becomes the control's baked layer, so a higher zIndex draws on top. A server form has no per-element layer — JSON UI cannot bind one, and its cells draw in fixed per-kind bands (a background below, a Button above it, Text above that) — so zIndex has no effect in a form
display'flex' | 'none''flex''none' removes the element from layout entirely — siblings collapse to fill the gap. Different from visible={false} which hides the element but keeps its space

Flex container props​

These apply to a component that contains children.

PropTypeDefaultDescription
flexDirection'row' | 'row-reverse' | 'column' | 'column-reverse''column'Main axis direction for child layout
wrap'nowrap' | 'wrap' | 'wrap-reverse''nowrap'Whether children wrap onto multiple lines
justifyContent'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly''flex-start'Alignment of children along the main axis
alignItems'flex-start' | 'flex-end' | 'center' | 'stretch''stretch'Alignment of children along the cross axis
alignContent'flex-start' | 'flex-end' | 'center' | 'stretch' | 'space-between' | 'space-around'—Alignment of multiple lines when wrap is enabled
gap / rowGap / columnGapnumber | Percent—Space between children. gap sets both axes

Flex item props​

These apply to a component as a child inside a flex container.

PropTypeDefaultDescription
flexnumber—Shorthand for flexGrow
flexGrownumber0How much of the remaining space the item claims
flexShrinknumber1How much the item shrinks when space is tight
flexBasisnumber | Percent | 'auto''auto'Initial size before flex growing/shrinking
alignSelf'auto' | 'flex-start' | 'flex-end' | 'center' | 'stretch''auto'Overrides the parent's alignItems for this item only

Spacing​

PropTypeDefaultDescription
padding / paddingTop / paddingRight / paddingBottom / paddingLeftnumber | Percent—Inner spacing in texels or as a percentage of the parent's content-box width
margin / marginTop / marginRight / marginBottom / marginLeftnumber | Percent—Outer spacing in texels or as a percentage of the parent's content-box width

Appearance​

PropTypeDefaultDescription
backgroundstring (resource-pack texture path, e.g. 'textures/ui/my_panel')none — nothing is drawn behind the elementResource-pack texture drawn behind the element, filling its computed layout box. It sits below the element's own content and its children, so a plain Panel can be given a surface without wrapping it in a themed component. Left unset, no background layer is drawn at all
Stateful surfaces

Interactive primitives (Button, the Form.* fields) extend background with per-state variants — backgroundHover, backgroundPressed, backgroundLocked. Each falls back to background, which itself falls back to the unstyled placeholder texture, so those components always draw something. See the individual component pages for the state props they support.

Visibility props​

PropTypeDefaultDescription
visiblebooleantrueWhether the element is drawn. false removes it and its children entirely, but keeps the space it was laid out in. Use display={'none'} to remove it from layout too
enabledbooleantrueWhether the control accepts input. Set per element
liveVisiblebooleanfalseCarry visible on a compiled screen whether or not the build's liveness probe sees it flip. The conditional sugar sets it on every {cond && <X/>} it rewrites; set it by hand for a visible that is false in every state the probe tries

Conditional rendering​

A compiled screen's shape is frozen, so a branch that adds or drops an element cannot be a runtime decision. The build rewrites the two React idioms into a carried visible instead, at source level, so what you write stays idiomatic:

{isAdmin && <Button onPress={ban}><Text>{'Ban'}</Text></Button>}

becomes <Button visible={isAdmin} liveVisible …>. An element ternary becomes both branches with opposite visible:

{online ? <Text>{'Online'}</Text> : <Text>{'Offline'}</Text>}

Both are constructed and both share the same space, so position them accordingly — a stack is usually what you want, since only the shown one then takes room. The rewrite also marks the element liveVisible, so the visibility is carried whether or not the build's probe happens to flip it.

This applies only when each branch is a single element or nullish. A string or fragment branch stays an ordinary runtime conditional, which a compiled screen refuses as a shape change — wrap a conditional string in a <Text> instead:

<Text>{online ? 'Online' : 'Offline'}</Text>

Examples​

Stacked column​

<Panel padding={10} gap={8}>
<Text>{'Title'}</Text>
<Text>{'Body text'}</Text>
</Panel>

Row of buttons​

<Panel flexDirection={'row'} padding={10} gap={8}>
<Button flex={1}>
<Text>{'Cancel'}</Text>
</Button>
<Button flex={1}>
<Text>{'Confirm'}</Text>
</Button>
</Panel>

Centered content​

<Panel width={300} height={200} justifyContent={'center'} alignItems={'center'}>
<Text>{'Centered'}</Text>
</Panel>

Visibility control​

function ConditionalUI({ showButton }: { showButton: boolean }) {
return (
<Panel padding={10} gap={8}>
<Text>{'Some text'}</Text>
<Button visible={showButton}>
<Text>{'Optional Button'}</Text>
</Button>
</Panel>
);
}

display none vs visible​

{/* visible={false} keeps the space reserved */}
<Button visible={false}>
<Text>{'Hidden'}</Text>
</Button>

{/* display={'none'} removes from layout — siblings collapse */}
<Button display={'none'}>
<Text>{'Removed'}</Text>
</Button>

Absolute positioning​

<Panel width={300} height={200}>
<Text>{'Main content'}</Text>
{/* Pinned to top-right, outside normal flow */}
<Panel position={'absolute'} top={4} right={4}>
<Text>{'Close'}</Text>
</Panel>
</Panel>

Visibility vs display​

visible={false}display={'none'}
Space reservedYesNo
Children executedYesNo
Use caseHide visuallyRemove from layout

TypeScript​

import type { ControlProps, LayoutProps } from '@bedrock-core/ui';

LayoutProps carries the flex layout properties; ControlProps extends it with visible, enabled, and background. Every built-in component's props type extends ControlProps. Individual types are also exported:

import type {
FlexDirection, FlexSize, FlexWrap,
JustifyContent, AlignItems, AlignContent, AlignSelf,
Display, Position, Spacing,
} from '@bedrock-core/ui';

The underlying primitives (Percent, FlexStyle, …) live in the flexbox entry point:

import type { Percent, FlexStyle } from '@bedrock-core/ui/flexbox';