-
Notifications
You must be signed in to change notification settings - Fork 41
example arrange action
github-actions[bot] edited this page Aug 25, 2026
·
1 revision
Add a button to the admin bar's Arrange dropdown that runs your own layout algorithm. The shell ships Cascade / Overview / Snap / Tile; your item sits alongside them with identical styling.
The contract is a PHP filter (to register the menu item) plus a JS action (to run when the user clicks it). The two halves are decoupled — you can ship a plugin that registers the item without a JS callback, and some other code can subscribe to os.arrange.custom-action independently.
<?php
/**
* Plugin Name: Diagonal Cascade
*/
defined( 'ABSPATH' ) || exit;
add_filter( 'openstation_arrange_menu_items', function ( $items ) {
$items[] = array(
'id' => 'diagonal',
'title' => __( 'Diagonal cascade', 'diagonal-cascade' ),
'description' => __( 'Lay windows on a 45° line from the top-left.', 'diagonal-cascade' ),
'position' => 15, // optional: default 10 → items sort after built-ins
);
return $items;
} );
// Enqueue your JS on the desktop shell. `openstation` is the shell's
// main script handle; adding it as a dep guarantees `window.wp.os`
// is populated by the time your code runs.
add_action( 'admin_enqueue_scripts', function () {
if ( ! function_exists( 'openstation_is_enabled' ) || ! openstation_is_enabled() ) {
return;
}
wp_enqueue_script(
'diagonal-cascade',
plugin_dir_url( __FILE__ ) . 'diagonal-cascade.js',
array( 'openstation', 'wp-hooks' ),
'1.0.0',
true
);
} );// diagonal-cascade.js
( function () {
wp.os.whenReady( function () {
wp.os.hooks.addAction(
'os.arrange.custom-action',
'diagonal-cascade/apply',
function ( payload ) {
if ( payload.id !== 'diagonal' ) {
return;
}
var windows = wp.os.windowManager.getAll()
.filter( function ( w ) {
return w.state !== 'minimized';
} );
windows.forEach( function ( w, i ) {
var offset = i * 60;
w.element.style.left = 40 + offset + 'px';
w.element.style.top = 40 + offset + 'px';
} );
}
);
} );
} )();- A new "Diagonal cascade" entry in the Arrange submenu, styled identically to the built-ins.
- Clicking it fires
os.arrange.custom-actionwith{ id: 'diagonal' }. - Your subscriber runs the arrangement. Any other plugin can also subscribe (e.g. to play a sound, log analytics, etc.).
If your plugin is TS:
import { HOOKS } from 'openstation';
wp.os.hooks.addAction(
HOOKS.ARRANGE_CUSTOM_ACTION,
'diagonal-cascade/apply',
( payload: { id: string } ) => { /* ... */ }
);-
openstation_arrange_menu_itemsfilter — full filter signature, field validation rules, position sorting. -
os.arrange.*action family —cascade.starting,cascade.applied,tile.*,snap.changed,custom-action.
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