components/input
入力とフォーム · 08 / 64

Input

ui.widgets.Input

1 行のテキスト、メール、パスワード、検索の入力。

BEHAVIOR CONTRACT

label、helper、error、required、読み取り専用、disabled、先頭アイコン、IME が完全な編集コアを共有します。

RECORDED INTERACTION

harness が Name フィールドにフォーカスし、実際のテキストを入力します。

examples/storybook/stories.zig:2888
// ── 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;
}
GitHub でソースを見るexamples/storybook/stories.zig:2888

Storybook にあるこの story のコードそのままです(zenit 5f9add5+wip 2026-09-30)。W は ui.widgets のことで、col / row / label は Storybook 内の小さなレイアウトヘルパーです。

zenit · デュアルライセンスオープンソースプロジェクトは GPL-3.0-only のもとで無料で使えます。クローズドソースや商用製品には商用ライセンスが必要です。作者への連絡先:zongyi.xzy#gmail.com(# を @ に置き換え)zenit 5f9add5+wip 2026-09-30