-
Notifications
You must be signed in to change notification settings - Fork 41
example load components
Surface: wp.os.loadComponents( tags? ) · Status: Stable
The component kit registers per bundle, at import time. After boot the page has 26 of the 67 tags — whichever ones desktop.min.js, shell-overlays and window-system happened to import for their own UI. <os-switch>, <os-number-field>, <os-table> and 38 others are not among them.
If your plugin is built beside this repo you can import them. If it installs from a zip onto a site that already has OpenStation, there is no path to import from at build time — and that is what this API is for.
await wp.os.loadComponents( [ 'os-switch', 'os-number-field' ] );One await, and the tags upgrade.
( function () {
const TAGS = [ 'os-panel', 'os-section', 'os-row', 'os-switch', 'os-number-field', 'os-button' ];
async function renderSettings( host ) {
// Cheap on every call: with the tags already registered this
// resolves without touching the network. Don't memoize it.
await wp.os.loadComponents( TAGS );
host.innerHTML = `
<os-panel>
<os-section heading="Delivery">
<os-row>
<os-switch id="live" label="Send immediately"></os-switch>
</os-row>
<os-row>
<os-number-field id="retries" label="Retries" min="0" max="9" value="3">
</os-number-field>
</os-row>
<os-row>
<os-button id="save" variant="primary">Save</os-button>
</os-row>
</os-section>
</os-panel>
`;
host.querySelector( '#save' ).addEventListener( 'click', () => {
save( {
// Props reflect attributes: checked reads '' when on,
// null when off — compare against null.
live: host.querySelector( '#live' ).checked !== null,
retries: Number( host.querySelector( '#retries' ).value ),
} );
} );
}
wp.os.ready( () => {
renderSettings( document.getElementById( 'my-plugin-settings' ) );
} );
} )();Your script needs the shell as a dependency so wp.os exists when it runs:
wp_enqueue_script(
'my-plugin-settings',
plugins_url( 'settings.js', __FILE__ ),
array( 'openstation' ),
'1.0.0',
true
);os-components[.min].js is 332 KB raw / 84 KB gzip — the whole kit, including the components the page already had. A lazy bundle cannot import from desktop.min.js, so that overlap can't be avoided; what it can be is unpaid, and it is, by every page that never calls this.
Rules of thumb:
| You want… | Do this |
|---|---|
| Two or three tags, and you already ship a bundle |
import the classes — ~3 KB gzip each, nothing at runtime |
| The kit, or several components across several screens |
loadComponents() — one fetch, cached, shared with anything else that asks |
| A zip-distributed plugin with no build-time link to this repo |
loadComponents() — it is the only route that works |
Pass the tags you're about to render. The argument is what lets the loader skip the fetch when they're already there; loadComponents() with no argument always loads the kit.
Names that aren't components get a console.error naming them, and the rest of the call proceeds — a typo costs you one component, not the panel.
It never double-registers. The custom-element registry is page-global and defineComponent() no-ops on a tag that exists, so a tag another plugin loaded first is simply used.
Failure is loud in the right place. The promise rejects only if the bundle was needed and the fetch failed. On a page where no bundle URL is configured it resolves instead, and any tag that stayed inert is named by the missing-import warner in the console — the same message a developer would get from a forgotten import.
-
components-reference.md— every tag, class, andstatic helpdescriptor -
use-from-a-plugin.md— the build-time route, types, and class imports - OpenStation Preferences → Components — the whole kit rendered live, with props and working examples
This wiki is generated from the docs/ directory — edits made here are overwritten by the next sync.
To change a page, open a pull request against docs/.
Guides
- Development guide
- Releasing openstation
- Agents security model
- API Index
- Architecture
- Bridge protocol — wiring overview
- <os-*> component reference
- Native Desktop Host — Experimental
- Desktop themes
- Dock customization — two registries, one mental model
- The event-driven framework
- Files on the Desktop
- Folder sharing
- Getting Started
- Hooks Reference
- Icons
- JavaScript Reference
- The Living Tree — algorithm definition
- Mio
- Native Windows & Framework Interop
- Plugin compatibility layer
- Progressive Web App (PWA)
- Station Home
- Using openstation from your own plugin
Migration notes
- Migration: built-in activity channels move to the os/ namespace
- Migration: window, wallpaper and widget bundles load on demand
- Migration — the navigation model
- Migration: a native window's tabs move to the window chrome
All examples
- AI Agents — extend and invoke from a plugin
- wp.os.ai.ask() — programmatic AI Copilot
- Tune the AI model config
- Custom arrange-menu action
- Open a child window its owner can't cover
- Style a specific admin page inside the iframe
- Code Blue — register your plugin's log file
- Open a file in the Code editor (deep-link from any window)
- Connect to a window — title-bar button + iframe pub/sub
- Content changes — live-refresh every window listing your type
- Custom window chrome (Experimental)
- Register a custom unfocused-window effect
- Example: render a data table
- Real file storage — react to uploads, gate policy, share from PHP
- React to a window being set free onto the real desktop
- Cross-window devtools — instrumentation primitives
- Add a dock item with a badge
- Decorate the dock without forking the renderer
- Replace the dock rail entirely
- Retune the Drafts widget's AI writing assistant
- Gate OpenStation by role
- Iframe-initiated window opens
- Build a feed reader without the bookkeeping
- Inject data into openStationConfig
- Render a list without losing clicks — renderKeyedList()
- Example: layout primitives (body → panel → row → col)
- Use <os-*> components from a plugin that ships as a zip
- Restyle and drive Mio
- Add an action that works on a whole selection
- WP Explorer — custom post types and their folder
- Add an action button to a WP Explorer preview pane
- Example: native Posts window
- Example: native window with tabs
- Native windows
- Customize note → post conversion
- Send a notification
- OAuth relay — connect to an external service
- OS-file drop
- <os-flyout> — window-scoped sliding card
- Plugins window — extras
- Track who's around — wp.os.presence
- Example: progress bar
- PWA install — surface your own button
- React to window events
- Example: extend the Trash
- Register a slash-command
- Register a desktop theme from a plugin
- Register a game
- Example: register a desktop icon (Jorvy)
- Register a wallpaper
- Register a widget
- Related entities — extend the title bar's "Related" menu
- The native-window render ctx
- Programmatic folder sharing
- Share state across multi-bundle plugins — wp.os.createSharedStore()
- Example: loading spinner
- Add an opt-in card to Station Home
- Accept drops on your desktop icon
- Give a tile two icons, one per state
- Add a row to a window's ⋯ menu
- Example: window activity & the status ring
- Window controls
- Subscribe to window lifecycle events
- Window links — relate windows and restyle the ties (Experimental)
- Window loading state — spinner overlay & ready signal
- Show a banner at the top of a window
- Pulse a window's icon — Window.requestAttention()
- Register a custom window reveal
- Window slots
- Window themes
- Native window with bundle-bound config