Skip to main content Skills Marketplace Descubra e explore skills de IA criadas pela comunidade.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Copiar promptMostrar detalhes do prompt Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
npx skills add https://github.com/BEKO2210/Firstbrain --skill robius-event-actionO comando permanece em uma só linha. Role horizontalmente para revisá-lo antes de copiar.
Prefere uma cópia local? Baixe os arquivos disponíveis atualmente no SkillsMP.
Baixar Zip Baixando... Ocupações relacionadas SOC
Baseado na classificação ocupacional SOC
name robius-event-action description | type skill created 2026-02-27T00:00:00.000Z domain productivity category developer-experience risk unknown source community tags ["skill","productivity","developer-experience","robius","event","action"]
Robius Event and Action Patterns Skill
Best practices for event handling and action patterns in Makepad applications based on Robrix and Moly codebases.
Source codebases:
Robrix : Matrix chat client - MessageAction, RoomsListAction, AppStateAction
Moly : AI chat application - StoreAction, ChatAction, NavigationAction, Timer patterns
When to Use
Use this skill when:
Implementing custom actions in Makepad
Handling events in widgets
Centralizing action handling in App
Widget-to-widget communication
Keywords: makepad action, makepad event, widget action, handle_actions, cx.widget_action
Custom Action Pattern
Defining Domain-Specific Actions
use makepad_widgets::*;
#[derive(Clone, DefaultNone, Debug)]
pub enum MessageAction {
React { details: MessageDetails, reaction: String },
Reply (MessageDetails),
Edit (MessageDetails),
Delete (MessageDetails),
OpenContextMenu { details: MessageDetails, abs_pos: DVec2 },
None ,
}
#[derive(Clone, Debug)]
pub struct MessageDetails {
pub room_id: OwnedRoomId,
pub event_id: OwnedEventId,
pub content: String ,
pub sender_id: OwnedUserId,
}
Emitting Actions from Widgets impl Widget for Message {
fn handle_event (&mut self , cx: &mut Cx, event: &Event, scope: &mut Scope) {
self .view.handle_event (cx, event, scope);
let area = self .view.area ();
match event.hits (cx, area) {
Hit::FingerDown (_fe) => {
cx.set_key_focus (area);
}
Hit::FingerUp (fe) => {
if fe.is_over && fe.is_primary_hit () && fe.was_tap () {
cx.widget_action (
self .widget_uid (),
&scope.path,
MessageAction::Reply (self .get_details ()),
);
}
}
Hit::FingerLongPress (lpe) => {
cx.widget_action (
self .widget_uid (),
&scope.path,
MessageAction::OpenContextMenu {
details: self .get_details (),
abs_pos: lpe.abs,
},
);
}
_ => {}
}
}
}
Centralized Action Handling in App
Using MatchEvent Trait impl MatchEvent for App {
fn handle_startup (&mut self , cx: &mut Cx) {
self .initialize (cx);
}
fn handle_actions (&mut self , cx: &mut Cx, actions: &Actions) {
for action in actions {
if let Some (action) = action.downcast_ref::<LoginAction>() {
match action {
LoginAction::LoginSuccess => {
self .app_state.logged_in = true ;
self .update_ui_visibility (cx);
}
LoginAction::LoginFailure (error) => {
self .show_error (cx, error);
}
}
continue ;
}
if let MessageAction ::OpenContextMenu { details, abs_pos } =
action.as_widget_action ().cast ()
{
self .show_context_menu (cx, details, abs_pos);
continue ;
}
match action.downcast_ref () {
Some (AppStateAction::RoomFocused (room)) => {
self .app_state.selected_room = Some (room.clone ());
continue ;
}
Some (AppStateAction::NavigateToRoom { destination }) => {
self .navigate_to_room (cx, destination);
continue ;
}
_ => {}
}
match action.downcast_ref () {
Some (ModalAction::Open { kind }) => {
self .ui.modal (ids!(my_modal)).open (cx);
continue ;
}
Some (ModalAction::Close { was_internal }) => {
if *was_internal {
self .ui.modal (ids!(my_modal)).close (cx);
}
continue ;
}
_ => {}
}
}
}
}
impl AppMain for App {
fn handle_event (&mut self , cx: &mut Cx, event: &Event) {
self .match_event (cx, event);
let scope = &mut Scope::with_data (&mut self .app_state);
self .ui.handle_event (cx, event, scope);
}
}
Action Types
Widget Actions (UI Thread) Emitted by widgets, handled in the same frame:
cx.widget_action (
self .widget_uid (),
&scope.path,
MyAction::Something,
);
if let MyAction ::Something = action.as_widget_action ().cast () {
}
if let Some (uid) = action.as_widget_action ().widget_uid () {
if uid == my_expected_uid {
if let MyAction ::Something = action.as_widget_action ().cast () {
}
}
}
Posted Actions (From Async) Posted from async tasks, received in next event cycle:
Cx::post_action (DataFetchedAction { data });
SignalToUI::set_ui_signal ();
if let Some (action) = action.downcast_ref::<DataFetchedAction>() {
self .process_data (&action.data);
}
Global Actions For app-wide state changes:
cx.action (NavigationAction::GoBack);
if let Some (NavigationAction::GoBack) = action.downcast_ref () {
self .navigate_back (cx);
}
Event Handling Patterns
Hit Testing impl Widget for MyWidget {
fn handle_event (&mut self , cx: &mut Cx, event: &Event, scope: &mut Scope) {
let area = self .view.area ();
match event.hits (cx, area) {
Hit::FingerDown (fe) => {
cx.set_key_focus (area);
}
Hit::FingerUp (fe) => {
if fe.is_over && fe.is_primary_hit () {
if fe.was_tap () {
}
if fe.was_long_press () {
}
}
}
Hit::FingerMove (fe) => {
}
Hit::FingerHoverIn (_) => {
self .animator_play (cx, id!(hover.on));
}
Hit::FingerHoverOut (_) => {
self .animator_play (cx, id!(hover.off));
}
Hit::FingerScroll (se) => {
}
_ => {}
}
}
}
Keyboard Events fn handle_event (&mut self , cx: &mut Cx, event: &Event, scope: &mut Scope) {
if let Event ::KeyDown (ke) = event {
match ke.key_code {
KeyCode::Return if !ke.modifiers.shift => {
self .submit (cx);
}
KeyCode::Escape => {
self .cancel (cx);
}
KeyCode::KeyC if ke.modifiers.control || ke.modifiers.logo => {
self .copy_to_clipboard (cx);
}
_ => {}
}
}
}
Signal Events For handling async updates:
fn handle_event (&mut self , cx: &mut Cx, event: &Event, scope: &mut Scope) {
if let Event ::Signal = event {
while let Some (update) = PENDING_UPDATES.pop () {
self .apply_update (cx, update);
}
}
}
Action Chaining Pattern Widget emits action → Parent catches and re-emits with more context:
cx.widget_action (
self .widget_uid (),
&scope.path,
ItemAction::Selected (item_id),
);
if let ItemAction ::Selected (item_id) = action.as_widget_action ().cast () {
cx.widget_action (
self .widget_uid (),
&scope.path,
ListAction::ItemSelected {
list_id: self .list_id.clone (),
item_id,
},
);
}
Best Practices
Use DefaultNone derive : All action enums must have a None variant
Use continue after handling : Prevents unnecessary processing
Downcast pattern for async actions : Posted actions are not widget actions
Widget action cast for UI actions : Use as_widget_action().cast()
Always call SignalToUI::set_ui_signal() : After posting actions from async
Centralize in App::handle_actions : Keep action handling in one place
Use descriptive action names : MessageAction::Reply not MessageAction::Action1
Reference Files
references/action-patterns.md - Additional action patterns (Robrix)
references/event-handling.md - Event handling reference (Robrix)
references/moly-action-patterns.md - Moly-specific patterns
Store-based action forwarding
Timer-based retry pattern
Radio button navigation
External link handling
Platform-conditional actions (#[cfg])
UiRunner event handling
Connections
Domain: [[Produktivitaet & Werkzeuge]]
Kategorie: [[Developer Experience]]
Navigation: [[Skills Uebersicht]], [[Home]]