Makepad-skills makepad-2.0-vector
git clone https://github.com/ZhangHanDong/makepad-skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/ZhangHanDong/makepad-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/makepad-2.0-vector" ~/.claude/skills/zhanghandong-makepad-skills-makepad-2-0-vector && rm -rf "$T"
skills/makepad-2.0-vector/SKILL.mdMakepad 2.0 Vector Graphics Skill
Version: makepad-widgets (dev branch) | Last Updated: 2026-03-03
Overview
The
Vector widget renders resolution-independent vector graphics using SVG-like syntax. It supports paths, shapes, gradients, filters, groups, transforms, and property animation via Tween.
Two ways to use SVG in Splash:
- Define shapes inline in Splash (paths, rects, circles, etc.)Vector{}
- Load externalSvg{}
files via.svg
orcrate_resource()
, with optional animation and custom GPU shadershttp_resource()
Documentation
Refer to the local files for detailed documentation:
- Complete Vector API, shapes, gradients, filters, animation./references/vector-reference.md
Basic Usage
Vector{ width: 48 height: 48 viewbox: vec4(0 0 24 24) Path{ d: "M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" fill: false stroke: #4488ff stroke_width: 2.0 stroke_linecap: "round" stroke_linejoin: "round" } }
Key Properties
| Property | Description | Example |
|---|---|---|
/ | Widget size in pixels | |
| SVG viewBox as vec4 | |
CRITICAL: Shape Properties vs Widget Properties
Vector shapes use SVG-style properties, NOT
widget properties:draw_bg.*
// CORRECT — SVG properties Path{d:"M 0 0 L 10 10" stroke:#x66aaff stroke_width:2.5} Circle{cx:10 cy:10 r:5 fill:#x44ddaa} // WRONG — these do nothing on Vector shapes! Path{d:"..." draw_bg.stroke_color:#x66aaff draw_bg.stroke_width:2.} Circle{cx:10 cy:10 r:5 draw_bg.fill_color:#x44ddaa}
Shape Types
Path (SVG path data)
Path{ d: "M10 10 L20 20 L10 20 Z" fill: #f00 stroke: #000 stroke_width: 1.5 }
Built-in Shapes
Rect{x: 0 y: 0 width: 100 height: 50 fill: #f00 rx: 5} Circle{cx: 50 cy: 50 r: 25 fill: #00f} Ellipse{cx: 50 cy: 30 rx: 40 ry: 20 fill: #0f0} Line{x1: 0 y1: 0 x2: 100 y2: 100 stroke: #fff stroke_width: 2} Polyline{points: "0,0 50,25 100,0" fill: false stroke: #fff} Polygon{points: "50,0 100,100 0,100" fill: #f0f}
Gradients
Linear Gradient
Gradient{ id: "myGrad" x1: 0 y1: 0 x2: 1 y2: 1 Stop{offset: 0 color: #ff0000} Stop{offset: 1 color: #0000ff} } Path{d: "..." fill: "url(#myGrad)"}
Radial Gradient
RadGradient{ id: "radGrad" cx: 0.5 cy: 0.5 r: 0.5 Stop{offset: 0 color: #ffffff} Stop{offset: 1 color: #000000} }
Groups & Transforms
Group{ transform: "translate(10 20) rotate(45 50 50)" opacity: 0.8 Circle{cx: 0 cy: 0 r: 10 fill: #f00} Rect{x: 20 y: 0 width: 20 height: 20 fill: #0f0} }
Filters
Filter{ id: "shadow" DropShadow{dx: 2 dy: 2 blur: 4 color: #0008} } Path{d: "..." fill: #fff filter: "url(#shadow)"}
Tween Animation (SVG Property Animation)
CRITICAL: Tween is a property value, NOT a container. It replaces a shape property (fill, stroke, opacity, cx, cy, r, etc.) with an animated value.
Basic Syntax
// Animate opacity (pulse effect) Circle{cx:8 cy:8 r:6 fill:#x44ddaa opacity:Tween{from:0.3 to:1.0 dur:1.5 loop_:true}} // Animate position (moving dot) Circle{cx:Tween{from:20 to:380 dur:3.0 loop_:true} cy:25 r:5 fill:#x66aaff} // Animate color Circle{fill:Tween{from:#x44ddaa to:#x6688dd dur:3.0 loop_:true} cx:10 cy:10 r:8} // Animate stroke Path{d:"M 0 0 L 100 0" stroke:Tween{from:#x333333 to:#x66aaff dur:2.0 loop_:true} stroke_width:2.}
CRITICAL: loop_
Must Be Boolean
loop_// CORRECT — indefinite loop opacity:Tween{from:0.3 to:1.0 dur:1.5 loop_:true} // CORRECT — play 3 times opacity:Tween{from:0.3 to:1.0 dur:1.5 loop_:3.0} // WRONG — string doesn't trigger Indefinite, plays only once! opacity:Tween{from:0.3 to:1.0 dur:1.5 loop_:"indefinite"}
Tween Properties
| Property | Type | Description | Default |
|---|---|---|---|
| value | Start value (color, float, string) | - |
| value | End value | - |
| Vec | Keyframe values (alternative to from/to) | - |
| f32 | Duration in seconds | 1.0 |
| f32 | Delay offset in seconds | 0.0 |
| bool/f32 | = indefinite, float = repeat count | 1.0 |
| string | "discrete", "paced", "spline" | "linear" |
| string | "freeze" or "remove" | "remove" |
Animatable Properties
Any shape property can be animated with Tween:
,fill
— color animationstroke
,stroke_width
,opacity
— float animationstroke_opacity
,cx
,cy
(Circle) — position/size animationr
(Path) — path morphing animationd
Common Patterns
Pulsing indicator:
Vector{width:16 height:16 Circle{cx:8 cy:8 r:6 fill:#x44ddaa opacity:Tween{from:0.3 to:1.0 dur:1.5 loop_:true}} }
Moving dot along a line:
Vector{width:Fill height:40 Path{d:"M 20 20 L 380 20" stroke:#x333355 stroke_width:1.} Circle{cx:Tween{from:20 to:380 dur:3.0 loop_:true} cy:20 r:4 fill:Tween{from:#x44ddaa to:#xffaa44 dur:3.0 loop_:true}} }
Delayed sequential animation:
Circle{cx:8 cy:8 r:6 fill:#x44ddaa opacity:Tween{from:0.3 to:1.0 dur:1.5 begin:0.0 loop_:true}} Circle{cx:8 cy:8 r:6 fill:#xffaa44 opacity:Tween{from:0.3 to:1.0 dur:1.5 begin:0.5 loop_:true}} Circle{cx:8 cy:8 r:6 fill:#x6688dd opacity:Tween{from:0.3 to:1.0 dur:1.5 begin:1.0 loop_:true}}
Tween vs Animator
| Feature | (Vector) | (Widget) |
|---|---|---|
| Scope | SVG shape properties | Widget shader vars |
| Syntax | Property value replacement | block |
| Triggers | Automatic on render | State transitions (hover, etc.) |
| Loop | | |
| Use for | SVG animations | UI hover/focus/active effects |
Icon Pattern (Common)
Most Vector widgets in Makepad 2.0 are used as icons with SVG paths:
let IconCheck = Vector{width: 18 height: 18 viewbox: vec4(0 0 24 24) Path{d: "M20 6L9 17L4 12" fill: false stroke: theme.color_highlight stroke_width: 2.5 stroke_linecap: "round" stroke_linejoin: "round"} } let IconTrash = Vector{width: 14 height: 14 viewbox: vec4(0 0 24 24) Path{d: "M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" fill: false stroke: theme.color_label_inner_inactive stroke_width: 1.8 stroke_linecap: "round" stroke_linejoin: "round"} }
Use with theme colors for consistent styling across light/dark modes.
Vector vs Svg vs SDF2D
| Feature | | | SDF2D Shader |
|---|---|---|---|
| Input | Inline shapes in Splash | External file | Shader code |
| SVG path data | Yes () | Yes (parsed from file) | No |
| Gradients | bindings | SVG | Manual |
| Filters | | SVG | Manual |
| Animation | | SVG + | Shader uniforms |
| Custom GPU shader | | | Full control |
| URL loading | No | Yes () | No |
| Resolution-independent | Yes | Yes | Yes |
| Performance | Good for static | Good for complex SVGs | Best for animated |
Use
for: Inline icons, illustrations, programmatic vector graphics
Use Vector{}
for: Loading pre-made SVG files, complex SVG assets, SVG from URLs
Use SDF2D for: Animated shapes, hover effects, custom widget backgroundsSvg{}
Hex Color Escape
When using hex colors containing the letter 'e', prefix with
#x:
// WRONG - parser misreads 'e' as exponent stroke: #2ecc71 // CORRECT stroke: #x2ecc71
Best Practices
- Use
to define coordinate space independent of widget sizeviewbox - Use theme colors for icon strokes/fills for dark/light mode support
- Use
bindings for reusable icon definitionslet - Keep paths simple - Complex SVG paths can impact performance
- Use
for outline-only icons (most common pattern)fill: false - Set
for cleaner line endings on iconsstroke_linecap: "round"