
Makepad 2.0 Widgets
- 44 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-widgets is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- makepad-2.0-widgets
- AI & Agent Building
- AI-coding skill
Makepad 2.0 Widgets by the numbers
- 44 all-time installs (skills.sh)
- +1 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #7,794 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-widgetsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 44 |
|---|---|
| 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 Widget Catalog Skill
Version: makepad-widgets (dev branch) | Last Updated: 2026-03-03
Overview
Makepad 2.0 provides a rich set of built-in widgets for building UIs. All widgets are defined in Splash syntax and registered via script_mod!.
Documentation
Refer to the local files for detailed documentation:
./references/widget-catalog.md- Complete widget list with properties./references/widget-advanced.md- Advanced patterns: PortalList, Dock, custom widgets, MapView
IMPORTANT: Documentation Completeness Check
Before answering questions, Claude MUST: 1. Read the relevant reference file(s) listed above 2. Incorporate reference content into the answer
---
Widget Categories Quick Reference
Containers (Layout)
| Widget | Description | Key Properties |
|---|---|---|
View | Basic container (transparent) | width, height, flow, spacing, padding, align |
SolidView | View with solid background | + show_bg: true, draw_bg.color |
RoundedView | View with rounded corners | + draw_bg.border_radius |
RoundedAllView | All corners same radius | + border_radius shorthand |
GradientXView | Horizontal gradient bg | + draw_bg colors |
GradientYView | Vertical gradient bg | + draw_bg colors |
ScrollXView | Horizontal scrolling | scroll property |
ScrollYView | Vertical scrolling | scroll property |
ScrollXYView | Both-axis scrolling | scroll property |
Text Widgets
| Widget | Description | Key Properties |
|---|---|---|
Label | Single/multi-line text | text, draw_text.color, draw_text.text_style.font_size |
H1 - H4 | Heading levels | text (pre-styled) |
P | Paragraph text | text |
TextInput | Editable text field | text, empty_text, password, read_only, numeric_only |
Markdown | Markdown renderer | body |
Html | HTML renderer | body |
LinkLabel | Clickable link text | text, url |
Buttons
| Widget | Description | Key Properties |
|---|---|---|
Button | Standard button | text |
ButtonFlat | Flat style button | text |
ButtonFlatter | Minimal button | text |
Toggles
| Widget | Description | Key Properties |
|---|---|---|
CheckBox | Check box | text, active |
Toggle | Toggle switch | text, active |
RadioButton | Radio button | text, active |
Input Widgets
| Widget | Description | Key Properties |
|---|---|---|
Slider | Horizontal slider | min, max, step, default, precision |
DropDown | Dropdown select | labels: ["a", "b", "c"] |
Media
| Widget | Description | Key Properties |
|---|---|---|
Image | Image display | source, fit (Stretch/Horizontal/Vertical/Smallest/Biggest/Size) |
Svg | External SVG file renderer | draw_svg.svg (crate_resource/http_resource), animating, draw_svg.color |
Icon | SVG icon (tinted) | draw_icon.svg, draw_icon.color, icon_walk |
Vector | Inline vector graphics | viewbox, Path{d: "..."} |
LoadingSpinner | Loading indicator | color, rotation_speed |
MapView | Map widget | center_lon, center_lat, zoom (MUST use fixed height!) |
Layout Helpers
| Widget | Description | Usage |
|---|---|---|
Hr | Horizontal rule | Divider line |
Vr | Vertical rule | Vertical divider |
Filler | Flexible space | Push siblings apart (use between Fit siblings only!) |
Splitter | Resizable split | axis: Horizontal/Vertical, a/b children |
FoldHeader | Collapsible section | header + body children |
Lists
| Widget | Description | Usage |
|---|---|---|
PortalList | Virtualized list | For large lists (100+ items), only renders visible items |
FlatList | Simple list | For small lists, renders all items |
Navigation
| Widget | Description | Control |
|---|---|---|
Modal | Modal dialog | .open(cx) / .close(cx) from Rust |
Tooltip | Tooltip popup | Hover-triggered |
PopupNotification | Toast notification | Timed display |
SlidePanel | Sliding panel | slide_from |
ExpandablePanel | Expandable area | open/close |
PageFlip | Page switcher | active_page: page_name |
StackNavigation | Stack nav | push/pop pages |
Dock System
| Widget | Description |
|---|---|
Dock | Tab container system |
DockSplitter | Dock split panels |
DockTabs | Tab bar |
DockTab | Individual tab |
---
Critical Rules
1. height: Fit on Containers
// WRONG - View defaults to 0px height
View{ flow: Down Label{text: "Invisible"} }
// CORRECT
View{ height: Fit flow: Down Label{text: "Visible"} }2. new_batch for Colored Containers with Text
// WRONG - text behind background
RoundedView{ draw_bg.color: #333 Label{text: "Invisible"} }
// CORRECT
RoundedView{ new_batch: true draw_bg.color: #333 Label{text: "Visible"} }3. Named Children with :=
// Named (addressable, overridable)
title := Label{text: "Hello"}
// Static (not addressable)
Label{text: "Hello"}4. Label Default Color is White
// Default text is white (#fff) - set color for light backgrounds
Label{text: "Dark text" draw_text.color: #333}5. MapView MUST Have Fixed Height
// WRONG
MapView{ width: Fill height: Fill }
// CORRECT
View{ new_batch: true width: Fill height: 400
MapView{ width: Fill height: 400 center_lat: 40.7 center_lon: -73.9 zoom: 14.0 }
}6. Label Does NOT Support Animator
// WRONG (silently ignored)
Label{ animator: Animator{...} }
// CORRECT - wrap in View
View{ animator: Animator{...} Label{text: "Animated"} }---
Common Widget Patterns
Card
RoundedView{
width: Fill height: Fit
padding: 16
new_batch: true
draw_bg.color: #2a2a3d
draw_bg.border_radius: 8.0
flow: Down spacing: 8
title := Label{text: "Title" draw_text.color: #fff draw_text.text_style.font_size: 16}
body := Label{text: "Content" draw_text.color: #aaa}
}Form Input
View{
width: Fill height: Fit
flow: Down spacing: 4
Label{text: "Email" draw_text.color: #aaa draw_text.text_style.font_size: 11}
email_input := TextInput{
width: Fill height: 36
empty_text: "Enter email..."
}
}Scrollable List
ScrollYView{
width: Fill height: Fill
flow: Down spacing: 4
new_batch: true
on_render: || {
for i, item in items {
ItemTemplate{label.text: item.name}
}
}
}---
Best Practices
1. Use `height: Fit` on every container unless you want Fill or fixed pixels 2. Use `new_batch: true` on any View with background color + text children 3. Use `:=` for children you need to reference or override 4. Use theme colors (theme.color_*) instead of hardcoded colors 5. Use `PortalList` for large lists (virtualizes rendering) 6. Use `ScrollYView` for scrollable content areas 7. Use `RoundedView` for cards and containers (has border_radius)
Makepad 2.0 Advanced Widget Patterns
---
PortalList Usage Pattern
PortalList is a virtualized list widget that only renders visible items. It requires a Rust-side draw loop to populate items.
DSL Definition (in script_mod!)
list := PortalList{
width: Fill
height: Fill
flow: Down
scroll_bar: ScrollBar{}
// Templates are defined with := syntax
// These become entries in the templates HashMap
Item := View{
width: Fill
height: Fit
padding: 10
title := Label{
text: ""
draw_text.color: #fff
}
}
Header := View{
width: Fill
height: 40
show_bg: true
draw_bg.color: #333
label := Label{
text: "Section Header"
draw_text.color: #aaa
}
}
}Rust Draw Loop
// In your Widget's draw_walk implementation
while let Some(item) = self.view.draw_walk(cx, scope, walk).step() {
if let Some(mut list) = item.borrow_mut::<PortalList>() {
// Tell the list how many total items exist
list.set_item_range(cx, 0, count);
// Iterate over visible items only
while let Some(item_id) = list.next_visible_item(cx) {
// Create/reuse a widget from a template by LiveId
let item = list.item(cx, item_id, id!(Item));
// Populate the item's children
item.label(ids!(title)).set_text(cx, &format!("Item {}", item_id));
// Draw the item
item.draw_all(cx, &mut Scope::empty());
}
}
}Templates in PortalList
- Named IDs using
:=define templates stored in the widget'stemplatesHashMap - Regular properties (like
flow,scroll_bar) go into struct fields - Templates are collected during
on_after_applyviavm.vec_with() - Multiple template types can be used: select which template to instantiate based on
item_id
// Using different templates for different item types
while let Some(item_id) = list.next_visible_item(cx) {
let template = if item_id == 0 { id!(Header) } else { id!(Item) };
let item = list.item(cx, item_id, template);
// ... populate and draw
item.draw_all(cx, &mut Scope::empty());
}PortalList Scrolling API
// Scroll to specific item
list.scroll_to_item(cx, item_index);
// Smooth scroll to item
list.smooth_scroll_to_item(cx, item_index);
// Get scroll position
let pos = list.scroll_position();
// Enable tail mode (auto-scroll to bottom)
list.set_tail(cx, true);---
Dock System Complete Example
The Dock widget provides a tabbed, splittable panel layout system.
1. Dock Definition
dock := Dock{
width: Fill
height: Fill
// Override tab bar template
tab_bar +: {
TabTemplate := IconTab{
// custom tab appearance
}
}
// Root layout structure
root := DockSplitter{
axis: Horizontal
align: Weighted(0.3)
// Left panel: tabs
a: DockTabs{
tabs: [
DockTab{name: "Files" template: FilesView}
DockTab{name: "Search" template: SearchView}
]
selected: 0
closable: false
}
// Right panel: further split
b: DockSplitter{
axis: Vertical
align: Weighted(0.7)
a: DockTabs{
tabs: [
DockTab{name: "Editor" template: EditorView}
]
selected: 0
}
b: DockTabs{
tabs: [
DockTab{name: "Console" template: ConsoleView}
]
selected: 0
}
}
}
// 2. Content templates (matched by DockTab.template)
FilesView := View{
width: Fill height: Fill
flow: Down
Label{text: "File list here"}
}
EditorView := View{
width: Fill height: Fill
Label{text: "Editor content"}
}
SearchView := View{
width: Fill height: Fill
Label{text: "Search panel"}
}
ConsoleView := View{
width: Fill height: Fill
Label{text: "Console output"}
}
}Dock Sub-Types Reference
DockSplitter:
axis-HorizontalorVerticalalign-Weighted(ratio),FromA(pixels),FromB(pixels)a- First pane content (DockTabs or DockSplitter)b- Second pane content (DockTabs or DockSplitter)
DockTabs:
tabs- Array of DockTab definitionsselected- Index of selected tabclosable- Whether tabs can be closed (bool)
DockTab:
name- Tab display texttemplate- LiveId matching a content template defined in the Dockkind- Tab kind identifier
---
Custom Widget Creation
Basic Custom Widget
To create a custom widget in Makepad 2.0, derive the required traits:
#[derive(Script, ScriptHook, Widget)]
pub struct MyWidget {
#[uid]
uid: WidgetUid,
#[source]
source: ScriptObjectRef, // REQUIRED: links to DSL definition
#[walk]
walk: Walk, // Size and position
#[layout]
layout: Layout, // Child layout rules
#[redraw]
#[live]
draw_bg: DrawQuad, // Background draw primitive
#[live]
draw_text: DrawText, // Text draw primitive
#[live]
text: String, // A DSL-settable property
#[rust]
my_state: i32, // Rust-only state (not settable from DSL)
#[rust]
area: Area, // Widget area for hit testing
}Key derive macros:
Script- Enables Splash script integrationScriptHook- Enables lifecycle hooks (on_before_apply, on_after_apply)Widget- Implements the Widget traitAnimator- Adds animation support (optional)WidgetRef- Generates the WidgetRef wrapper typeWidgetSet- Generates the WidgetSet typeWidgetRegister- Enables widget registration
Field attributes:
#[source]- ScriptObjectRef linking to DSL (REQUIRED)#[uid]- Unique widget identifier#[walk]- Walk (width, height, margin)#[layout]- Layout (flow, spacing, padding, align)#[redraw]- Mark field as triggering redraw when changed#[live]- DSL-settable field with default#[live(default_value)]- DSL-settable with explicit default#[rust]- Rust-only field, not settable from DSL#[apply_default]- Apply default values from DSL#[deref]- Delegate to inner widget (for wrapper widgets)#[visible]- Widget visibility field
Register Widget in script_mod!
script_mod! {
use mod.prelude.widgets_internal.*
use mod.widgets.*
mod.widgets.MyWidgetBase = #(MyWidget::register_widget(vm))
mod.widgets.MyWidget = set_type_default() do mod.widgets.MyWidgetBase{
width: Fit
height: Fit
// default property values
draw_bg +: {
color: #333
}
}
}Custom Draw Widget
For widgets that need custom drawing logic:
impl Widget for CustomDraw {
fn draw_walk(&mut self, cx: &mut Cx2d, _scope: &mut Scope, walk: Walk) -> DrawStep {
// Begin layout turtle
cx.begin_turtle(walk, self.layout);
// Get the computed rect
let rect = cx.turtle().rect();
// Draw custom shapes
self.draw_bg.draw_abs(cx, rect);
// Draw text at specific position
// self.draw_text.draw_walk(cx, walk, align, text);
// End turtle and capture area
cx.end_turtle_with_area(&mut self.area);
DrawStep::done()
}
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
// Handle hit events
match event.hits(cx, self.area) {
Hit::FingerDown(_fe) => {
// Handle touch/click down
}
Hit::FingerUp(_fe) => {
// Handle touch/click up
}
Hit::FingerHoverIn(_) => {
// Handle hover enter
}
Hit::FingerHoverOut(_) => {
// Handle hover leave
}
_ => ()
}
}
}Widget with Children (Container)
For container widgets that hold child widgets:
impl Widget for MyContainer {
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
cx.begin_turtle(walk, self.layout);
// Draw background if enabled
if self.show_bg {
self.draw_bg.begin(cx, walk, self.layout);
}
// Draw children
for (_id, child) in &self.children {
child.draw_all(cx, scope);
}
if self.show_bg {
self.draw_bg.end(cx);
}
cx.end_turtle_with_area(&mut self.area);
DrawStep::done()
}
}---
MapView Critical Rules
MapView renders vector tile-based geographic maps. It has strict requirements:
MUST use fixed pixel height
// CORRECT: fixed pixel height
MapView{
width: Fill
height: 400
}
// WRONG: will cause rendering issues
MapView{
width: Fill
height: Fill // NEVER use Fill
}
// WRONG: will cause rendering issues
MapView{
width: Fill
height: Fit // NEVER use Fit
}MUST wrap in container with new_batch
map_container := View{
new_batch: true // REQUIRED for MapView
width: Fill
height: 400
map := MapView{
width: Fill
height: 400
center_lon: -73.9857
center_lat: 40.7484
zoom: 14.0
dark_theme: true
}
}MapView Data Sources
use_local_mbtiles: true- Load tiles from local.mbtilesfile (default, offline)use_network: true- Fetch tiles from network (online mode)- If both are enabled, offline mode takes priority
style_light/style_dark- Theme style configurations with map rendering rules
---
Draw Batching (new_batch) - Detailed Rules
How Batching Works
Makepad batches consecutive draw calls using the same shader into a single GPU draw call for performance. The draw order follows the widget tree order.
The Text Visibility Problem
When a View with show_bg: true contains text widgets, the background quad and text quads may be batched into the same draw call. Since the background quad covers the entire view area, text drawn in the same batch appears behind the background, making it invisible.
Setting new_batch
// Pattern: colored container with text
card := RoundedView{
new_batch: true // Forces a new GPU draw batch
show_bg: true
draw_bg.color: #2a2a3a
title := Label{
text: "Card Title"
draw_text.color: #fff
}
}When new_batch is CRITICAL
1. Any View with show_bg containing text children:
SolidView{
new_batch: true
show_bg: true
draw_bg.color: #444
Label{text: "Must be visible"}
}2. Views with hover/press effects containing text: Without new_batch, text vanishes during hover because the draw_bg shader re-renders with different instance values, pushing text behind the background.
3. MapView containers:
View{
new_batch: true
MapView{...}
}When new_batch is NOT needed
View{}withoutshow_bg(invisible layout only)- Views containing only other Views (no direct text widgets)
- Text widgets themselves (Label, H1, etc.)
- Widgets that already force their own batch internally
---
Splitter Usage Pattern
content := Splitter{
axis: Horizontal
align: Weighted(0.3)
a := View{
width: Fill
height: Fill
// Left/top panel content
Label{text: "Panel A"}
}
b := View{
width: Fill
height: Fill
// Right/bottom panel content
Label{text: "Panel B"}
}
}Splitter Axis Values
SplitterAxis.Horizontal- Left/right split (default)SplitterAxis.Vertical- Top/bottom split
Splitter Align Values
SplitterAlign.Weighted(0.5)- Proportional split (0.0 to 1.0)SplitterAlign.FromA(200.0)- Fixed pixels from left/topSplitterAlign.FromB(200.0)- Fixed pixels from right/bottom
---
FoldHeader Usage Pattern
FoldHeader{
header := View{
width: Fill
height: Fit
padding: 10
FoldButton{}
Label{text: "Section Title"}
}
body := View{
width: Fill
height: Fit
padding: Inset{left: 20}
Label{text: "Collapsible content here"}
}
}The opened value animates between 0.0 (closed) and 1.0 (open). The body's height is interpolated based on this value.
---
Modal Usage Pattern
modal := Modal{
// Override the content slot
content +: {
width: 400
height: Fit
padding: 20
flow: Down
spacing: 10
show_bg: true
draw_bg.color: #333
H3{text: "Dialog Title"}
P{text: "Dialog message content"}
View{
width: Fill
height: Fit
flow: Right
align: Align{x: 1.0}
spacing: 10
Button{text: "Cancel"}
Button{text: "OK"}
}
}
}Modal Control (from Rust)
// Open modal
self.modal(id!(modal)).open(cx);
// Close modal
self.modal(id!(modal)).close(cx);---
PageFlip Usage Pattern
page_flip := PageFlip{
active_page: page_one
page_one := View{
width: Fill height: Fill
Label{text: "Page One"}
}
page_two := View{
width: Fill height: Fill
Label{text: "Page Two"}
}
}Switching Pages (from Rust)
self.page_flip(id!(page_flip)).set_active_page(cx, id!(page_two));---
Common Widget Access Patterns (Rust)
Accessing Child Widgets
// Access a specific child by id path
self.view.label(ids!(title)).set_text(cx, "New Title");
self.view.button(ids!(submit_btn)).set_text(cx, "Submit");
self.view.text_input(ids!(name_input)).set_text(cx, "default");
// Access nested children
self.view.label(ids!(container.inner.title)).set_text(cx, "Nested");
// Read text input value
let text = self.view.text_input(ids!(name_input)).text();
// Get/set slider value
let val = self.view.slider(ids!(volume)).value();
// Get selected dropdown item
let idx = self.view.drop_down(ids!(selector)).selected_item();Handling Widget Actions
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
self.view.handle_event(cx, event, scope);
for action in cx.actions() {
// Button clicked
if self.view.button(ids!(my_btn)).clicked(action) {
// handle click
}
// Text input changed
if let Some(text) = self.view.text_input(ids!(my_input)).changed(action) {
log!("Text changed: {}", text);
}
// Slider changed
if let Some(val) = self.view.slider(ids!(my_slider)).changed(action) {
log!("Slider: {}", val);
}
// CheckBox/Toggle toggled
if let Some(active) = self.view.check_box(ids!(my_check)).changed(action) {
log!("Active: {}", active);
}
// DropDown selected
if let Some(item) = self.view.drop_down(ids!(my_dd)).selected(action) {
log!("Selected: {}", item);
}
}
}Makepad 2.0 Widget Catalog
Complete reference for all built-in widgets in Makepad 2.0. All widgets are defined using script_mod! blocks and used in Splash DSL syntax.
---
View Containers
All View variants inherit from ViewBase. Views are the fundamental layout containers.
Base View
| Widget | Background | Shape | Notes |
|---|---|---|---|
View | none | - | Invisible layout container. Setting show_bg: true shows an ugly green default; use SolidView instead for colored backgrounds |
SolidView | flat color | rectangle | Basic colored rectangle |
RoundedView | color | rounded rect | draw_bg.border_radius (uniform float, default 2.5) |
RoundedAllView | color | per-corner radius | draw_bg.border_radius is vec4 (top-left, top-right, bottom-right, bottom-left) |
RoundedXView | color | left/right radius | draw_bg.border_radius is vec2 (left radius, right radius) |
RoundedYView | color | top/bottom radius | draw_bg.border_radius is vec2 (top radius, bottom radius) |
RectView | color | rectangle with border | Supports border_size, border_color, border_inset, gradient |
RectShadowView | color + shadow | rectangle | clip_x/clip_y default false for shadow overflow |
RoundedShadowView | color + shadow | rounded rect | clip_x/clip_y default false for shadow overflow |
CircleView | color | circle | draw_bg.border_radius overrides auto-calculated radius |
HexagonView | color | hexagon | draw_bg.border_radius.x sets explicit radius (vec2) |
GradientXView | horizontal gradient | rectangle | Set draw_bg.color and draw_bg.color_2 |
GradientYView | vertical gradient | rectangle | Set draw_bg.color and draw_bg.color_2 |
CachedView | texture-cached | rectangle | texture_caching: true; renders children to texture |
CachedRoundedView | texture-cached | rounded rect | Texture-cached with rounded corners and optional border |
Scrollable Views
| Widget | Scrolls | Notes |
|---|---|---|
ScrollXYView | both axes | Horizontal and vertical scroll bars |
ScrollXView | horizontal only | Horizontal scroll bar only |
ScrollYView | vertical only | Vertical scroll bar only |
View Properties (from ViewBase struct)
Layout properties (set directly on widget):
width,height- Size values:Fill,Fit, fixed pixels (e.g.,100), or100.0flow- Layout direction:Down,Right,Overlay,Right {wrap: true}spacing- Gap between children (pixels)padding- Inner padding: single value orInset{left: 0. right: 0. top: 0. bottom: 0.}margin- Outer margin: same format as paddingalign- Child alignment:Center,TopLeft,Align{x: 0.5 y: 0.5}clip_x,clip_y- Clip overflow (default depends on widget)
Display properties:
show_bg- Whether to draw the background (defaultfalsefor View)visible- Widget visibility (defaulttrue)new_batch- Force new GPU draw batch (CRITICAL for text-over-background)cursor- Mouse cursor:MouseCursor.Hand,MouseCursor.Default, etc.grab_key_focus- Whether view captures keyboard focus (defaulttrue)capture_overload- Capture pointer events even when scrolling
draw_bg properties (for views with show_bg: true):
color- Primary fill color (instance)color_2- Secondary color for gradients (instance, defaultvec4(-1)= disabled)border_size- Border thickness (uniform)border_radius- Corner rounding (type varies by widget)border_color- Border color (instance)border_color_2- Secondary border gradient color (instance)border_inset- Border inset (uniform vec4)shadow_color- Shadow color (instance, shadow views only)shadow_radius- Shadow blur radius (uniform, shadow views only)shadow_offset- Shadow offset (uniform vec2, shadow views only)color_dither- Dithering amount (uniform, default 1.0)gradient_fill_horizontal- Fill gradient direction: 0.0 = vertical, 1.0 = horizontal (uniform)gradient_border_horizontal- Border gradient direction (uniform)
---
Text Widgets
Labels and Headings
| Widget | Style | Notes |
|---|---|---|
Label | Regular text | Default: width: Fit, height: Fit. Does NOT support animator or cursor! |
Labelbold | Bold text | Bold font variant of Label |
LabelGradientX | Horizontal gradient text | Set draw_text.color and draw_text.color_2 |
LabelGradientY | Vertical gradient text | Set draw_text.color and draw_text.color_2 |
TextBox | Paragraph text | width: Fill, uses theme.font_size_p |
P | Paragraph | Same as TextBox |
Pbold | Bold paragraph | Bold font variant |
Pitalic | Italic paragraph | Italic font variant |
Pbolditalic | Bold italic paragraph | Combined bold italic |
H1 | Heading 1 | width: Fill, theme.font_size_1, bold, theme.color_text_hl |
H1italic | Heading 1 italic | Bold italic variant |
H2 | Heading 2 | theme.font_size_2, bold |
H2italic | Heading 2 italic | Bold italic variant |
H3 | Heading 3 | theme.font_size_3, bold |
H3italic | Heading 3 italic | Bold italic variant |
H4 | Heading 4 | theme.font_size_4, bold |
H4italic | Heading 4 italic | Bold italic variant |
IconSet | Icon font | Uses theme.font_icons, font_size 100 |
CRITICAL: Default text color is WHITE (theme.color_label_outer). You MUST set draw_text.color explicitly on light backgrounds, or text will be invisible.
draw_text properties:
color- Text color (default:theme.color_label_outer, which is white/light)color_2- Secondary text color for gradient (default disabled)text_style- Font style:theme.font_regular{font_size: 11},theme.font_bold{...},theme.font_italic{...},theme.font_bold_italic{...}color_dither- Dithering amount (uniform)gradient_fill_horizontal- Gradient direction (0.0 = vertical, 1.0 = horizontal)
Editable Text
| Widget | Notes |
|---|---|
TextInput | Full-featured text input (themed with border and bevels) |
TextInputFlat | Flat styled text input (base style) |
TextInput properties:
text- The text content (String)is_password- Mask text as password (bool)is_read_only- Prevent editing (bool)is_numeric_only- Only allow numbers (bool)empty_text- Placeholder text when empty (String)input_mode- Keyboard input modeautocapitalize- Auto-capitalize behaviorautocorrect- Auto-correct behaviorreturn_key_type- Return key type
TextInput draw_bg instances: hover, down, focus, disabled, empty
Rich Text and Links
| Widget | Notes |
|---|---|
LinkLabel | Clickable text link with hover/press states |
TextFlow | Rich text container for mixed content (base for Markdown/Html) |
Markdown | Markdown rendering (feature-gated with pulldown-cmark; set body property) |
Html | HTML rendering (feature-gated; set body property) |
---
Button Widgets
| Widget | Style | Notes |
|---|---|---|
Button | Standard themed button | Beveled with gradient |
ButtonFlat | Flat button | Base button style, rounded corners |
ButtonFlatter | Minimal button | Invisible/minimal background |
ButtonGradientX | Horizontal gradient button | Gradient fill |
ButtonGradientY | Vertical gradient button | Gradient fill |
ButtonIcon | Button with icon | Icon + text |
ButtonFlatIcon | Flat button with icon | |
ButtonFlatterIcon | Minimal button with icon | |
ButtonGradientXIcon | Gradient X with icon | |
ButtonGradientYIcon | Gradient Y with icon |
Button properties:
text- Button label text (String)draw_bg- Background drawingdraw_text- Text drawingdraw_icon- SVG icon drawingicon_walk- Walk for icon sizing (defaultWalk{width: 22.0, height: Fit})label_walk- Walk for label sizinganimator- Animation states
Button draw_bg instance variables: hover, down, focus, disabled
Color uniforms (draw_bg):
color,color_hover,color_down,color_focus,color_disabledcolor_2,color_2_hover,color_2_down,color_2_focus,color_2_disabledborder_color,border_color_hover,border_color_down,border_color_focus,border_color_disabledborder_color_2,border_color_2_hover,border_color_2_down,border_color_2_focus,border_color_2_disabledborder_size,border_radius
Button draw_text color variants:
color,color_hover,color_down,color_focus,color_disabled
---
Toggle Widgets (CheckBox, Toggle, RadioButton)
CheckBox Variants
| Widget | Style | Notes |
|---|---|---|
CheckBox | Themed check box | Beveled, themed colors |
CheckBoxFlat | Flat check box | Base style |
CheckBoxCustom | Custom check box | For custom styling |
Toggle Variants
| Widget | Style | Notes |
|---|---|---|
Toggle | Themed toggle switch | Pill-shaped switch |
ToggleFlat | Flat toggle switch | Base style |
RadioButton Variants
| Widget | Style | Notes |
|---|---|---|
RadioButton | Themed radio | Circular indicator |
RadioButtonFlat | Flat radio | Base style |
RadioButtonFlatter | Minimal radio | |
RadioButtonTabFlat | Tab-style radio | Tab-like appearance |
RadioButtonTab | Themed tab radio |
Toggle/CheckBox/RadioButton properties:
text- Label textactive- Current on/off state (not directly settable; controlled by animator)draw_bg- Background drawingdraw_text- Label text drawinglabel_walk- Label sizinganimator- Animation states
draw_bg instance variables: hover, down, focus, active, disabled
CheckBox-specific draw_bg uniforms:
size- Check box size in pixels (default 15.0)mark_size- Check mark scale (default 0.65)mark_color,mark_color_hover,mark_color_down,mark_color_active,mark_color_active_hover,mark_color_focus,mark_color_disabled- Standard
color,border_colorvariants (with_hover,_down,_active,_focus,_disabledsuffixes)
---
Input Widgets
Slider Variants
| Widget | Style | Notes |
|---|---|---|
Slider | Themed slider | Full-featured with bevels |
SliderFlat | Flat slider | Base flat style |
SliderMinimal | Minimal slider | Simplest style |
SliderMinimalFlat | Minimal flat slider | |
SliderGradientX | Gradient X slider | Horizontal gradient fill |
SliderGradientY | Gradient Y slider | Vertical gradient fill |
SliderRound | Round handle slider | Circular handle |
SliderRoundFlat | Round flat slider | |
SliderRoundGradientX | Round gradient X | |
SliderRoundGradientY | Round gradient Y | |
Rotary | Rotary knob | Circular dial control |
RotaryFlat | Flat rotary knob | |
RotaryGradientY | Gradient rotary knob |
Slider properties:
min- Minimum value (f64, default 0.0)max- Maximum value (f64, default 1.0)step- Step increment (f64, default 0.0 = continuous)default- Default/initial value (f64)precision- Decimal places to display (usize, default 2)axis- Drag direction:DragAxis.Horizontal(default) orDragAxis.Verticaltext- Label textbind- Data binding path (String)draw_bg,draw_text,label_walk,label_align
Slider draw_bg instance variables: hover, focus, drag, disabled
Slider-specific draw_bg uniforms:
val_color,val_color_hover,val_color_focus,val_color_drag,val_color_disabledhandle_color,handle_color_hover,handle_color_focus,handle_color_drag,handle_color_disabledhandle_size,offset_y- Standard
color,border_colorvariants with state suffixes
DropDown Variants
| Widget | Style | Notes |
|---|---|---|
DropDown | Themed dropdown | Full-featured with bevels |
DropDownFlat | Flat dropdown | Base flat style |
DropDownGradientX | Gradient X dropdown | |
DropDownGradientY | Gradient Y dropdown |
DropDown properties:
labels- Array of string options (Vec<String>)selected_item- Currently selected index (usize)bind- Data binding pathbind_enum- Enum data bindingpopup_menu- Popup menu configurationdraw_bg,draw_text
DropDown draw_bg instances: hover, focus, down, active, disabled
---
Media Widgets
| Widget | Notes |
|---|---|
Image | Static/animated image. Default: width: 100, height: 100 |
Video | Video playback. Default: width: 100, height: 100 |
Svg | Renders external .svg files with optional animation and custom GPU shaders |
Icon | SVG icon rendering |
IconGradientX | Gradient X icon |
IconGradientY | Gradient Y icon |
IconRotated | Rotatable icon (draw_icon.rotation_angle) |
LoadingSpinner | Animated circular loading indicator |
MathView | LaTeX math rendering (requires makepad_latex_math crate) |
MapView | Geographic map rendering (vector tile-based) |
Image Properties
fit- How image fits container:ImageFit.Stretch(default),ImageFit.Horizontal,ImageFit.Vertical,ImageFit.Smallest,ImageFit.Biggest,ImageFit.Sizewidth_scale- Scale factor for width (f64, default 1.0)src- Image source:http_resource("url")orcrate_resource("self:path")animation- Animation mode:ImageAnimation.Loop(default),.Stop,.Once,.Bounce,.Frame(f64),.Factor(f64),.OnceFps(f64),.LoopFps(f64),.BounceFps(f64)draw_bg.opacity- Image opacity (0.0 to 1.0)draw_bg.image_scale- Scale vec2draw_bg.image_pan- Pan offset vec2
Svg Widget Properties
The Svg{} widget loads and renders external .svg files. It supports SVG gradients, filters, <animate> elements, and custom GPU shader effects.
Properties:
draw_svg- The DrawSvg shader instance (inherits from DrawVector)draw_svg.svg- SVG resource:crate_resource("self:path/to/file.svg")orhttp_resource("https://url/file.svg")draw_svg.color- Tint color override. Defaultvec4(-1,-1,-1,-1)= use original SVG colors.draw_svg.svg_scale- GPU-side scale uniformvec2(default1.0, 1.0)draw_svg.svg_offset- GPU-side offset uniformvec2(default0.0, 0.0)draw_svg.svg_time- Animation time uniform (float, auto-updated whenanimating: true)animating- Enable per-frame time updates for SVG<animate>elements and custom shader effects (defaulttrue)width,height- Widget size (defaultFit)
Basic usage:
Svg{
width: 300 height: 300
draw_svg +: { svg: crate_resource("self:resources/my_icon.svg") }
}Load from URL:
Svg{
width: 300 height: 100
draw_svg +: { svg: http_resource("https://example.com/logo.svg") }
}With custom GPU shader effect:
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 id = self.v_shape_id;
let t = self.svg_time;
if id < 0.5 { return base }
return mix(base, vec4(1.0, 0.0, 0.0, 1.0), sin(t) * 0.5 + 0.5);
}
}
}Static SVG (no animation):
Svg{
width: 32 height: 32
animating: false
draw_svg +: { svg: crate_resource("self:resources/icons/icon_file.svg") }
}IMPORTANT: Use draw_svg +: (merge operator) to set svg and shader properties.
Icon Properties
draw_icon.svg- SVG resource:crate_resource("self:resources/icons/name.svg")draw_icon.color- Icon tint coloricon_walk- Walk for icon sizing (defaultWalk{width: 17.5, height: Fit})draw_bg.color- Background color (instance)
MathView Properties
text- LaTeX math expression (String)font_size- Font size (f64, default 11.0)color- Text color (default#fff)baseline_offset- Vertical baseline adjustment (default -2.0)
MapView Properties
center_lon- Center longitude (f64, default 4.9041)center_lat- Center latitude (f64, default 52.3676)zoom- Zoom level (f64, default 14.0)min_zoom- Minimum zoom (f64, default 11.0)max_zoom- Maximum zoom (f64, default 17.0)dark_theme- Use dark map style (bool, default false)use_network- Enable network tile fetching (bool, default false)use_local_mbtiles- Use local mbtiles file (bool, default true)
CRITICAL MapView rules:
- MUST use fixed pixel height (e.g.,
height: 400). Never useFitorFillfor height. - MUST wrap in a container with
new_batch: true.
---
Layout Widgets
| Widget | Notes |
|---|---|
Hr | Horizontal divider/rule. width: Fill, themed bevel line |
Vr | Vertical divider/rule. height: Fill, themed bevel line |
Filler | Empty spacer. width: Fill, height: Fill |
Splitter | Resizable split pane with drag handle |
FoldHeader | Collapsible section with header and body |
ScrollBar | Scroll bar component (used internally by ScrollViews) |
Splitter Properties
axis- Split direction:SplitterAxis.Horizontal(default) orSplitterAxis.Verticalalign- Split position:SplitterAlign.FromA(pixels)- Fixed distance from startSplitterAlign.FromB(pixels)- Fixed distance from endSplitterAlign.Weighted(ratio)- Proportional (default 0.5)a :=/b :=- Named child slots for the two panessize- Splitter bar thickness (default 6.0)min_horizontal,max_horizontal- Horizontal drag limits (default 50.0)min_vertical,max_vertical- Vertical drag limits (default 50.0)
FoldHeader Properties
header :=/body :=- Named child slotsbody_walk- Walk for body (default:Walk{width: Fill, height: Fit})animator.active- Controls open/close state (@on = open, @off = closed)opened- Animation value (0.0 = closed, 1.0 = open)
ScrollBar Properties
bar_size- Scroll bar width in pixels (default 10.0)bar_side_margin- Margin from edge (default 3.0)min_handle_size- Minimum handle size (default 30.0)
---
List Widgets
| Widget | Notes |
|---|---|
PortalList | Virtualized scrolling list (only renders visible items) |
FlatList | Non-virtualized list (renders all items) |
PortalList Properties
flow- DefaultDown(vertical list)scroll_bar- Scroll bar configuration:ScrollBar{}capture_overload- Defaulttrue- Templates defined with
:=syntax are stored in templates HashMap - Driven programmatically from Rust via
draw_walk()loop
FlatList Properties
- Similar to PortalList but renders all children
- Suitable for small, fixed-size lists
---
Dock System
| Widget | Notes |
|---|---|
Dock | Full-featured tabbed dock layout (themed with round corners) |
DockFlat | Flat-styled dock layout |
Dock Sub-Types (DSL only)
| Type | Notes |
|---|---|
DockSplitter | Splits dock into two regions. Properties: axis, align, a, b |
DockTabs | Tab container. Properties: tabs (array of DockTab), selected, closable |
DockTab | Individual tab. Properties: name, template, kind |
Dock Properties
tab_bar- Tab bar style (e.g.,TabBarGradientY{},TabBarFlat{})splitter- Splitter style (e.g.,Splitter{})root :=- Root dock layout node (DockSplitter or DockTabs)- Content templates defined with
:=syntax
---
Navigation Widgets
| Widget | Notes |
|---|---|
Modal | Overlay dialog with dimmed background. Uses content +: for dialog content |
Tooltip | Hover tooltip with positioned content |
PopupNotification | Toast-style notification overlay (top-right aligned) |
SlidePanel | Animated side panel with slide-in/out |
ExpandablePanel | Draggable panel overlay with touch gesture |
PageFlip | Page switching container (only one page visible at a time) |
StackNavigation | iOS-style stack-based navigation with back button |
Modal Properties
content :=- Dialog content container (View, default:width: Fit, height: Fit, flow: Down)bg_view :=- Background overlay (default: semi-transparent black#000000B3)flow: Overlay(default)- Emits
ModalAction::Dismissedon background click
SlidePanel Properties
side- Slide direction:SlideSide.Left(default),SlideSide.Right,SlideSide.Topactive- Animation position (0.0 = visible, 1.0 = hidden)animator.active- @on = slide in, @off = slide out
PageFlip Properties
active_page- Currently visible page (LiveId)lazy_init- Whether to lazily initialize pages (default false)- Pages defined as templates with
:=syntax
StackNavigation
- Contains
StackNavigationViewchildren StackViewHeader- Pre-built header with back button and titleStackNavigationView- Individual stack page (default:visible: false)
---
Special Widgets
| Widget | Notes |
|---|---|
FileTree | File hierarchy tree (programmatically driven from Rust) |
CachedWidget | Cached rendering wrapper |
Vector | SVG-like vector graphics drawing |
Window | Application window container |
Root | Root widget container |
---
Draw Batching (new_batch)
Widgets using the same shader are batched into a single GPU draw call. This causes problems when text needs to appear on top of a background:
Problem: Text drawn in the same batch as a background quad will be rendered behind it, making text invisible.
Solution: Set new_batch: true on any View with show_bg: true that contains text children.
my_card := RoundedView{
new_batch: true // CRITICAL: forces new draw batch
show_bg: true
draw_bg.color: #333
label := Label{
text: "This text is now visible"
}
}When new_batch is required:
- Any View with
show_bg: truethat contains Label, H1-H4, TextBox, P, or other text widgets - Views with hover effects (draw_bg instance variables that change) containing text
- MapView containers (MUST have new_batch on parent)
When new_batch is NOT needed:
- View without show_bg (invisible layout containers)
- Views that only contain other Views (no direct text children)
- The innermost text widgets themselves