---
title: "Componente Gestures — zenit Zig UI"
description: "Arbitraje de gestos para clic simple, doble, triple y pulsación larga. Los gestos sobre una misma área de clic se arbitran por ventana de tiempo y solo uno…"
url: https://zenit.z.express/es/components/multiclick
language: es
alternate_en: https://zenit.z.express/components/multiclick.md
alternate_zh: https://zenit.z.express/zh/components/multiclick.md
alternate_ja: https://zenit.z.express/ja/components/multiclick.md
alternate_ko: https://zenit.z.express/ko/components/multiclick.md
alternate_fr: https://zenit.z.express/fr/components/multiclick.md
alternate_de: https://zenit.z.express/de/components/multiclick.md
project: zenit v0.1.0-alpha (Zig 0.15.2, macOS)
source: https://github.com/version-next/zenit
---

# Gestures

`ui.interaction`

Arbitraje de gestos para clic simple, doble, triple y pulsación larga.

[Video](https://zenit.z.express/media/stories/multiclick.mp4?v=e6fbe37258)

**BEHAVIOR CONTRACT**

Los gestos sobre una misma área de clic se arbitran por ventana de tiempo y solo uno gana.

**RECORDED INTERACTION**

El harness hace doble clic en el área; el contador double aumenta.

`examples/storybook/stories.zig:4695`

```zig
pub fn buildMultiClick(scope: *ui.Scope, cx: *ui.Cx) anyerror!*ui.Node {
    const a = cx.allocator;
    const c = try col(cx, 12);
    try c.appendChild(a, try label(cx, "Gesture arena — tap/double/triple counts + press-and-hold long_press (500ms) + pointer-cancel state"));

    const pad = try ui.box(cx, .{
        .width = .{ .px = 320 },
        .height = .{ .px = 140 },
        .background = light.color.bg_secondary,
        .align_items = .center,
        .justify = .center,
    }, .{});
    (try pad.style.ensureExtFallible(a)).corner_radius = ui.CornerRadius.uniform(10);
    pad.meta.ownership.meta.test_id = "story.multiclick.pad";
    try pad.appendChild(a, try ui.text(cx, "click / double-click / hold", .{ .font_size = 13, .color = light.color.fg_secondary }));
    try c.appendChild(a, pad);

    const single_label = try ui.text(cx, "single: 0", .{ .font_size = 13, .color = light.color.fg_primary });
    single_label.meta.ownership.meta.test_id = "story.multiclick.single";
    const double_label = try ui.text(cx, "double: 0", .{ .font_size = 13, .color = light.color.fg_primary });
    double_label.meta.ownership.meta.test_id = "story.multiclick.double";
    const triple_label = try ui.text(cx, "triple: 0", .{ .font_size = 13, .color = light.color.fg_primary });
    triple_label.meta.ownership.meta.test_id = "story.multiclick.triple";
    const long_label = try ui.text(cx, "long: idle", .{ .font_size = 13, .color = light.color.fg_primary });
    long_label.meta.ownership.meta.test_id = "story.multiclick.long";
    try c.appendChild(a, single_label);
    try c.appendChild(a, double_label);
    try c.appendChild(a, triple_label);
    try c.appendChild(a, long_label);

    const st = try cx.bindState(MultiClickStory, .{
        .cx = cx,
        .single_label = single_label,
        .double_label = double_label,
        .triple_label = triple_label,
        .long_label = long_label,
    });
    st.alive = true;
    st.rec_ids[0] = try cx.registerGesture(pad, .tap, .{}, MultiClickStory.onGesture, @ptrCast(st));
    st.rec_ids[1] = try cx.registerGesture(pad, .double_tap, .{}, MultiClickStory.onGesture, @ptrCast(st));
    st.rec_ids[2] = try cx.registerGesture(pad, .triple_tap, .{}, MultiClickStory.onGesture, @ptrCast(st));
    st.rec_ids[3] = try cx.registerGesture(pad, .long_press, .{}, MultiClickStory.onGesture, @ptrCast(st));

    pad.meta.per_frame.hooks.slots.anim_state = @ptrCast(st);
    pad.meta.per_frame.hooks.before_render.main = MultiClickStory.tickHook;

    const rc = try a.create(MultiClickCleanup);
    rc.* = .{ .cx = cx, .st = st };
    try scope.registerResource(@ptrCast(rc), MultiClickCleanup.destroy);
    return c;
}
```

[Ver el código en GitHubexamples/storybook/stories.zig:4695](https://github.com/version-next/zenit/blob/HEAD/examples/storybook/stories.zig#L4695)

El código literal de la story en el Storybook (zenit 5f9add5+wip 2026-09-30). `W` es `ui.widgets`; `col` / `row` / `label` son pequeños helpers de layout del Storybook.
