Component
Phui\Component, the attributes that declare its reactive members, and the nodes that mount it.
Component
abstract class Phui\Component
Extended by every component. Only build() is required.
Building
abstract build(): NodeReturns the component's node tree. Throws InvalidArgumentException if it returns a hidden node, since that would leave the component with nothing to render; wrap the component in Node::when() at its mount site instead.
bindings(): arrayReturns the component's Binding array — all of its keyboard, paste, click and scroll behaviour. Parents remap or suppress individual bindings per instance through bindings() on the component node.
isFocusable(): boolWhether the component takes part in focus traversal. A parent's focusable() on the mount node wins; otherwise the answer comes from canFocus().
canFocus(): boolWhether the component takes focus when the parent has no opinion. Returns $focusable by default; override it when focusability depends on the component's own state.
protected function canFocus(): bool
{
return ! $this->disabled;
}Lifecycle
onMount(): voidRuns once when the component is added to the tree, before its first build. Services and the runtime context are available, so initialise anything the first frame reads here — and start timers, fetches, or focus.
onRebuild(): voidRuns after the component rebuilds.
beforeUnmount(): voidRuns just before the component is removed from the tree.
Mounting
final static mount(?string $key = null): ComponentNodeReturns a ComponentNode that mounts this component.
UserList::mount()->props(users: $this->users)final static modal(?string $key = null): ModalNodeReturns a ModalNode that mounts this component in a layer above the rest of the tree.
Protected members
protected bool $focusable = falseWhether the component can take focus. Set it to true to opt in, or override canFocus() for a value that depends on the component's state.
protected private(set) Focus $focus
protected private(set) Timers $timers
protected private(set) System $system
protected private(set) Async $async
protected private(set) Themes $themes
protected private(set) Keymaps $keymapsThe runtime services, supplied by the framework.
final protected colours(string $class): objectReturns the colours object for $class: the one the parent set on this instance if there is one, otherwise the value resolved from the active Theme.
final protected get(string $class): mixedReturns the service registered on the Screen under $class. Throws MissingServiceException when nothing is registered.
final protected has(string $class): boolReturns whether a service is registered under $class.
final protected emit(string $event, mixed $data = null): voidEmits a named event with an optional payload, dispatched to any handler the parent registered on this instance with on().
Attributes
Classes in the Phui\Attributes namespace, applied to component properties.
#[State(bool $isDeep = false)]Marks a property as internal state. Writing to it schedules a rebuild. $isDeep compares nested array and object contents rather than the top-level value.
#[Prop(bool $isDeep = false)]Marks a property as owned by the parent and supplied through props().
#[Model(string $emit, bool $isDeep = false)]Marks a property as two-way bound. Writing to it emits the $emit event carrying the new value, for the parent to handle with on().
#[Ref]Marks an ElementRef property, which the framework creates and binds once the node carrying it renders.
ComponentNode
class Phui\Nodes\ComponentNode extends Node
Returned by mount().
props(mixed ...$props): staticSets the component's #[Prop] and #[Model] values, passed as named arguments.
on(
string $eventName,
Closure $handler,
?Closure $condition = null,
): staticRegisters a handler for an event the component emits. The handler receives the EmitEvent, whose data carries the payload. $condition gates whether the handler runs.
bindings(array $bindings): staticOverrides the component's own bindings for this instance. Overrides merge by signature — event, key and modifiers — and Binding::none() removes a default outright.
colours(object ...$colours): staticSets colours objects for this instance, taking precedence over the active theme.
requestFocus(): staticAsks the runtime to focus this component once it mounts.
focusable(bool $focusable = true): staticDecides focusability for this instance, overriding whatever the component decides for itself. false takes it out of tab traversal, so it never holds focus or receives keyboard input. Mouse input is positional and still reaches it.
Checkbox::mount()
->props(label: 'Ready', checked: $this->ready)
->focusable(false);ModalNode
final class Phui\Nodes\ModalNode extends ComponentNode
Returned by modal(). Adds the following to the ComponentNode surface.
interactable(bool $interactable = true): staticSets whether the modal receives input.
transparent(bool $transparent = true): staticSets whether the tree behind the modal shows through.
VirtualContainer
final class Phui\Nodes\VirtualContainer extends ElementNode implements ContainerNode
A container that builds only the rows currently in view.
static make(
Closure $builder,
int|Closure $itemCount,
?int $itemHeight = null,
?string $key = null,
): selfCreates a virtual container. $builder receives an index and returns that row. $itemHeight fixes every row to the same height; when it is null rows are measured, and each row must then be an element node rather than a component.
version(
int|string|null $version,
int|array|null $changed = null,
): staticMarks the backing data as changed so built rows are discarded. $changed limits the discard to the given indices.
Canvas
final class Phui\Nodes\Canvas extends ElementNode
An element drawn cell by cell.
static make(
int $width,
int $height,
?string $key = null,
): selfCreates a canvas of a fixed cell size.
draw(Closure $callback): staticSets the callback that paints the canvas, called with a Surface.
getWidth(): int
getHeight(): intReturn the canvas's cell dimensions.