--- name: robius-widget-patterns description: | CRITICAL: Use for Robius widget patterns. Triggers on: apply_over, TextOrImage, modal, 可复用, 模态, collapsible, drag drop, reusable widget, widget design, pageflip, 组件设计, 组件模式 --- # Robius Widget Patterns Skill Best practices for designing reusable Makepad widgets based on Robrix and Moly codebase patterns. **Source codebases:** - **Robrix**: Matrix chat client - Avatar, RoomsList, RoomScreen widgets - **Moly**: AI chat application - Slot, ChatLine, PromptInput, AdaptiveView widgets ## Triggers Use this skill when: - Creating reusable Makepad widgets - Designing widget component APIs - Implementing text/image toggle patterns - Dynamic styling in Makepad - Keywords: robrix widget, makepad component, reusable widget, widget design pattern ## Production Patterns For production-ready widget patterns, see the `_base/` directory: | Pattern | Description | |---------|-------------| | [01-widget-extension](./_base/01-widget-extension.md) | Add helper methods to widget references | | [02-modal-overlay](./_base/02-modal-overlay.md) | Popups, dialogs using DrawList2d overlay | | [03-collapsible](./_base/03-collapsible.md) | Expandable/collapsible sections | | [04-list-template](./_base/04-list-template.md) | Dynamic lists with LivePtr templates | | [05-lru-view-cache](./_base/05-lru-view-cache.md) | Memory-efficient view caching | | [14-callout-tooltip](./_base/14-callout-tooltip.md) | Tooltips with arrow positioning | | [20-redraw-optimization](./_base/20-redraw-optimization.md) | Efficient redraw patterns | | [15-dock-studio-layout](./_base/15-dock-studio-layout.md) | IDE-style resizable panels | | [16-hover-effect](./_base/16-hover-effect.md) | Hover effects with instance variables | | [17-row-based-grid-layout](./_base/17-row-based-grid-layout.md) | Dynamic grid layouts | | [18-drag-drop-reorder](./_base/18-drag-drop-reorder.md) | Drag-and-drop widget reordering | | [19-pageflip-optimization](./_base/19-pageflip-optimization.md) | PageFlip 切换优化,即刻销毁/缓存模式 | ## Standard Widget Structure ```rust use makepad_widgets::*; live_design! { use link::theme::*; use link::widgets::*; pub MyWidget = {{MyWidget}} { width: Fill, height: Fit, flow: Down, // Child widgets defined in DSL inner_view = { // ... } } } #[derive(Live, LiveHook, Widget)] pub struct MyWidget { #[deref] view: View, // Delegate to inner View #[live] some_property: f64, // DSL-configurable property #[live(100.0)] default_val: f64, // With default value #[rust] internal_state: State, // Rust-only state (not in DSL) #[animator] animator: Animator, // For animations } impl Widget for MyWidget { fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) { self.view.handle_event(cx, event, scope); // Custom event handling... } fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep { self.view.draw_walk(cx, scope, walk) } } ``` ## Text/Image Toggle Pattern A common pattern for widgets that show either text or an image (like avatars): ```rust live_design! { pub Avatar = {{Avatar}} { width: 36.0, height: 36.0, align: { x: 0.5, y: 0.5 } flow: Overlay, // Stack views on top of each other text_view = { visible: true, // Default visible show_bg: true, draw_bg: { uniform background_color: #888888 fn pixel(self) -> vec4 { let sdf = Sdf2d::viewport(self.pos * self.rect_size); let c = self.rect_size * 0.5; sdf.circle(c.x, c.x, c.x) sdf.fill_keep(self.background_color); return sdf.result } } text =