Custom Action Management
Important!
Custom actions are only supported for non-public apps that will be distributed privately via a shareable authorization link from your App Settings page. This means that apps built with custom actions will not be eligible for distribution via the Miro Marketplace at this time, and cannot be widely and publicly distributed. Please follow our Changelog for further developments.
⚠️ To ensure you can see the custom action in a dropdown from your app, you will need to register a minimum of two custom actions. If only one single custom action was registered, no drop down will appear and instead the custom action will fire directly by clicking on its icon.
Methods
register(...)
(customAction: CustomAction<T>) => Promise<CustomAction<T>>
🚦 Rate limit: Level 1
Experimental
You use this method to register a custom action with an app.
The method takes a single argument: an object that defines the custom action.
You need to register custom actions in the headless iframe of your app so that the actions are available as long as the app is running on the board.
For Miro apps, this is usually the index.js
/.ts
file.
If you register a custom action in the panel or the modal iframe, the operation throws an error.
Custom actions registration requires two steps:
- Subscribe to the event dispatched by the custom action using
miro.board.ui.on
method - Register custom action with it's definition. Apps cannot register custom actions that don't have subscription.
await miro.board.ui.on('custom:translate-content', handler);
await miro.board.experimental.action.register(
{
"event": "translate-content",
"ui": {
"label":
"en": "Translate content",
"icon": "chat-two",
"description": "Translate the content of the board items included in the current selection.",
},
"scope": "local",
"predicate": {
"type": "text"
},
"contexts": {
"item": {}
}
}
);
You can learn more about custom action on our tutorial.
deregister(...)
(eventName: string) => Promise<void>
🚦 Rate limit: Level 1
Experimental
Use this method to deregister a custom action that was previously registered by an app.
The method takes one argument:
- The name of the event used when registering the custom action.
await miro.board.ui.on('custom:translate-content', handler);
await miro.board.experimental.action.register(
{
"event": "translate-content",
"ui": {
"label":
"en": "Translate content",
"icon": "chat-two",
"description": "Translate the content of the board items included in the current selection.",
},
"scope": "local",
"predicate": {
"type": "text"
},
"contexts": {
"item": {}
}
}
);
await miro.board.experimental.action.deregister("translate-content")
Type definitions
CustomActionFilter
{ $and?: Array<CustomActionFilter<T>> $eq?: T $exists?: boolean $gt?: T $gte?: T $in?: Array<T> $lt?: T $lte?: T $ne?: T $nin?: Array<T> $not?: CustomActionFilter<T> $or?: Array<CustomActionFilter<T>> $regex?: string $where?: string }
CustomActionPredicate
CustomActionPredicate: | { $and?: Array<CustomActionPredicate<T>>; $not?: CustomActionPredicate<T>; $or?: Array<CustomActionPredicate<T>> } | CustomActionFilter<T> | {} | {}
CustomAction
{ contexts?: { item?: {} } event: string predicate?: CustomActionPredicate<ItemsProps<T>> scope?: 'local' | 'global' selection?: 'single' | 'multi' title="ui">ui?: { description?: string | Partial<Record<SupportedLanguages, string>> icon: string label: string | Partial<Record<SupportedLanguages, string>> position?: number } }
contexts
contexts
specifies where within the board UI the custom action will be accessible to users. It establishes the entry point for the custom action, indicating the UI element users can interact with to execute the custom action.
Currently, custom actions are available only in the context menu of selected board items.
Therefore, item
is the only supported property for contexts
at the moment.
The value of contexts.item
is an empty object for now. Default value: {}
.
"contexts": {
"item": {}
}
Makes the custom action available in a specific context on the board.
Currently, you can only make custom actions available in the context menu of selected board items, Tag cannot be used as an item.
event
The name of the custom event to which the app subscribes in order to respond with a custom action. The event
name must match the value of the ${string}
placeholder in the custom:${string}
event name you provide to the on
property when subscribing to the app.
- The event name can contain only lowercase alphabetic characters and hyphens (
^[a-z]+(-[a-z]+)\*$
). - It cannot contain spaces.
- It cannot exceed 30 characters.
Example:
// Event name
const eventName = 'translate-content';
// Custom event name that the app subscribes to.
await miro.board.ui.on(`custom:${eventName}`, handler);
predicate
The predicate
property specifies the criteria that determine which board items a custom action applies to.
The custom action only appears in the context menu when all currently selected items match the conditions defined in predicate
.
predicate
evaluates each selected item individually, even with multi-selections. It checks each item separately and must return true for every item in the selection.
If any selected item fails the predicate
check, the custom action does not display.
In summary, predicate
allows you to selectively show custom actions based on rules that apply to the current selection. The action only appears when all selected items pass the predicate
criteria.
- The conditions that you can set with
predicate
correspond to the supported board item properties. predicate
syntax leverages the MongoDB query DSL syntax.
This approach offers a wide range of operators that allow granular control of the availability of a custom action on the board UI.
// Example of a predicate that makes a custom action available only when
// the selected board items are shapes, texts, or sticky notes.
"predicate": {
"type": {
"$in": ["shape", "text", "sticky_note"]
},
}
scope
scope
defines the scope of the custom action and how it interacts with other capabilities in the board. As of now, this property is not actually relevant since we only support local
scope for the time being. Default value: local
.
selection
selection
determines whether the custom action is displayed for single or multiple selected items. Use multi
if you want the custom action to be displayed when the selection includes 1 or more items and they all match the predicate. Use single
for the custom action to be shown when there is only one selected item and it matches the predicate. Default value: multi
.
Note: If the selection contains more than 100 items, the custom action will not be displayed.
ui
The object exposes content that is displayed to board users in the context menu when one or more board items are selected.
All properties
Property | Type |
---|---|
deregister(...) |
(eventName: string) => Promise<void> |
register(...) |
(customAction: CustomAction<T>) => Promise<CustomAction<T>> |
Updated about 1 month ago