
Makepad 2.0 Vector
- 43 installs
- 745 repo stars
- Updated April 7, 2026
- zhanghandong/makepad-skills
Helps with ai & agent building tasks during AI-assisted development.
About
makepad-2.0-vector is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- makepad-2.0-vector
- AI & Agent Building
- AI-coding skill
Makepad 2.0 Vector by the numbers
- 43 all-time installs (skills.sh)
- +1 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #7,921 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Jul 28, 2026 (Skillselion catalog sync)
npx skills add https://github.com/zhanghandong/makepad-skills --skill makepad-2.0-vectorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 43 |
|---|---|
| repo stars | ★ 745 |
| Last updated | April 7, 2026 |
| Repository | zhanghandong/makepad-skills ↗ |
What it does
Helps with ai & agent building tasks during AI-assisted development.
Files
Makepad 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:
- `Vector{}` - Define shapes inline in Splash (paths, rects, circles, etc.)
- `Svg{}` - Load external
.svgfiles viacrate_resource()orhttp_resource(), with optional animation and custom GPU shaders
Documentation
Refer to the local files for detailed documentation:
./references/vector-reference.md- Complete Vector API, shapes, gradients, filters, animation
---
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 |
|---|---|---|
width / height | Widget size in pixels | 48 |
viewbox | SVG viewBox as vec4 | vec4(0 0 24 24) |
CRITICAL: Shape Properties vs Widget Properties
*Vector shapes use SVG-style properties, NOT `draw_bg.` widget properties:**
// 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
// 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 |
|---|---|---|---|
from | value | Start value (color, float, string) | - |
to | value | End value | - |
values | Vec | Keyframe values (alternative to from/to) | - |
dur | f32 | Duration in seconds | 1.0 |
begin | f32 | Delay offset in seconds | 0.0 |
loop_ | bool/f32 | true = indefinite, float = repeat count | 1.0 |
calc | string | "discrete", "paced", "spline" | "linear" |
fill_mode | string | "freeze" or "remove" | "remove" |
Animatable Properties
Any shape property can be animated with Tween:
fill,stroke— color animationstroke_width,opacity,stroke_opacity— float animationcx,cy,r(Circle) — position/size animationd(Path) — path morphing animation
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 | Tween (Vector) | Animator (Widget) |
|---|---|---|
| Scope | SVG shape properties | Widget shader instance vars |
| Syntax | Property value replacement | animator: Animator{...} block |
| Triggers | Automatic on render | State transitions (hover, etc.) |
| Loop | loop_:true | Loop {duration: 1.0} |
| 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 | Vector{} | Svg{} | SDF2D Shader |
|---|---|---|---|
| Input | Inline shapes in Splash | External .svg file | Shader code |
| SVG path data | Yes (d: "...") | Yes (parsed from file) | No |
| Gradients | let bindings | SVG <defs> | Manual |
| Filters | Filter{DropShadow{}} | SVG <filter> | Manual |
| Animation | Tween{} | SVG <animate> + animating: true | Shader uniforms |
| Custom GPU shader | shader_id | draw_svg +: {get_color: fn(){...}} | Full control |
| URL loading | No | Yes (http_resource()) | No |
| Resolution-independent | Yes | Yes | Yes |
| Performance | Good for static | Good for complex SVGs | Best for animated |
Use `Vector{}` for: Inline icons, illustrations, programmatic vector graphics Use `Svg{}` for: Loading pre-made SVG files, complex SVG assets, SVG from URLs Use SDF2D for: Animated shapes, hover effects, custom widget backgrounds
---
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
1. Use `viewbox` to define coordinate space independent of widget size 2. Use theme colors for icon strokes/fills for dark/light mode support 3. Use `let` bindings for reusable icon definitions 4. Keep paths simple - Complex SVG paths can impact performance 5. Use `fill: false` for outline-only icons (most common pattern) 6. Set `stroke_linecap: "round"` for cleaner line endings on icons
Makepad 2.0 Vector Graphics Reference
Overview
The Vector{} widget renders SVG-like vector graphics declaratively in Splash. It supports paths, shapes, gradients, filters, groups, transforms, and animations -- all without loading external SVG files.
---
Basic Usage
Vector{width: 200 height: 200 viewbox: vec4(0 0 200 200)
Rect{x: 10 y: 10 w: 80 h: 60 rx: 5 ry: 5 fill: #f80}
Circle{cx: 150 cy: 50 r: 30 fill: #08f}
Line{x1: 10 y1: 150 x2: 190 y2: 150 stroke: #fff stroke_width: 2}
}The viewbox property defines the coordinate space as vec4(x y width height). The widget sizes itself to fit the viewbox when width: Fit and height: Fit (the defaults), or you can set explicit pixel dimensions.
---
Common Style Properties
All shapes support these properties:
| Property | Type | Default | Notes |
|---|---|---|---|
fill | color, Gradient, RadGradient, Tween, or false | inherited | false = no fill |
fill_opacity | f32 | 1.0 | multiplied with fill alpha |
stroke | color, Gradient, or Tween | none | outline color |
stroke_width | f32 or Tween | 0.0 | outline thickness |
stroke_opacity | f32 or Tween | 1.0 | outline alpha |
opacity | f32 or Tween | 1.0 | overall shape opacity |
stroke_linecap | string | "butt" | "butt", "round", "square" |
stroke_linejoin | string | "miter" | "miter", "round", "bevel" |
transform | Transform or array | identity | see Transforms section |
filter | Filter ref | none | see Filters section |
shader_id | f32 | 0.0 | for custom GPU effects on Svg widget |
---
Shape Types
Path -- SVG path data
Path{d: "M 10 10 L 100 100 C 50 50 200 200 300 300 Z" fill: #f00 stroke: #000 stroke_width: 2}The d property accepts standard SVG path data strings (M, L, C, Q, A, Z, etc.).
Rect -- Rectangle
Rect{x: 10 y: 20 w: 100 h: 50 rx: 5 ry: 5 fill: #f80 stroke: #fff stroke_width: 1}Properties: x, y, w, h, rx (corner radius x), ry (corner radius y)
Circle
Circle{cx: 50 cy: 50 r: 40 fill: #08f}Properties: cx (center x), cy (center y), r (radius)
Ellipse
Ellipse{cx: 100 cy: 50 rx: 80 ry: 40 fill: #0f8}Properties: cx, cy, rx (x radius), ry (y radius)
Line
Line{x1: 10 y1: 10 x2: 190 y2: 190 stroke: #fff stroke_width: 2 stroke_linecap: "round"}Properties: x1, y1, x2, y2
Polyline -- open connected segments
Polyline{pts: [10 10 50 80 100 20 150 90] fill: false stroke: #ff0 stroke_width: 2}Properties: pts (flat array of x y pairs)
Polygon -- closed connected segments
Polygon{pts: [100 10 40 198 190 78 10 78 160 198] fill: #f0f stroke: #fff stroke_width: 1}Properties: pts (flat array of x y pairs, auto-closed)
---
Groups
Group{} composes shapes and applies shared styles/transforms to all children:
Vector{width: 200 height: 200 viewbox: vec4(0 0 200 200)
Group{opacity: 0.7 transform: Rotate{deg: 15}
Rect{x: 20 y: 20 w: 60 h: 60 fill: #f00}
Circle{cx: 130 cy: 50 r: 30 fill: #0f0}
}
}Groups can be nested. Style properties on a Group (fill, stroke, etc.) apply to its children.
---
Gradients
Define gradients as let bindings and reference them in fill or stroke.
Linear Gradient
let my_grad = Gradient{x1: 0 y1: 0 x2: 1 y2: 1
Stop{offset: 0 color: #ff0000}
Stop{offset: 0.5 color: #00ff00}
Stop{offset: 1 color: #0000ff}
}
Vector{width: 200 height: 100 viewbox: vec4(0 0 200 100)
Rect{x: 0 y: 0 w: 200 h: 100 fill: my_grad}
}Gradient coordinates (x1, y1, x2, y2) are in the range 0-1 (object bounding box). Stop children define color stops with offset (0-1), color, and optional opacity.
Radial Gradient
let radial = RadGradient{cx: 0.5 cy: 0.5 r: 0.5
Stop{offset: 0 color: #fff}
Stop{offset: 1 color: #000}
}
Vector{width: 200 height: 200 viewbox: vec4(0 0 200 200)
Circle{cx: 100 cy: 100 r: 90 fill: radial}
}RadGradient properties: cx, cy (center, default 0.5), r (radius, default 0.5), fx, fy (focal point, defaults to center).
Gradient Stops with Opacity
let glass = Gradient{x1: 0 y1: 0 x2: 1 y2: 1
Stop{offset: 0 color: #xffffff opacity: 0.35}
Stop{offset: 0.4 color: #xffffff opacity: 0.08}
Stop{offset: 1 color: #xffffff opacity: 0.2}
}---
Filters
Define a Filter with DropShadow effects:
let shadow = Filter{
DropShadow{dx: 2 dy: 4 blur: 6 color: #000000 opacity: 0.5}
}
Vector{width: 200 height: 200 viewbox: vec4(0 0 200 200)
Rect{x: 40 y: 40 w: 120 h: 120 rx: 10 ry: 10 fill: #445 filter: shadow}
}DropShadow properties:
dx-- x offsetdy-- y offsetblur-- blur radiuscolor-- shadow coloropacity-- shadow opacity
---
Transforms
Transforms can be applied to any shape or group via the transform property. Use a single transform or an array of transforms (composed left-to-right).
Available Transforms
| Transform | Syntax | Notes |
|---|---|---|
| Rotate | Rotate{deg: 45} | Optional cx, cy for rotation center |
| Scale | Scale{x: 2 y: 1.5} | If only x given, y defaults to same |
| Translate | Translate{x: 100 y: 50} | Translation offset |
| SkewX | SkewX{deg: 30} | Horizontal skew |
| SkewY | SkewY{deg: 15} | Vertical skew |
Static Transforms
// Single transform
Rect{x: 0 y: 0 w: 50 h: 50 fill: #f00 transform: Rotate{deg: 45}}
// Multiple transforms (composed left-to-right)
Group{transform: [Translate{x: 100 y: 50} Scale{x: 2 y: 2} Rotate{deg: 30}]
Circle{cx: 0 cy: 0 r: 20 fill: #0ff}
}Animated Transforms
Add dur, from, to (or values), and optionally loop_ and begin to animate:
// Continuously rotating shape
Circle{cx: 100 cy: 100 r: 30 fill: #0ff
transform: Rotate{deg: 0 dur: 2.0 from: 0 to: 360 loop_: true}
}
// Animated scale
Rect{x: 50 y: 50 w: 40 h: 40 fill: #f80
transform: Scale{x: 1 dur: 1.5 from: 1 to: 2 loop_: true}
}---
Tween (Property Animation)
Use Tween{} to animate individual shape properties (fill, stroke, d, x, y, r, etc.):
// Animated path morphing
Path{d: Tween{
dur: 2.0 loop_: true
values: ["M 10 80 Q 50 10 100 80" "M 10 80 Q 50 150 100 80"]
} fill: #f0f}
// Animated fill color
Circle{cx: 50 cy: 50 r: 30
fill: Tween{dur: 1.5 loop_: true from: #ff0000 to: #0000ff}
}
// Animated stroke width
Rect{x: 10 y: 10 w: 80 h: 80
fill: false stroke: #fff
stroke_width: Tween{dur: 2.0 loop_: true from: 1 to: 5}
}Tween Properties
| Property | Type | Description |
|---|---|---|
from | value | Start value |
to | value | End value |
values | array | Array of keyframe values (alternative to from/to) |
dur | f32 | Duration in seconds |
begin | f32 | Start delay in seconds |
loop_ | bool or number | true for indefinite, or a number for repeat count |
calc | string | "linear" (default), "discrete", "paced", "spline" |
fill_mode | string | "remove" (default) or "freeze" |
---
Vector vs Svg Widget
Vector{} | Svg{} | |
|---|---|---|
| Input | Declarative shapes in Splash script | External .svg file via resource handle |
| Use case | Programmatic/inline vector graphics | Loading pre-made SVG assets |
| Source | Inline Path{}, Rect{}, Circle{}, etc. | crate_resource("self:path.svg") or http_resource("url") |
| Gradients | let bindings, referenced by name | Parsed from SVG <defs> (linear, radial) |
| Filters | Filter{DropShadow{...}} | Parsed from SVG <filter> (feDropShadow) |
| Animation | Tween{} on properties, animated transforms | Parsed from SVG <animate> elements + animating: true |
| Custom shaders | shader_id + custom get_color on Svg | Override get_color via draw_svg +: |
| Color override | Set fill/stroke on shapes directly | draw_svg.color replaces all SVG colors (or -1 for original) |
| Syntax | Vector{viewbox: ... Path{} Rect{}} | Svg{draw_svg +: {svg: crate_resource("self:file.svg")}} |
Use Vector{} when you want to define graphics inline in your UI script. Use Svg{} when loading existing SVG files as assets.
Svg Widget Quick Reference
// Load from local resource
Svg{
width: 300 height: 300
animating: false
draw_svg +: { svg: crate_resource("self:resources/icon.svg") }
}
// Load from URL
Svg{
width: 300 height: 100
draw_svg +: { svg: http_resource("https://example.com/logo.svg") }
}
// With animation and custom shader
Svg{
width: 600 height: 450
animating: true
draw_svg +: {
svg: crate_resource("self:resources/scene.svg")
get_color: fn() {
let base = self.eval_gradient();
let t = self.svg_time;
return mix(base, vec4(1.0), sin(t) * 0.1);
}
}
}Svg properties: draw_svg.svg (resource), draw_svg.color (tint override, default -1 = original), draw_svg.svg_time (animation time uniform), animating (bool, enables per-frame updates).
---
SVG Icons as Vector Paths
Simple SVG icons can be embedded directly as Path shapes:
// Check mark icon
let IconCheck = Vector{width: 18 height: 18 viewbox: vec4(0 0 24 24)
Path{d: "M20 6L9 17L4 12" fill: false stroke: #fff stroke_width: 2.5
stroke_linecap: "round" stroke_linejoin: "round"}
}
// File icon
Vector{width: 32 height: 32 viewbox: vec4(0 0 49 49)
Path{d: "M12.069,11.678c0,-2.23 1.813,-4.043 4.043,-4.043l10.107,0l0,8.086c0,1.118 0.903,2.021 2.021,2.021l8.086,0l0,18.193c0,2.23 -1.813,4.043 -4.043,4.043l-16.171,0c-2.23,0 -4.043,-1.813 -4.043,-4.043l0,-24.257Zm24.257,4.043l-8.086,0l0,-8.086l8.086,8.086Z"}
}
// Folder icon
Vector{width: 32 height: 32 viewbox: vec4(0 0 49 49)
Path{d: "M11.884,37.957l24.257,0c2.23,0 4.043,-1.813 4.043,-4.043l0,-16.172c0,-2.23 -1.813,-4.042 -4.043,-4.042l-10.107,0c-0.638,0 -1.238,-0.297 -1.617,-0.809l-1.213,-1.617c-0.765,-1.017 -1.965,-1.617 -3.235,-1.617l-8.085,0c-2.23,0 -4.043,1.813 -4.043,4.043l0,20.214c0,2.23 1.813,4.043 4.043,4.043Z"}
}---
Hex Color Escaping
When using hex colors containing the letter e inside script_mod!, use the #x prefix to avoid parse errors:
// These need #x prefix (contain 'e' adjacent to digits)
fill: #x2ecc71
fill: #x1e1e2e
fill: #x4466ee
// These are fine without #x (no 'e' adjacent to digits)
fill: #ff4444
fill: #44cc44---
Complete Example: App Icon with Gradients, Groups, and Filters
// Define gradients
let glass_bg = Gradient{x1: 0 y1: 0 x2: 1 y2: 1
Stop{offset: 0 color: #x556677 opacity: 0.45}
Stop{offset: 1 color: #x334455 opacity: 0.35}
}
let brain_grad = Gradient{x1: 0.5 y1: 0 x2: 0.5 y2: 1
Stop{offset: 0 color: #x77ccff}
Stop{offset: 0.4 color: #x7799ee}
Stop{offset: 0.75 color: #x8866dd}
Stop{offset: 1 color: #x9944cc}
}
let brain_glow = RadGradient{cx: 0.5 cy: 0.45 r: 0.45
Stop{offset: 0 color: #x4466ee opacity: 0.4}
Stop{offset: 1 color: #x4466dd opacity: 0.0}
}
// Define filter
let icon_shadow = Filter{
DropShadow{dx: 0 dy: 4 blur: 6 color: #x000000 opacity: 0.5}
}
Vector{width: 256 height: 256 viewbox: vec4(0 0 256 256)
// Glass background with shadow
Rect{x: 16 y: 16 w: 224 h: 224 rx: 44 ry: 44
fill: glass_bg filter: icon_shadow}
// Brain glow
Circle{cx: 128 cy: 95 r: 80 fill: brain_glow}
// Brain paths (scaled and translated group)
Group{transform: [Translate{x: 36.8 y: 11.4} Scale{x: 7.6 y: 7.6}]
Path{d: "M15.5 13a3.5 3.5 0 0 0 -3.5 3.5v1a3.5 3.5 0 0 0 7 0v-1.8"
fill: false stroke: brain_grad stroke_width: 0.35
stroke_linecap: "round" stroke_linejoin: "round"}
Path{d: "M8.5 13a3.5 3.5 0 0 1 3.5 3.5v1a3.5 3.5 0 0 1 -7 0v-1.8"
fill: false stroke: brain_grad stroke_width: 0.35
stroke_linecap: "round" stroke_linejoin: "round"}
}
// Keyboard keys
Rect{x: 73 y: 190 w: 9 h: 6 rx: 1 ry: 1 fill: #xffffff fill_opacity: 0.18}
Rect{x: 85 y: 190 w: 9 h: 6 rx: 1 ry: 1 fill: #xffffff fill_opacity: 0.18}
}