Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/pocket-stack/pocketjs/llms.txt

Use this file to discover all available pages before exploring further.

@pocketjs/framework/components exports every UI building block available in PocketJS — from the four host primitives (View, Text, Image, Sprite) up through the app-shell components that handle focus, portals, modals, grids, lazy mounting, and full-screen paging. All components accept a ref callback that delivers the NodeMirror for imperative animation or focus control. Solid control-flow components (Show, For, Index, Switch, Match) are not exported here — import them directly from solid-js.

Host primitives

The four host primitives map directly to native node types in the Rust core. They are the only components that cross the JS/native boundary; every other component in this module is built from them.

View

The primary flex container and interactive hit-target. Use View for layout boxes, interactive tiles, and any element that needs focusable or onPress.
function View(props: ViewProps): JSX.Element
class
string
Tailwind-subset class literal compiled to a styleId at build time. Pass a single static string — dynamic concatenation defeats the compiler.
style
Record<string, number | string>
Inline spec props as an escape hatch for values that cannot be expressed as a compiled class (e.g. dynamic translateX, per-item opacity).
onPress
() => void
Fired when the user presses CIRCLE while this node (or a descendant) is focused. Bubbles up through ancestor nodes until a handler is found.
focusable
boolean
When true, joins the d-pad focus traversal order for the active focus scope. Required for a node to receive the focus: style variant.
ref
(node: NodeMirror) => void | NodeMirror
Callback that receives the NodeMirror immediately after the node is created. Also accepts a { current: NodeMirror | null } ref object.
children
JSX.Element
Child nodes. Any valid JSX expression — View, Text, Image, Sprite, or Solid control-flow components.

Text

Renders baked-font text. Text content is passed as children and must be a static string or a reactive string signal — PocketJS does not support rich inline formatting inside a single Text node.
function Text(props: TextProps): JSX.Element
class
string
Tailwind-subset class literal. Controls font slot, size, color, and alignment via compiled styles.
style
Record<string, number | string>
Inline spec props (escape hatch).
ref
(node: NodeMirror) => void | NodeMirror
Callback that receives the NodeMirror.
children
JSX.Element
The text content. Reactive — wrapping in a signal causes the native text node to update in place without recreating the node.

Image

Draws an uploaded texture by src key. The key is looked up in the renderer’s texture registry, which is populated from the pak at render() time.
function Image(props: ImageProps): JSX.Element
class
string
Tailwind-subset class literal. Controls size and position.
src
string
Asset name from the pak — the key stored as ui:img.<name> in the pack. Pass the bare name without the ui:img. prefix (e.g. "cover", not "ui:img.cover").
style
Record<string, number | string>
Inline spec props (escape hatch).
ref
(node: NodeMirror) => void | NodeMirror
Callback that receives the NodeMirror.

Sprite

An auto-playing animated sprite — a native primitive alongside View, Text, and Image. The sprite atlas (a pow2 texture holding a grid of frames) is baked into the pak, and the Rust core cycles frame cells per vblank — deterministic and with zero per-frame JS. A Sprite revealed by Show or Lazy starts animating immediately on display.
function Sprite(props: SpriteProps): JSX.Element
class
string
Tailwind-subset class literal.
sprite
string
Sprite-atlas key: the ui:sprite.<name> entry baked into the pak. Pass the bare name (e.g. "cover" for ui:sprite.cover). Bake atlases by listing them in the demo’s sprites.json with { cols, rows, frames, step }step is vblanks per frame (fps = 60/step).
style
Record<string, number | string>
Inline spec props (escape hatch).
ref
(node: NodeMirror) => void | NodeMirror
Callback that receives the NodeMirror.

App-shell components

The following components are built on top of the host primitives and cover common UI patterns: full-screen roots, focus management, portalled overlays, modals, grids, and galleries.

Screen

A full-screen root View. Defaults class to "relative flex-col w-full h-full bg-slate-50 overflow-hidden" when none is given, making it a sensible starting point for any page.
interface ScreenProps extends ViewProps {}
function Screen(props: ScreenProps): JSX.Element
ScreenProps inherits every prop from ViewProps. Override class to apply a custom background or flex direction.

