Surfaces
A surface is a place your module renders. Each surface in the manifest pairs with a register* call in
your code (matched by id, or by kind for windows). Each surface renders in its own iframe.
| Kind | Where it appears | Manifest extras |
|---|---|---|
widget | Floating, draggable; snaps to 8 screen zones, reorders within a stack, pins. | gated:false keeps it visible while the overlay panel is closed. |
window | A draggable window with a dock launcher button. | label, icon, order drive the dock button. Your registerWindow({ kind }) must use the surface id as its kind. |
settings | A section in the Settings window. | label, icon, order place it in the sidebar. |
Widgets
ps.registerWidget({
id: 'badge', // matches the manifest surface id
gated: false, // visible even when the overlay panel is closed
render(root) { /* draw into root */ },
})
Windows
A window gets a draggable frame and a dock button. The registerWindow kind must equal the
manifest surface id.
ps.registerWindow({
kind: 'main', // = the manifest surface id
title: 'My Module',
initial: { w: 360, h: 280 },
launcher: { icon: 'gauge', label: 'My Module', order: 200 },
render(root) { /* draw into root */ },
})
Settings
ps.registerSettings({
id: 'prefs',
title: 'My Module',
icon: 'gauge',
order: 220,
render(root) { /* draw your settings UI */ },
})
Sharing state across surfaces
Because each surface is a separate iframe, state that several surfaces share (e.g. a setting a widget
reads) must go through ps.host.storage. After a settings surface
writes a value, call ps.reload() so the other surfaces
re-render with it.