robius-widget-patterns – Design & UI skill for AI agents
CRITICAL: Use for Robius widget patterns. Triggers on: apply_over, TextOrImage, modal, 可复用, 模态, collapsible, drag drop, reusable widget, widget design, pageflip, 组件设计, 组件模式
Install the robius-widget-patterns skill with one command
Pick the tool you use, copy the command and paste it in your terminal. The skill lands in that tool's skills folder and is ready in your next session.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/robius-widget-patterns-20205.tgz | tar xz -C ~/.claude/skills
Call it in Claude Code: /robius-widget-patterns – then describe the task you want done.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/robius-widget-patterns-20205.tgz | tar xz -C ~/.codex/skills
Call it in Codex: $robius-widget-patterns – then describe the task you want done.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/robius-widget-patterns-20205.tgz | tar xz -C ~/.hermes/skills
Call it in Hermes Agent: /robius-widget-patterns – then describe the task you want done.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/robius-widget-patterns-20205.tgz | tar xz -C ~/.deepcode/skills
Call it in DeepSeek: /robius-widget-patterns – then describe the task you want done.
SKILL.md content
Supporting material availability
This catalog copy contains the inline guidance below, but does not include the following supporting paths. They are external prerequisites, not bundled files:
<support-root>/references/widget-patterns.md<support-root>/references/styling-patterns.md<support-root>/references/moly-widget-patterns.md
Ask for the original supporting material or an existing installation before using a step that depends on these paths; this catalog does not identify a verified download source for them. Resolve each path relative to that installation, inspect its contents, and verify any applicable license and execution prerequisites. Do not run a command or claim a referenced procedure was followed until its required file exists. Do not fabricate the missing scripts or treat an unrelated file with the same name as equivalent. Independent steps fully documented here can proceed within the user’s authorized scope; report any dependent step as unavailable.
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
When to Use
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
The upstream _base/ directory is not bundled. These pattern names are navigation suggestions, not production-certified code:
| Pattern | Description |
|---------|-------------|
| 01-widget-extension | Add helper methods to widget references |
| 02-modal-overlay | Popups, dialogs using DrawList2d overlay |
| 03-collapsible | Expandable/collapsible sections |
| 04-list-template | Dynamic lists with LivePtr templates |
| 05-lru-view-cache | Memory-efficient view caching |
| 14-callout-tooltip | Tooltips with arrow positioning |
| 20-redraw-optimization | Efficient redraw patterns |
| 15-dock-studio-layout | IDE-style resizable panels |
| 16-hover-effect | Hover effects with instance variables |
| 17-row-based-grid-layout | Dynamic grid layouts |
| 18-drag-drop-reorder | Drag-and-drop widget reordering |
| 19-pageflip-optimization | PageFlip 切换优化,即刻销毁/缓存模式 |
| 21-collapsible-row-portal-list | Auto-grouping consecutive items in portal lists with FoldHeader |
| 22-dropdown-overlay | Dropdown popups using DrawList2d overlay (no layout push) |
Standard Widget Structure
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 = <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):
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 = <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 = <Label> {
text: "?"
}
}
img_view = <View> {
visible: false, // Hidden by default
img = <Image> {
fit: Stretch,
width: Fill, height: Fill,
}
}
}
}
#[derive(LiveHook, Live, Widget)]
pub struct Avatar {
#[deref] view: View,
#[rust] info: Option<UserInfo>,
}
impl Avatar {
/// Show text content, hiding the image
pub fn show_text<T: AsRef<str>>(
&mut self,
cx: &mut Cx,
bg_color: Option<Vec4>,
info: Option<AvatarTextInfo>,
username: T,
) {
self.info = info.map(|i| i.into());
// Get first character
let first_char = utils::first_letter(username.as_ref())
.unwrap_or("?").to_uppercase();
self.label(ids!(text_view.text)).set_text(cx, &first_char);
// Toggle visibility
self.view(ids!(text_view)).set_visible(cx, true);
self.view(ids!(img_view)).set_visible(cx, false);
// Apply optional background color
if let Some(color) = bg_color {
self.view(ids!(text_view)).apply_over(cx, live! {
draw_bg: { background_color: (color) }
});
}
}
/// Show image content, hiding the text
pub fn show_image<F, E>(
&mut self,
cx: &mut Cx,
info: Option<AvatarImageInfo>,
image_set_fn: F,
) -> Result<(), E>
where
F: FnOnce(&mut Cx, ImageRef) -> Result<(), E>
{
let img_ref = self.image(ids!(img_view.img));
let res = image_set_fn(cx, img_ref);
if res.is_ok() {
self.view(ids!(img_view)).set_visible(cx, true);
self.view(ids!(text_view)).set_visible(cx, false);
self.info = info.map(|i| i.into());
}
res
}
/// Check current display status
pub fn status(&mut self) -> DisplayStatus {
if self.view(ids!(img_view)).visible() {
DisplayStatus::Image
} else {
DisplayStatus::Text
}
}
}Dynamic Styling with apply_over
Apply dynamic styles at runtime:
// Apply single property
self.view(ids!(content)).apply_over(cx, live! {
draw_bg: { color: #ff0000 }
});
// Apply multiple properties
self.view(ids!(message)).apply_over(cx, live! {
padding: { left: 20, right: 20 }
margin: { top: 10 }
});
// Apply with variables
let highlight_color = if is_selected { vec4(1.0, 0.0, 0.0, 1.0) } else { vec4(0.5, 0.5, 0.5, 1.0) };
self.view(ids!(item)).apply_over(cx, live! {
draw_bg: { color: (highlight_color) }
});Widget Reference Pattern
Implement *Ref methods for external API:
impl AvatarRef {
/// See [`Avatar::show_text()`].
pub fn show_text<T: AsRef<str>>(
&self,
cx: &mut Cx,
bg_color: Option<Vec4>,
info: Option<AvatarTextInfo>,
username: T,
) {
if let Some(mut inner) = self.borrow_mut() {
inner.show_text(cx, bg_color, info, username);
}
}
/// See [`Avatar::show_image()`].
pub fn show_image<F, E>(
&self,
cx: &mut Cx,
info: Option<AvatarImageInfo>,
image_set_fn: F,
) -> Result<(), E>
where
F: FnOnce(&mut Cx, ImageRef) -> Result<(), E>
{
if let Some(mut inner) = self.borrow_mut() {
inner.show_image(cx, info, image_set_fn)
} else {
Ok(())
}
}
}Collapsible/Expandable Pattern
live_design! {
pub CollapsibleSection = {{CollapsibleSection}} {
flow: Down,
header = <View> {
cursor: Hand,
icon = <Icon> { }
title = <Label> { text: "Section" }
}
content = <View> {
visible: false,
// Expandable content here
}
}
}
#[derive(Live, LiveHook, Widget)]
pub struct CollapsibleSection {
#[deref] view: View,
#[rust] is_expanded: bool,
}
impl CollapsibleSection {
pub fn toggle(&mut self, cx: &mut Cx) {
self.is_expanded = !self.is_expanded;
self.view(ids!(content)).set_visible(cx, self.is_expanded);
// Rotate icon
let rotation = if self.is_expanded { 90.0 } else { 0.0 };
self.view(ids!(header.icon)).apply_over(cx, live! {
draw_icon: { rotation: (rotation) }
});
self.redraw(cx);
}
}Loading State Pa
… (full content is in the download package)
Related skills
- saas-multi-tenant – Design and implement multi-tenant SaaS architectures with row-level security…
- scarcity-urgency-psychologist – Design honest scarcity and urgency messaging when verified inventory, capacity, or…
- schema-markup – Design, validate, and optimize schema.org structured data for eligibility, correctness…
- sci-fi-interface – Web and App implementation guide for Sci-Fi Interface Design. Trigger when user wants…
- seek-and-analyze-video – Seek and analyze video content using Memories.ai Large Visual Memory Model for…
- senior-frontend – Frontend development skill for React, Next.js, TypeScript, and Tailwind CSS…
- shadcn – Manages shadcn/ui components and projects, providing context, documentation, and usage…
- skeuomorphism – Web and App implementation guide for Skeuomorphism. Trigger when user wants UI to mimic…