Focusable

A View with focusable: true pre-set. Use it for any interactive tile that should be reachable via d-pad navigation.
interface FocusableProps extends ViewProps {
  onPress?: () => void;
}
function Focusable(props: FocusableProps): JSX.Element
onPress
() => void
Fired on CIRCLE while this node is focused.
All other ViewProps props are forwarded to the underlying View.

FocusScope

Restricts d-pad traversal and CIRCLE to its subtree while active (default true). Backed by pushFocusScope from @pocketjs/framework/input. Use FocusScope in any dialog, panel, or section that should capture all input while visible.
interface FocusScopeProps extends ViewProps, FocusScopeOptions {
  active?: boolean | (() => boolean);
}
function FocusScope(props: FocusScopeProps): JSX.Element
active
boolean | (() => boolean)
When true (default), the scope is pushed and d-pad navigation is restricted to this subtree. Accepts a reactive getter — the scope is pushed/popped reactively.
autoFocus
boolean
Focus the first focusable child when the scope activates. Defaults to true inside pushFocusScope.
restoreFocus
boolean
Restore the previously focused node when the scope is popped. Defaults to true inside pushFocusScope.
All ViewProps props are forwarded to the underlying View.

FocusGrid

Gives its subtree explicit row/column d-pad semantics while active. Requires columns; wrap (default false) wraps at row ends. Backed by pushFocusGrid.
interface FocusGridProps extends ViewProps, FocusGridOptions {
  active?: boolean | (() => boolean);
}
function FocusGrid(props: FocusGridProps): JSX.Element
active
boolean | (() => boolean)
When true (default), the grid traversal is active. Accepts a reactive getter.
columns
number
required
Number of columns for row/column d-pad routing. Drives traversal only — visible column count emerges from tile widths vs. container width.
wrap
boolean
When true, focus wraps at row ends rather than clamping. Defaults to false.
All ViewProps props are forwarded to the underlying View.

ActionHandler

Declarative wrapper over onButtonPress: fires onPress on the button edge. Renders children (or nothing). Use it to colocate button bindings with the UI they drive.
interface ActionHandlerProps extends ButtonPressOptions {
  button: number;
  onPress: (pressed: number, buttons: number) => void;
  children?: JSX.Element;
}
function ActionHandler(props: ActionHandlerProps): JSX.Element
button
number
required
BTN constant or bitmask to listen for. Imported from @pocketjs/framework/input.
onPress
(pressed: number, buttons: number) => void
required
Callback fired on button-down. pressed is the just-pressed bitmask; buttons is the full held mask.
allowWhenBlocked
boolean
When true, this handler fires even while a modal or system block owns input. Defaults to false.
active
boolean | (() => boolean)
Gate the handler. When false, the handler is suppressed. Defaults to true.
children
JSX.Element
Optional children rendered inline. The component renders null when omitted.

Portal

Renders children into the full-screen overlay root (above the app layer, zIndex 1000) instead of the local tree. Cleans up its host node on unmount.
interface PortalProps {
  children?: JSX.Element | (() => JSX.Element);
}
function Portal(props: PortalProps): JSX.Element
children
JSX.Element | (() => JSX.Element)
Content to render into the overlay. Accepts a factory function for deferred evaluation (used internally by Modal).

A portalled backdrop plus a focus-scoped panel. While open, it blocks background button handlers via pushButtonHandlerBlock and fades/scales the panel in. Use Modal for dialogs, confirmation prompts, or any overlay that should capture all input.
interface ModalProps {
  class?: string;
  panelClass?: string;
  open?: boolean | (() => boolean);
  children?: JSX.Element;
}
function Modal(props: ModalProps): JSX.Element
open
boolean | (() => boolean)
When true, the modal is visible and blocks background input. Accepts a reactive getter.
class
string
Class for the centering frame. Defaults to "absolute inset-0 z-50 flex-col items-center justify-center".
panelClass
string
Class for the panel itself. Defaults to "flex-col gap-2 w-[328] p-3 rounded-xl shadow-lg bg-white border-slate-200".
children
JSX.Element
Content rendered inside the panel.

