Form Composition
Input · Select · Button同一尺寸档的 Input、Select、Button 混排:筛选工具栏与业务表单。
BEHAVIOR CONTRACT
三者共用 ControlSize(外框高 XS 20 / SM 24 / MD 32 / LG 40),同档下高度、圆角、字号、图标与间距对齐。
RECORDED INTERACTION
Harness 在工具栏里筛选状态与负责人、输入搜索词,再在表单里填写客户、选择区域和金额。
pub fn build(scope: *ui.Scope, cx: *ui.Cx) anyerror!*ui.Node {
const a = cx.allocator;
const root = try ui.box(cx, .{ .direction = .column, .gap = 16 }, .{});
tag(root, "story.formcompose.root");
try root.appendChild(a, try heading(cx, "Filter toolbar · same size"));
try root.appendChild(a, try caption(cx, "Input / Select / Button share ControlSize: XS 20 · SM 24 · MD 32 · LG 40 px"));
inline for (sizes) |spec| {
try root.appendChild(a, try filterToolbar(spec, scope, cx));
}
try root.appendChild(a, try heading(cx, "Business form · MD"));
try root.appendChild(a, try orderForm(scope, cx));
return root;
}这是 Storybook 中该 story 的原样代码(zenit 5f9add5+wip 2026-09-30)。其中 W 即 ui.widgets,col / row / label 是 Storybook 内的布局小工具。
SelectProps
ui.widgets.Selectfn mountSelect(props: SelectProps, scope: *Scope, cx: *Cx) !SelectMount字段
类型
默认值
说明
options[]const SelectOption&.{}—
placeholder[]const u8"Select an option..."—
widthf32352—
sizeSelectSize.md—
modeSelectMode.single.single—
searchableboolfalse—
show_selected_value_in_searchbooltrueKeep the selected label in a searchable single-select trigger. Set to false for search-first presentations where the trigger should retain its search placeholder while the selected row remains checked.
clearableboolfalse—
leading_icon?svg_assets.Assetnull—
initial_selected[]const usize&.{}—
disabledboolfalse—
max_dropdown_heightf32280—
on_change?core.HandlerRefnull—
InputProps
ui.widgets.Inputfn Input(props: InputProps) InputBuilder字段
类型
默认值
说明
initial_value?[]const u8null初始值。**只在 mount 时读取一次** —— 之后改无效。 首帧之后要写入内容,用 `mountResult()` 拿 `result.state` 再调 `setText()`(2026-07-31 新增)。
growableboolfalse—
placeholder?[]const u8null占位符
placeholder_color?Colornull占位符文本颜色覆盖
input_typeInputType.text.number.email.password.tel.text输入类型
sizeInputSize.md尺寸 (统一 ControlSize,默认 md;外框高度 = padding_y × 2 + font_size × line_height, 默认主题 xs=20 / sm=24 / md=32 / lg=40)
label_text?[]const u8null标签
helper?[]const u8null辅助文本
error_msg?[]const u8null错误信息
requiredboolfalse必填
readonlyboolfalse只读
disabledboolfalse禁用
width?f32null宽度
leading_icon_asset?svg_assets.Assetnull左侧图标
append_text?[]const u8null右侧附加文本(如计数)
append_icon_asset?svg_assets.Assetnull右侧附加图标(如 clear / eye)
embeddedboolfalse嵌入复合控件时仅保留文本编辑能力,由父控件绘制统一 shell。 Select/ComboBox 等组件使用它避免出现双层 border / focus ring。
state_id?u64null状态 ID (用于 StateStore, 如果为 null 则使用自动生成的 ID)
on_change?core.HandlerRefnull值变化回调 2026-07-31 并轨:统一 ?core.HandlerRef(用 cx.strHandlerFrom 构造以拿到文本)。
ButtonProps
ui.widgets.Buttonfn Button(props: ButtonProps) ButtonBuilder字段
类型
默认值
说明
label?[]const u8null标签文本
variantButtonVariant.primary.secondary.ghost.danger.link.field.primary变体
sizeButtonSize.md尺寸
icon_onlyboolfalse图标模式(只显示图标)
loadingboolfalse加载中
disabledboolfalse禁用
blockboolfalse块级(宽度填充) 非 block Button 保持 intrinsic 宽度:父容器交叉轴为 stretch(默认)时按 start 排而不被拉伸;父显式 align_items=.center/.end 时照常居中/靠尾。
on_click?core.HandlerRefnull点击 handler
icon?u32null图标纹理 ID(放在 label 文本左侧)
icon_asset?svg_assets.AssetnullSVG 图标资源(优先于 texture icon)
icon_size?f32null图标尺寸(null = 跟随 control metrics 的 icon_size;应 ≤ 行高)
icon_tint?Colornull图标 tint 颜色(默认跟随 textColor)
on_event?GenericEventCallbacknull通用事件处理(支持 hover/key 等复合事件)
event_context?*anyopaquenull事件上下文
样式覆盖
styleStyleOverride.{}默认态样式覆盖
hover_style?StyleOverridenullhover 态样式覆盖
pressed_style?StyleOverridenullpressed 态样式覆盖
SelectMount
ui.widgets.Select字段
类型
默认值
说明
wrapper*Node—
—
trigger*Node—
—
panel*Node—
—
state*SelectState—
—
is_open*Signal(bool)—
—
*Node
ui.widgets.Inputmount 直接返回 *Node,把它 append 到父节点即可。
*Node
ui.widgets.Buttonmount 直接返回 *Node,把它 append 到父节点即可。