-
Notifications
You must be signed in to change notification settings - Fork 41
example tile drop handler
Your plugin registers a desktop icon and you want the user to drag things onto it — a photo onto an image editor, a post onto a publishing tool, a file onto an uploader. This is how.
defined( 'ABSPATH' ) || exit;Registering your own DropTarget on the tile element:
// ✗ Silently displaced.
wp.hooks.addAction( 'os.files.tile-rendered', 'my-plugin/drop', ( { tile } ) => {
wp.os.dragManager.registerDropTarget( { element: tile, /* … */ } );
} );Every non-folder tile carries a claimant that hard-rejects foreign
payloads, so a drop can't fall through to the wallpaper underneath —
it's what shows the red "Can't drop here" chip. The drop-target
registry allows one target per element, and the claimant is
installed after tile-rendered fires. Yours is overwritten before the
user ever drags anything.
Cooperate with the claimant instead. It already consults a handler registry for its accept predicate, its hover chip, and its drop — register there and the layer does the rest.
const off = wp.os.files.registerTilePayloadHandler( 'shortcut', {
// Narrow: only my icon, nobody else's.
appliesTo: ( { placement } ) => placement.file.ref === 'lienzo',
// Which payloads I'll take. Return false and the user still gets
// the normal rejection chip.
accept: ( data ) => data.kind === 'attachment' || data.kind === 'post',
// Shown next to the cursor while a matching payload hovers.
acceptLabel: 'Open in Lienzo',
onDrop: ( session ) => {
const { kind, id, url, title } = session.payload.data;
openLienzoWith( { kind, id, url, title } );
},
} );
// Later, if your feature unmounts:
off();type is the drag payload's type, not the file type:
type |
Dragged from |
|---|---|
'shortcut' |
Desktop icons, post/page references, dock-item promotions, site-window entity tiles |
'attachment' |
Media Library tiles and the site window's Media section |
'note' |
Pinned notes |
Register one handler per type you want to accept:
[ 'shortcut', 'attachment' ].forEach( ( type ) =>
wp.os.files.registerTilePayloadHandler( type, handler )
);Inspect session.payload.data for the payload itself — its shape
depends on the source. Guard on what you actually need rather than
assuming a field is present.
Several handlers can register the same type. Resolution is
first-registered whose appliesTo matches, so handlers only
compete when they claim the same tile for the same payload type.
That makes appliesTo the important part. Match on something that
identifies your icon:
// ✓ Only my icon.
appliesTo: ( { placement } ) => placement.file.ref === 'lienzo',
// ✗ Claims every tile on the desktop, and shadows every handler
// registered after mine.
appliesTo: () => true,placement.file carries type, ref, title, icon, and
shortcutUrl — ref is the id you passed to
openstation_register_icon().
- No matching handler → red "Can't drop here" chip, drop rejected.
-
appliesTomatches butacceptreturns false → same rejection. Use this for "right icon, wrong thing". - Both pass → your
acceptLabelnext to the cursor, tile highlights,onDropruns on release.
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