ActionBar

A portalled bottom bar rendered above the app layer. Defaults to a pinned left-3 right-3 bottom-3 row of button hints when no class is given.
interface ActionBarProps extends ViewProps {}
function ActionBar(props: ActionBarProps): JSX.Element
All ViewProps props are forwarded. Override class to reposition or restyle the bar. Rendered via Portal into the overlay root.

Grid

A wrapping tile layout (flex-row flex-wrap). With columns and active, it delegates row/column d-pad traversal to FocusGrid; columns drives traversal only — layout stays flexbox. Pass gap as a number so class can remain a single compiled literal.
interface GridProps extends ViewProps, Partial<FocusGridOptions> {
  gap?: number;
  active?: boolean | (() => boolean);
}
function Grid(props: GridProps): JSX.Element
gap
number
Cross-axis gap in px, applied via the style object so class stays a single static literal.
columns
number
Grid column count for FocusGrid traversal. When omitted, the component renders as a plain View with no traversal.
wrap
boolean
Wrap focus at row ends. Forwarded to FocusGrid. Defaults to false.
active
boolean | (() => boolean)
Enable FocusGrid d-pad traversal. Requires columns. Accepts a reactive getter.
All other ViewProps props are forwarded to the underlying View or FocusGrid.

Lazy

On-demand mount: builds children only while when is truthy. The end-of-frame sweep destroys the subtree when when goes false. reveal shows fallback for N frames the first time the subtree activates, then latches revealed for its lifetime — no replay on re-activation. There is no per-frame work when reveal is 0.
interface LazyProps {
  when: boolean | (() => boolean);
  reveal?: number;
  fallback?: JSX.Element | (() => JSX.Element);
  children: () => JSX.Element;
}
function Lazy(props: LazyProps): JSX.Element
when
boolean | (() => boolean)
required
Mount the content while truthy; destroy when false.
reveal
number
Host frames to show fallback before revealing children the first time the component activates. Defaults to 0 (immediate). Simulates an asset/decode delay — textures are uploaded eagerly at pak load, so this models on-demand content build, not texture residency.
fallback
JSX.Element | (() => JSX.Element)
Shown during the reveal delay. A spinner, skeleton, or placeholder.
children
() => JSX.Element
required
Deferred content factory — only called once when is truthy AND the reveal delay has elapsed.

A horizontally paged, full-screen strip. Pressing LTRIGGER / RTRIGGER slides one whole screen at a time. The slide is a single native translateX tween per press — paint-only, no relayout. Pages outside the mount window are not built, keeping many-page galleries inside the PSP draw budget.
interface GalleryProps {
  count: number;
  page: () => number;
  onPageChange?: (next: number) => void;
  renderPage: (index: number) => JSX.Element;
  window?: number;
  duration?: number;
  easing?: EasingName;
  bindTriggers?: boolean;
  wrap?: boolean;
  class?: string;
}
function Gallery(props: GalleryProps): JSX.Element
count
number
required
Total number of pages.
page
() => number
required
Controlled current-page accessor (0-based). Reactive — the strip slides whenever this value changes.
onPageChange
(next: number) => void
Called with the next page index when LTRIGGER/RTRIGGER is pressed. Update the signal driving page here.
renderPage
(index: number) => JSX.Element
required
Page factory. Only called for pages inside the mount window.
window
number
Pages kept mounted on each side of the current page. Defaults to 1. Increase to pre-build adjacent pages; decrease to 0 to build only the current page.
duration
number
Slide animation duration in ms. Defaults to 300.
easing
EasingName
Slide easing curve. Defaults to "out". See EasingName in the Animation API.
bindTriggers
boolean
Bind LTRIGGER/RTRIGGER to page(-1/+1) internally. Defaults to true. Set to false to drive paging entirely from onPageChange.
wrap
boolean
Wrap past the ends instead of clamping. Defaults to false.
class
string
Override the outer viewport class. The outer node must remain untransformed — the scissor for overflow-hidden is taken from its world box, so it must not move.

Build docs developers (and LLMs) love