$npx -y skills add ZhangHanDong/makepad-skills --skill makepad-2.0-troubleshootingCRITICAL: Use for Makepad 2.0 troubleshooting and common mistakes. Triggers on: makepad error, makepad bug, makepad problem, makepad issue, makepad not working, text invisible, widget not showing, click not working, height zero, makepad pitfall, makepad gotcha, makepad FAQ, makep
| 1 | # Makepad 2.0 Common Pitfalls & Troubleshooting Guide |
| 2 | |
| 3 | This skill covers common mistakes when building with Makepad 2.0 and the Splash scripting language. Each pitfall includes: |
| 4 | - What the user sees (symptom) |
| 5 | - Why it happens (root cause) |
| 6 | - How to fix it (correct code) |
| 7 | |
| 8 | Reference documents: `AGENTS.md`, `splash.md` |
| 9 | |
| 10 | --- |
| 11 | |
| 12 | ## Pitfall #1: Container height is 0px -- UI is invisible |
| 13 | |
| 14 | **Symptom:** Your entire UI or a section of it does not appear. The container renders with zero height, making all children invisible. |
| 15 | |
| 16 | **Root Cause:** All View-based containers (`View`, `SolidView`, `RoundedView`, etc.) default to `height: Fill`. When a `Fill` container is placed inside a `Fit` parent (or any context where the available height is determined by children), the height resolves to 0px due to circular dependency: the parent asks the child how tall it is, the child says "as tall as my parent", and the result is zero. |
| 17 | |
| 18 | **Fix:** Always set `height: Fit` on containers that should shrink-wrap their content. |
| 19 | |
| 20 | ``` |
| 21 | // WRONG -- height defaults to Fill, resolves to 0px in a Fit context |
| 22 | View{ |
| 23 | flow: Down |
| 24 | Label{text: "Hello"} |
| 25 | } |
| 26 | |
| 27 | // CORRECT -- height: Fit makes the container wrap its children |
| 28 | View{ |
| 29 | height: Fit |
| 30 | flow: Down |
| 31 | Label{text: "Hello"} |
| 32 | } |
| 33 | ``` |
| 34 | |
| 35 | **Rule of thumb:** Write `height: Fit` immediately after the opening brace of every container unless you have a fixed-height parent or you explicitly want `height: Fill` inside a known fixed-size ancestor. |
| 36 | |
| 37 | **Exception:** Inside a fixed-height parent, `height: Fill` is valid: |
| 38 | ``` |
| 39 | View{ |
| 40 | height: 300 |
| 41 | View{ |
| 42 | height: Fill |
| 43 | Label{text: "I fill the 300px"} |
| 44 | } |
| 45 | } |
| 46 | ``` |
| 47 | |
| 48 | --- |
| 49 | |
| 50 | ## Pitfall #2: Text invisible on colored background -- missing new_batch |
| 51 | |
| 52 | **Symptom:** You add a `Label` inside a `RoundedView` or `SolidView` with a background color, but the text is invisible. The container appears correctly colored but the text cannot be seen, even though `draw_text.color` is set to a contrasting color. |
| 53 | |
| 54 | **Root Cause:** Makepad batches draw calls by shader type for GPU performance. All `Label` widgets using the same text shader get batched into one draw call, and all backgrounds into another. Without `new_batch: true`, the text draw call may execute *before* the background draw call, placing the text geometrically behind the opaque background. |
| 55 | |
| 56 | **Fix:** Add `new_batch: true` to any View-based container that has a visible background (`show_bg: true` or pre-styled views like `SolidView`, `RoundedView`) and contains text children. |
| 57 | |
| 58 | ``` |
| 59 | // WRONG -- text is drawn behind the background due to batching |
| 60 | RoundedView{ |
| 61 | height: Fit |
| 62 | draw_bg.color: #333 |
| 63 | Label{text: "Can't see me"} |
| 64 | } |
| 65 | |
| 66 | // CORRECT -- new_batch forces background to draw before children's text |
| 67 | RoundedView{ |
| 68 | height: Fit |
| 69 | new_batch: true |
| 70 | draw_bg.color: #333 |
| 71 | Label{text: "Now visible" draw_text.color: #fff} |
| 72 | } |
| 73 | ``` |
| 74 | |
| 75 | **When you MUST use `new_batch: true`:** |
| 76 | - Any container with `show_bg: true` (or pre-styled like `SolidView`, `RoundedView`) that contains text |
| 77 | - Hoverable items with background animator -- text disappears on hover without it |
| 78 | - Parent containers of repeated items that each have their own background |
| 79 | |
| 80 | --- |
| 81 | |
| 82 | ## Pitfall #3: Named child override does not work -- used `:` instead of `:=` |
| 83 | |
| 84 | **Symptom:** You define a template with `let` and try to override a child property per-instance, but the override is silently ignored. The default text always shows. |
| 85 | |
| 86 | **Root Cause:** In Splash, `:` creates a **static** property, while `:=` creates a **named/dynamic** child that is addressable and overridable. If you declare `label: Label{...}` (with `:`), the child has no addressable name and the override path `label.text:` cannot find it. |
| 87 | |
| 88 | **Fix:** Use `:=` for any child you want to reference or override later. |
| 89 | |
| 90 | ``` |
| 91 | // WRONG -- static child, override fails silently |
| 92 | let Card = View{ |
| 93 | height: Fit |
| 94 | title: Label{text: "default"} |
| 95 | } |
| 96 | Card{title.text: "new text"} // Fails! title is not addressable |
| 97 | |
| 98 | // CORRECT -- named child with :=, override works |
| 99 | let Card = View{ |
| 100 | height: Fit |
| 101 | title := Label{text: "default"} |
| 102 | } |
| 103 | Card{title.text: "new text"} // Works! title is a named child |
| 104 | ``` |
| 105 | |
| 106 | **Additional rule:** Named children inside a |