{"id":"b30f25ee-4207-48e8-93e3-8f18f0760466","shortId":"awhjkS","kind":"skill","title":"robius-widget-patterns","tagline":"CRITICAL: Use for Robius widget patterns. Triggers on:\napply_over, TextOrImage, modal, 可复用, 模态,\ncollapsible, drag drop, reusable widget, widget design,\npageflip, 组件设计, 组件模式","description":"# Robius Widget Patterns Skill\n\nBest practices for designing reusable Makepad widgets based on Robrix and Moly codebase patterns.\n\n**Source codebases:**\n- **Robrix**: Matrix chat client - Avatar, RoomsList, RoomScreen widgets\n- **Moly**: AI chat application - Slot, ChatLine, PromptInput, AdaptiveView widgets\n\n## When to Use\nUse this skill when:\n- Creating reusable Makepad widgets\n- Designing widget component APIs\n- Implementing text/image toggle patterns\n- Dynamic styling in Makepad\n- Keywords: robrix widget, makepad component, reusable widget, widget design pattern\n\n## Production Patterns\n\nFor production-ready widget patterns, see the `_base/` directory:\n\n| Pattern | Description |\n|---------|-------------|\n| 01-widget-extension | Add helper methods to widget references |\n| 02-modal-overlay | Popups, dialogs using DrawList2d overlay |\n| 03-collapsible | Expandable/collapsible sections |\n| 04-list-template | Dynamic lists with LivePtr templates |\n| 05-lru-view-cache | Memory-efficient view caching |\n| 14-callout-tooltip | Tooltips with arrow positioning |\n| 20-redraw-optimization | Efficient redraw patterns |\n| 15-dock-studio-layout | IDE-style resizable panels |\n| 16-hover-effect | Hover effects with instance variables |\n| 17-row-based-grid-layout | Dynamic grid layouts |\n| 18-drag-drop-reorder | Drag-and-drop widget reordering |\n| 19-pageflip-optimization | PageFlip 切换优化，即刻销毁/缓存模式 |\n| 21-collapsible-row-portal-list | Auto-grouping consecutive items in portal lists with FoldHeader |\n| 22-dropdown-overlay | Dropdown popups using DrawList2d overlay (no layout push) |\n\n## Standard Widget Structure\n\n```rust\nuse makepad_widgets::*;\n\nlive_design! {\n    use link::theme::*;\n    use link::widgets::*;\n\n    pub MyWidget = {{MyWidget}} {\n        width: Fill, height: Fit,\n        flow: Down,\n\n        // Child widgets defined in DSL\n        inner_view = <View> {\n            // ...\n        }\n    }\n}\n\n#[derive(Live, LiveHook, Widget)]\npub struct MyWidget {\n    #[deref] view: View,              // Delegate to inner View\n\n    #[live] some_property: f64,       // DSL-configurable property\n    #[live(100.0)] default_val: f64,  // With default value\n\n    #[rust] internal_state: State,    // Rust-only state (not in DSL)\n\n    #[animator] animator: Animator,   // For animations\n}\n\nimpl Widget for MyWidget {\n    fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {\n        self.view.handle_event(cx, event, scope);\n        // Custom event handling...\n    }\n\n    fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {\n        self.view.draw_walk(cx, scope, walk)\n    }\n}\n```\n\n## Text/Image Toggle Pattern\n\nA common pattern for widgets that show either text or an image (like avatars):\n\n```rust\nlive_design! {\n    pub Avatar = {{Avatar}} {\n        width: 36.0, height: 36.0,\n        align: { x: 0.5, y: 0.5 }\n        flow: Overlay,  // Stack views on top of each other\n\n        text_view = <View> {\n            visible: true,  // Default visible\n            show_bg: true,\n            draw_bg: {\n                uniform background_color: #888888\n                fn pixel(self) -> vec4 {\n                    let sdf = Sdf2d::viewport(self.pos * self.rect_size);\n                    let c = self.rect_size * 0.5;\n                    sdf.circle(c.x, c.x, c.x)\n                    sdf.fill_keep(self.background_color);\n                    return sdf.result\n                }\n            }\n            text = <Label> {\n                text: \"?\"\n            }\n        }\n\n        img_view = <View> {\n            visible: false,  // Hidden by default\n            img = <Image> {\n                fit: Stretch,\n                width: Fill, height: Fill,\n            }\n        }\n    }\n}\n\n#[derive(LiveHook, Live, Widget)]\npub struct Avatar {\n    #[deref] view: View,\n    #[rust] info: Option<UserInfo>,\n}\n\nimpl Avatar {\n    /// Show text content, hiding the image\n    pub fn show_text<T: AsRef<str>>(\n        &mut self,\n        cx: &mut Cx,\n        bg_color: Option<Vec4>,\n        info: Option<AvatarTextInfo>,\n        username: T,\n    ) {\n        self.info = info.map(|i| i.into());\n\n        // Get first character\n        let first_char = utils::first_letter(username.as_ref())\n            .unwrap_or(\"?\").to_uppercase();\n        self.label(ids!(text_view.text)).set_text(cx, &first_char);\n\n        // Toggle visibility\n        self.view(ids!(text_view)).set_visible(cx, true);\n        self.view(ids!(img_view)).set_visible(cx, false);\n\n        // Apply optional background color\n        if let Some(color) = bg_color {\n            self.view(ids!(text_view)).apply_over(cx, live! {\n                draw_bg: { background_color: (color) }\n            });\n        }\n    }\n\n    /// Show image content, hiding the text\n    pub fn show_image<F, E>(\n        &mut self,\n        cx: &mut Cx,\n        info: Option<AvatarImageInfo>,\n        image_set_fn: F,\n    ) -> Result<(), E>\n    where\n        F: FnOnce(&mut Cx, ImageRef) -> Result<(), E>\n    {\n        let img_ref = self.image(ids!(img_view.img));\n        let res = image_set_fn(cx, img_ref);\n\n        if res.is_ok() {\n            self.view(ids!(img_view)).set_visible(cx, true);\n            self.view(ids!(text_view)).set_visible(cx, false);\n            self.info = info.map(|i| i.into());\n        }\n        res\n    }\n\n    /// Check current display status\n    pub fn status(&mut self) -> DisplayStatus {\n        if self.view(ids!(img_view)).visible() {\n            DisplayStatus::Image\n        } else {\n            DisplayStatus::Text\n        }\n    }\n}\n```\n\n## Dynamic Styling with apply_over\n\nApply dynamic styles at runtime:\n\n```rust\n// Apply single property\nself.view(ids!(content)).apply_over(cx, live! {\n    draw_bg: { color: #ff0000 }\n});\n\n// Apply multiple properties\nself.view(ids!(message)).apply_over(cx, live! {\n    padding: { left: 20, right: 20 }\n    margin: { top: 10 }\n});\n\n// Apply with variables\nlet highlight_color = if is_selected { vec4(1.0, 0.0, 0.0, 1.0) } else { vec4(0.5, 0.5, 0.5, 1.0) };\nself.view(ids!(item)).apply_over(cx, live! {\n    draw_bg: { color: (highlight_color) }\n});\n```\n\n## Widget Reference Pattern\n\nImplement `*Ref` methods for external API:\n\n```rust\nimpl AvatarRef {\n    /// See [`Avatar::show_text()`].\n    pub fn show_text<T: AsRef<str>>(\n        &self,\n        cx: &mut Cx,\n        bg_color: Option<Vec4>,\n        info: Option<AvatarTextInfo>,\n        username: T,\n    ) {\n        if let Some(mut inner) = self.borrow_mut() {\n            inner.show_text(cx, bg_color, info, username);\n        }\n    }\n\n    /// See [`Avatar::show_image()`].\n    pub fn show_image<F, E>(\n        &self,\n        cx: &mut Cx,\n        info: Option<AvatarImageInfo>,\n        image_set_fn: F,\n    ) -> Result<(), E>\n    where\n        F: FnOnce(&mut Cx, ImageRef) -> Result<(), E>\n    {\n        if let Some(mut inner) = self.borrow_mut() {\n            inner.show_image(cx, info, image_set_fn)\n        } else {\n            Ok(())\n        }\n    }\n}\n```\n\n## Collapsible/Expandable Pattern\n\n```rust\nlive_design! {\n    pub CollapsibleSection = {{CollapsibleSection}} {\n        flow: Down,\n\n        header = <View> {\n            cursor: Hand,\n            icon = <Icon> { }\n            title = <Label> { text: \"Section\" }\n        }\n\n        content = <View> {\n            visible: false,\n            // Expandable content here\n        }\n    }\n}\n\n#[derive(Live, LiveHook, Widget)]\npub struct CollapsibleSection {\n    #[deref] view: View,\n    #[rust] is_expanded: bool,\n}\n\nimpl CollapsibleSection {\n    pub fn toggle(&mut self, cx: &mut Cx) {\n        self.is_expanded = !self.is_expanded;\n        self.view(ids!(content)).set_visible(cx, self.is_expanded);\n\n        // Rotate icon\n        let rotation = if self.is_expanded { 90.0 } else { 0.0 };\n        self.view(ids!(header.icon)).apply_over(cx, live! {\n            draw_icon: { rotation: (rotation) }\n        });\n\n        self.redraw(cx);\n    }\n}\n```\n\n## Loading State Pattern\n\n```rust\nlive_design! {\n    pub LoadableContent = {{LoadableContent}} {\n        flow: Overlay,\n\n        content = <View> {\n            visible: true,\n            // Main content\n        }\n\n        loading_overlay = <View> {\n            visible: false,\n            show_bg: true,\n            draw_bg: { color: #00000088 }\n            align: { x: 0.5, y: 0.5 }\n            <BouncingDots> { }\n        }\n\n        error_view = <View> {\n            visible: false,\n            error_label = <Label> { }\n        }\n    }\n}\n\n#[derive(Live, LiveHook, Widget)]\npub struct LoadableContent {\n    #[deref] view: View,\n    #[rust] state: LoadingState,\n}\n\npub enum LoadingState {\n    Idle,\n    Loading,\n    Loaded,\n    Error(String),\n}\n\nimpl LoadableContent {\n    pub fn set_state(&mut self, cx: &mut Cx, state: LoadingState) {\n        self.state = state;\n        match &self.state {\n            LoadingState::Idle | LoadingState::Loaded => {\n                self.view(ids!(content)).set_visible(cx, true);\n                self.view(ids!(loading_overlay)).set_visible(cx, false);\n                self.view(ids!(error_view)).set_visible(cx, false);\n            }\n            LoadingState::Loading => {\n                self.view(ids!(content)).set_visible(cx, true);\n                self.view(ids!(loading_overlay)).set_visible(cx, true);\n                self.view(ids!(error_view)).set_visible(cx, false);\n            }\n            LoadingState::Error(msg) => {\n                self.view(ids!(content)).set_visible(cx, false);\n                self.view(ids!(loading_overlay)).set_visible(cx, false);\n                self.view(ids!(error_view)).set_visible(cx, true);\n                self.label(ids!(error_view.error_label)).set_text(cx, msg);\n            }\n        }\n        self.redraw(cx);\n    }\n}\n```\n\n## PortalList Item Pattern\n\nFor virtual list items:\n\n```rust\nlive_design! {\n    pub ItemsList = {{ItemsList}} {\n        list = <PortalList> {\n            keep_invisible: false,\n            auto_tail: false,\n            width: Fill, height: Fill,\n            flow: Down,\n\n            // Item templates\n            item_entry = <ItemEntry> {}\n            header = <SectionHeader> {}\n            empty = <View> {}\n        }\n    }\n}\n\nimpl Widget for ItemsList {\n    fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {\n        while let Some(item) = self.view.draw_walk(cx, scope, walk).step() {\n            if let Some(mut list) = item.as_portal_list().borrow_mut() {\n                list.set_item_range(cx, 0, self.items.len());\n\n                while let Some(item_id) = list.next_visible_item(cx) {\n                    let item = list.item(cx, item_id, live_id!(item_entry));\n                    // Populate item with data\n                    self.populate_item(cx, item, &self.items[item_id]);\n                    item.draw_all(cx, scope);\n                }\n            }\n        }\n        DrawStep::done()\n    }\n}\n```\n\n## Best Practices\n\n1. **Use `#[deref]` for delegation**: Delegate to inner View for standard behavior\n2. **Separate DSL properties (`#[live]`) from Rust state (`#[rust]`)**\n3. **Implement both inner methods and `*Ref` wrappers**\n4. **Use `apply_over` for dynamic runtime styling**\n5. **Use `flow: Overlay` for toggle/swap patterns**\n6. **Use `set_visible()` to toggle between alternative views**\n7. **Always call `redraw(cx)` after state changes**\n\n## Reference Files\n\n- `references/widget-patterns.md` - Additional widget patterns (Robrix)\n- `references/styling-patterns.md` - Dynamic styling patterns (Robrix)\n- `references/moly-widget-patterns.md` - Moly-specific patterns\n  - `Slot` widget for runtime content replacement\n  - `MolyRoot` conditional rendering wrapper\n  - `AdaptiveView` for responsive Mobile/Desktop layouts\n  - Chat line variants (UserLine, BotLine, ErrorLine, etc.)\n  - `CommandTextInput` with action buttons\n  - Sidebar navigation with radio buttons\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.","tags":["robius","widget","patterns","antigravity","awesome","skills","sickn33","agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding"],"capabilities":["skill","source-sickn33","skill-robius-widget-patterns","topic-agent-skills","topic-agentic-skills","topic-ai-agent-skills","topic-ai-agents","topic-ai-coding","topic-ai-workflows","topic-antigravity","topic-antigravity-skills","topic-claude-code","topic-claude-code-skills","topic-codex-cli","topic-codex-skills"],"categories":["antigravity-awesome-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/sickn33/antigravity-awesome-skills/robius-widget-patterns","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add sickn33/antigravity-awesome-skills","source_repo":"https://github.com/sickn33/antigravity-awesome-skills","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 34583 github stars · SKILL.md body (12,177 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T18:52:09.218Z","embedding":null,"createdAt":"2026-04-18T21:43:41.551Z","updatedAt":"2026-04-22T18:52:09.218Z","lastSeenAt":"2026-04-22T18:52:09.218Z","tsv":"'0':1151 '0.0':717,718,899 '0.5':395,397,437,722,723,724,942,944 '00000088':939 '01':113 '02':123 '03':132 '04':136 '05':145 '1':1191 '1.0':716,719,725 '10':705 '100.0':299 '14':155 '15':170 '16':180 '17':189 '18':198 '19':209 '2':1203 '20':163,700,702 '21':217 '22':233 '3':1212 '36.0':390,392 '4':1220 '5':1228 '6':1235 '7':1244 '888888':421 '90.0':897 'action':1293 'adaptiveview':64,1279 'add':117 'addit':1255 'ai':58 'align':393,940 'altern':1242 'alway':1245 'anim':317,318,319,321 'api':80,746 'appli':13,548,562,666,668,674,680,688,694,706,729,903,1222 'applic':60 'arrow':161 'ask':1333 'asref':490,759 'auto':224,1094 'auto-group':223 'avatar':53,382,387,388,470,478,751,786 'avatarref':749 'background':419,550,568 'base':40,109,192 'behavior':1202 'best':33,1189 'bg':414,417,496,556,567,685,734,764,781,934,937 'bool':867 'borrow':1145 'botlin':1288 'boundari':1341 'button':1294,1299 'c':434 'c.x':439,440,441 'cach':149,154 'call':1246 'callout':157 'callout-tooltip':156 'chang':1251 'char':512,529 'charact':509 'chat':51,59,1284 'chatlin':62 'check':642 'child':269 'clarif':1335 'clear':1308 'client':52 'codebas':45,48 'collaps':19,133,219 'collapsible-row-portal-list':218 'collapsible/expandable':831 'collapsiblesect':837,838,860,869 'color':420,445,497,551,555,557,569,570,686,711,735,737,765,782,938 'commandtextinput':1291 'common':370 'compon':79,93 'condit':1276 'configur':296 'consecut':226 'content':481,573,679,848,852,884,924,928,995,1020,1046,1273 'creat':73 'criteria':1344 'critic':5 'current':643 'cursor':842 'custom':344 'cx':331,333,341,352,363,493,495,527,538,546,564,585,587,600,615,627,635,682,696,731,761,763,780,796,798,811,824,875,877,887,905,912,980,982,998,1006,1014,1023,1031,1039,1049,1057,1065,1073,1076,1118,1133,1150,1161,1165,1178,1185,1248 'cx2d':354,1120 'data':1175 'default':300,304,411,456 'defin':271 'deleg':286,1195,1196 'deref':283,471,861,958,1193 'deriv':276,464,854,951 'describ':1312 'descript':112 'design':25,36,77,97,253,385,835,918,1086 'dialog':128 'directori':110 'display':644 'displaystatus':651,658,661 'dock':172 'dock-studio-layout':171 'done':1188 'drag':20,200,204 'drag-and-drop':203 'drag-drop-reord':199 'draw':348,416,566,684,733,907,936,1114 'drawlist2d':130,240 'drawstep':360,1126,1187 'drop':21,201,206 'dropdown':235,237 'dropdown-overlay':234 'dsl':273,295,316,1205 'dsl-configur':294 'dynam':85,140,195,663,669,1225,1260 'e':582,595,603,794,806,814 'effect':183,185 'effici':152,167 'either':376 'els':660,720,829,898 'empti':1108 'entri':1106,1171 'enum':965 'environ':1324 'environment-specif':1323 'error':945,949,970,1010,1035,1042,1061 'error_view.error':1069 'errorlin':1289 'etc':1290 'event':328,334,335,340,342,345 'expand':851,866,879,881,889,896 'expandable/collapsible':134 'expert':1329 'extens':116 'extern':745 'f':581,593,597,793,804,808 'f64':293,302 'fals':453,547,636,850,932,948,1007,1015,1040,1050,1058,1093,1096 'ff0000':687 'file':1253 'fill':264,461,463,1098,1100 'first':508,511,514,528 'fit':266,458 'flow':267,398,839,922,1101,1230 'fn':326,347,422,486,578,592,614,647,755,790,803,828,871,975,1113 'fnonc':598,809 'foldhead':232 'get':507 'grid':193,196 'group':225 'hand':843 'handl':327,346 'header':841,1107 'header.icon':902 'height':265,391,462,1099 'helper':118 'hidden':454 'hide':482,574 'highlight':710,736 'hover':182,184 'hover-effect':181 'i.into':506,640 'icon':844,891,908 'id':523,533,541,559,608,622,630,654,678,692,727,883,901,994,1001,1009,1019,1026,1034,1045,1052,1060,1068,1157,1167,1169,1182 'ide':176 'ide-styl':175 'idl':967,990 'imag':380,484,572,580,590,612,659,788,792,801,823,826 'imageref':601,812 'img':450,457,542,605,616,623,655 'img_view.img':609 'impl':322,477,748,868,972,1109 'implement':81,741,1213 'info':475,499,588,767,783,799,825 'info.map':504,638 'inner':274,288,775,819,1198,1215 'inner.show':778,822 'input':1338 'instanc':187 'intern':307 'invis':1092 'item':227,728,1078,1083,1103,1105,1130,1148,1156,1160,1163,1166,1170,1173,1177,1179,1181 'item.as':1142 'item.draw':1183 'itemslist':1088,1089,1112 'keep':443,1091 'keyword':89 'label':950,1070 'layout':174,194,197,243,1283 'left':699 'let':426,433,510,553,604,610,709,772,816,892,1128,1138,1154,1162 'letter':515 'like':381 'limit':1300 'line':1285 'link':255,258 'list':138,141,222,230,1082,1090,1141,1144 'list-templ':137 'list.item':1164 'list.next':1158 'list.set':1147 'live':252,277,290,298,384,466,565,683,697,732,834,855,906,917,952,1085,1168,1207 'livehook':278,465,856,953 'liveptr':143 'load':913,929,968,969,992,1002,1017,1027,1053 'loadablecont':920,921,957,973 'loadingst':963,966,984,989,991,1016,1041 'lru':147 'lru-view-cach':146 'main':927 'makepad':38,75,88,92,250 'margin':703 'match':987,1309 'matrix':50 'memori':151 'memory-effici':150 'messag':693 'method':119,743,1216 'miss':1346 'mobile/desktop':1282 'modal':16,125 'modal-overlay':124 'moli':44,57,1266 'moly-specif':1265 'molyroot':1275 'msg':1043,1074 'multipl':689 'mut':329,332,337,350,353,356,491,494,583,586,599,649,762,774,777,797,810,818,821,873,876,978,981,1116,1119,1122,1140,1146 'mywidget':261,262,282,325 'navig':1296 'ok':620,830 'optim':166,212 'option':476,498,500,549,589,766,768,800 'output':1318 'overlay':126,131,236,241,399,923,930,1003,1028,1054,1231 'pad':698 'pageflip':26,211,213 'pageflip-optim':210 'panel':179 'pattern':4,10,31,46,84,98,100,106,111,169,368,371,740,832,915,1079,1234,1257,1262,1268 'permiss':1339 'pixel':423 'popul':1172 'popup':127,238 'portal':221,229,1143 'portallist':1077 'posit':162 'practic':34,1190 'product':99,103 'production-readi':102 'promptinput':63 'properti':292,297,676,690,1206 'pub':260,280,386,468,485,577,646,754,789,836,858,870,919,955,964,974,1087 'push':244 'radio':1298 'rang':1149 'readi':104 'redraw':165,168,1247 'redraw-optim':164 'ref':517,606,617,742,1218 'refer':122,739,1252 'references/moly-widget-patterns.md':1264 'references/styling-patterns.md':1259 'references/widget-patterns.md':1254 'render':1277 'reorder':202,208 'replac':1274 'requir':1337 'res':611,641 'res.is':619 'resiz':178 'respons':1281 'result':594,602,805,813 'return':446 'reusabl':22,37,74,94 'review':1330 'right':701 'robius':2,8,29 'robius-widget-pattern':1 'robrix':42,49,90,1258,1263 'roomscreen':55 'roomslist':54 'rotat':890,893,909,910 'row':191,220 'row-based-grid-layout':190 'runtim':672,1226,1272 'rust':248,306,311,383,474,673,747,833,864,916,961,1084,1209,1211 'rust-on':310 'safeti':1340 'scope':336,338,343,355,357,364,1121,1123,1134,1186,1311 'sdf':427 'sdf.circle':438 'sdf.fill':442 'sdf.result':447 'sdf2d':428 'section':135,847 'see':107,750,785 'select':714 'self':330,351,424,492,584,650,760,795,874,979,1117 'self.background':444 'self.borrow':776,820 'self.image':607 'self.info':503,637 'self.is':878,880,888,895 'self.items':1180 'self.items.len':1152 'self.label':522,1067 'self.populate':1176 'self.pos':430 'self.rect':431,435 'self.redraw':911,1075 'self.state':985,988 'self.view':532,540,558,621,629,653,677,691,726,882,900,993,1000,1008,1018,1025,1033,1044,1051,1059 'self.view.draw':361,1131 'self.view.handle':339 'separ':1204 'set':525,536,544,591,613,625,633,802,827,885,976,996,1004,1012,1021,1029,1037,1047,1055,1063,1071,1237 'show':375,413,479,487,571,579,752,756,787,791,933 'sidebar':1295 'singl':675 'size':432,436 'skill':32,71,1303 'skill-robius-widget-patterns' 'slot':61,1269 'sourc':47 'source-sickn33' 'specif':1267,1325 'stack':400 'standard':245,1201 'state':308,309,313,914,962,977,983,986,1210,1250 'status':645,648 'step':1136 'stop':1331 'stretch':459 'string':971 'struct':281,469,859,956 'structur':247 'studio':173 'style':86,177,664,670,1227,1261 'substitut':1321 'success':1343 'tail':1095 'task':1307 'templat':139,144,1104 'test':1327 'text':377,407,448,449,480,488,526,534,560,576,631,662,753,757,779,846,1072 'text/image':82,366 'text_view.text':524 'textorimag':15 'theme':256 'titl':845 'toggl':83,367,530,872,1240 'toggle/swap':1233 'tooltip':158,159 'top':403,704 'topic-agent-skills' 'topic-agentic-skills' 'topic-ai-agent-skills' 'topic-ai-agents' 'topic-ai-coding' 'topic-ai-workflows' 'topic-antigravity' 'topic-antigravity-skills' 'topic-claude-code' 'topic-claude-code-skills' 'topic-codex-cli' 'topic-codex-skills' 'treat':1316 'trigger':11 'true':410,415,539,628,926,935,999,1024,1032,1066 'uniform':418 'unwrap':518 'uppercas':521 'use':6,68,69,129,239,249,254,257,1192,1221,1229,1236,1301 'userlin':1287 'usernam':501,769,784 'username.as':516 'util':513 'val':301 'valid':1326 'valu':305 'variabl':188,708 'variant':1286 'vec4':425,715,721 'view':148,153,275,284,285,289,401,408,451,472,473,535,543,561,624,632,656,862,863,946,959,960,1011,1036,1062,1199,1243 'viewport':429 'virtual':1081 'visibl':409,412,452,531,537,545,626,634,657,849,886,925,931,947,997,1005,1013,1022,1030,1038,1048,1056,1064,1159,1238 'walk':349,358,359,362,365,1115,1124,1125,1132,1135 'widget':3,9,23,24,30,39,56,65,76,78,91,95,96,105,115,121,207,246,251,259,270,279,323,373,467,738,857,954,1110,1256,1270 'widget-extens':114 'width':263,389,460,1097 'wrapper':1219,1278 'x':394,941 'y':396,943 '切换优化':214 '即刻销毁':215 '可复用':17 '模态':18 '组件模式':28 '组件设计':27 '缓存模式':216","prices":[{"id":"4d1bb047-05fa-434f-be5a-d9ae4f6b613a","listingId":"b30f25ee-4207-48e8-93e3-8f18f0760466","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"sickn33","category":"antigravity-awesome-skills","install_from":"skills.sh"},"createdAt":"2026-04-18T21:43:41.551Z"}],"sources":[{"listingId":"b30f25ee-4207-48e8-93e3-8f18f0760466","source":"github","sourceId":"sickn33/antigravity-awesome-skills/robius-widget-patterns","sourceUrl":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/robius-widget-patterns","isPrimary":false,"firstSeenAt":"2026-04-18T21:43:41.551Z","lastSeenAt":"2026-04-22T18:52:09.218Z"}],"details":{"listingId":"b30f25ee-4207-48e8-93e3-8f18f0760466","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"sickn33","slug":"robius-widget-patterns","github":{"repo":"sickn33/antigravity-awesome-skills","stars":34583,"topics":["agent-skills","agentic-skills","ai-agent-skills","ai-agents","ai-coding","ai-workflows","antigravity","antigravity-skills","claude-code","claude-code-skills","codex-cli","codex-skills","cursor","cursor-skills","developer-tools","gemini-cli","gemini-skills","kiro","mcp","skill-library"],"license":"mit","html_url":"https://github.com/sickn33/antigravity-awesome-skills","pushed_at":"2026-04-22T06:40:00Z","description":"Installable GitHub library of 1,400+ agentic skills for Claude Code, Cursor, Codex CLI, Gemini CLI, Antigravity, and more. Includes installer CLI, bundles, workflows, and official/community skill collections.","skill_md_sha":"c4a0e8d43d49d23c5f5672ee21e41344e6fb08de","skill_md_path":"skills/robius-widget-patterns/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/sickn33/antigravity-awesome-skills/tree/main/skills/robius-widget-patterns"},"layout":"multi","source":"github","category":"antigravity-awesome-skills","frontmatter":{"name":"robius-widget-patterns","description":"CRITICAL: Use for Robius widget patterns. Triggers on:\napply_over, TextOrImage, modal, 可复用, 模态,\ncollapsible, drag drop, reusable widget, widget design,\npageflip, 组件设计, 组件模式"},"skills_sh_url":"https://skills.sh/sickn33/antigravity-awesome-skills/robius-widget-patterns"},"updatedAt":"2026-04-22T18:52:09.218Z"}}