Panel
<Panel slot> draws a pane in one of the screen’s nine slots: the four corners, the four edges and the centre. A Panel names a slot and an order, never a position. Each slot stacks its Panels in a column, so two Panels never overlap.
Its props are in PanelProps.
A slot Panel sits inside a Hud, which carries it to the screen.
import { Hud, Panel, Slot, Text } from "@spawnite/engine";
export function Readout({ coins, round }: { coins: number; round: number }) { return ( <Hud> <Panel slot={Slot.TopRight} order={1}> <Text>Coins {coins}</Text> </Panel> <Panel slot={Slot.TopRight} order={2}> <Text>Round {round}</Text> </Panel> </Hud> );}A Panel is glass by default, as Unity’s Panel and Godot’s PanelContainer draw a background. PanelVariant.Bare stacks its children with no pane, as Godot’s VBoxContainer does, so a Button in a bare Panel is not glass on glass.
A slot Panel inside an Entity stays in its slot and reads the entity; it does not follow it. That is screen UI, like Unity’s screen-space canvas or Roblox’s ScreenGui. A Panel that follows its entity in the world is anchored.
The Slot members are TopLeft, Top, TopRight, Left, Center, Right, BottomLeft, Bottom and BottomRight.
A Panel that frees the cursor
Section titled “A Panel that frees the cursor”freeCursor frees the cursor while the Panel shows, so a player clicks its controls under a camera that captures the cursor, as in a shooter. The camera takes the cursor back once the Panel goes. Use it for a screen the player stops to click, such as an inventory or a shop, as Roblox’s Modal button does. A readout leaves it off, the default, so it never takes the mouse from the camera. The camera page says what the player sees and how the lock comes back.
import { Button, Hud, Panel, Slot, Text } from "@spawnite/engine";
export function Shop({ onBuy }: { onBuy: () => void }) { return ( <Hud> <Panel slot={Slot.Center} freeCursor> <Text>A sword, 30 coins</Text> <Button onPress={onBuy}>Buy</Button> </Panel> </Hud> );}Anchored
Section titled “Anchored”<Panel anchor> follows the entity it sits in, like Roblox’s BillboardGui. It sits inside an Entity directly, with no Hud, and reads the entity through useEntity(). The screen layer always draws over it, so a nameplate slides under a slot Panel.
Its props are also in PanelProps, and Anchor says where it stands.
For meshes rather than HTML, such as a marker drawn in the scene, a Billboard faces the camera from every side of its entity. A health bar over an entity is a <ResourceBar> in an anchored Panel, as the Health page shows.
An anchored Panel takes the same variant, className and style as a slot Panel; style is for a size that comes from data, never a position, which the slot or the anchor gives. It takes no pointer events itself, so a drag across a nameplate still turns the camera.
import { Anchor, Bar, HealthTrait, Panel, Text, useEntity,} from "@spawnite/engine";import { useTrait } from "koota/react";
export function Nameplate() { const health = useTrait(useEntity(), HealthTrait); if (!health) return null;
return ( <Panel anchor={Anchor.Above} maxDistance={40}> <Text>Yeti</Text> <Bar label="Yeti health" value={health.current} maximum={health.maximum} /> </Panel> );}