Input
ui.widgets.Input한 줄 텍스트, 이메일, 비밀번호, 검색 입력.
BEHAVIOR CONTRACT
label, helper, error, required, 읽기 전용, disabled, 앞쪽 아이콘, IME가 완전한 편집 코어를 공유합니다.
RECORDED INTERACTION
harness가 Name 필드에 포커스를 두고 실제 텍스트를 입력합니다.
// ── Input ──
pub fn buildInput(scope: *ui.Scope, cx: *ui.Cx) anyerror!*ui.Node {
const a = cx.allocator;
const icons = ui.assets.common;
const c = try col(cx, 12);
// ── 类型 ──
try c.appendChild(a, try label(cx, "Types"));
const n1 = try W.Input(.{ .label_text = "Name", .placeholder = "Your name", .width = 320 }).mount(scope, cx);
n1.meta.ownership.meta.test_id = "story.input.name";
try c.appendChild(a, n1);
try c.appendChild(a, try W.Input(.{ .label_text = "Email", .input_type = .email, .placeholder = "you@example.com", .width = 320 }).mount(scope, cx));
try c.appendChild(a, try W.Input(.{ .label_text = "Password", .input_type = .password, .placeholder = "••••••••", .width = 320 }).mount(scope, cx));
// ── 尺寸 ──
try c.appendChild(a, try label(cx, "Sizes (sm / md / lg)"));
inline for (.{ W.input.InputSize.sm, .md, .lg }, .{ "Small", "Medium", "Large" }) |sz, ph| {
try c.appendChild(a, try W.Input(.{ .size = sz, .placeholder = ph, .width = 320 }).mount(scope, cx));
}
// ── 带图标 / append ──
try c.appendChild(a, try label(cx, "With icon / append"));
try c.appendChild(a, try W.Input(.{ .label_text = "Search", .placeholder = "Type to search…", .leading_icon_asset = icons.search, .width = 320 }).mount(scope, cx));
try c.appendChild(a, try W.Input(.{ .label_text = "Website", .placeholder = "mysite", .append_text = ".com", .width = 320 }).mount(scope, cx));
// ── 状态:required / helper / error / readonly / disabled ──
try c.appendChild(a, try label(cx, "States"));
try c.appendChild(a, try W.Input(.{ .label_text = "Required", .placeholder = "Mandatory", .required = true, .width = 320 }).mount(scope, cx));
try c.appendChild(a, try W.Input(.{ .label_text = "With helper", .placeholder = "Username", .helper = "3–20 characters", .width = 320 }).mount(scope, cx));
try c.appendChild(a, try W.Input(.{ .label_text = "With error", .initial_value = "bad value", .error_msg = "This field is invalid", .width = 320 }).mount(scope, cx));
try c.appendChild(a, try W.Input(.{ .label_text = "Readonly", .initial_value = "Read only value", .readonly = true, .width = 320 }).mount(scope, cx));
try c.appendChild(a, try W.Input(.{ .label_text = "Disabled", .placeholder = "Cannot type", .disabled = true, .width = 320 }).mount(scope, cx));
return c;
}Storybook에 있는 이 story의 원본 코드입니다(zenit 5f9add5+wip 2026-09-30). W는 ui.widgets이며, col / row / label은 Storybook 내부의 작은 레이아웃 헬퍼입니다.
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 构造以拿到文本)。
*Node
ui.widgets.Inputmount는 *Node을(를) 직접 반환합니다. 부모 노드에 append하면 됩니다.