Skip to main content

Tap-Dance Behavior


A tap-dance key invokes a different behavior (e.g. kp) corresponding to how many times it is pressed. For example, you could configure a tap-dance key that acts as LSHIFT if tapped once, or Caps Lock if tapped twice. The expandability of the number of bindings attached to a particular tap-dance is a great way to add more functionality to a single key, especially for keyboards with a limited number of keys. Tap-dances are completely custom, so for every unique tap-dance key,a new tap-dance must be defined in your keymap's behaviors.

Tap-dances are designed to resolve immediately when interrupted by another keypress. Meaning, when a keybind is pressed other than any active tap-dances, the tap-dance will activate according to the current value of its counter before the interrupting keybind is registered.



Defines the maximum elapsed time after the last tap-dance keybind press before a binding is selected from bindings. Default value is 200ms.


An array of one or more keybinds. This list can include any ZMK keycode and any listed ZMK behavior, like hold-taps, or sticky keys. The index of a keybind in the bindings array corresponds to the number of times the tap-dance binding is pressed. For example, in the basic tap-dance counter shown below, &kp N2 is the second binding in the array of bindings: we then see an output of 2 when the td0 binding is pressed twice.

The number of bindings in this array also determines the tap-dance's maximum number of keypresses. When a tap-dance reaches its maximum number of keypresses, it will immediately invoke the last behavior in its list of bindings, rather than waiting for tapping-term-ms to expire before the output is displayed.

Example Usage

This example configures a tap-dance named td0 that outputs the number of times its binding is pressed from 1-3.

Basic Tap-Dance Example: Counter
#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>

/ {
behaviors {
td0: tap_dance_0 {
compatible = "zmk,behavior-tap-dance";
#binding-cells = <0>;
tapping-term-ms = <200>;
bindings = <&kp N1>, <&kp N2>, <&kp N3>;

keymap {
compatible = "zmk,keymap";

default_layer {
bindings = <

The following image describes the behavior of this particular tap-dance.

Timing Diagram


Alphanumeric key press bindings, like those used for td0, will release as soon as an interrupting key press occurs. For instance, if a modifier key like LSHIFT were to replace the N1 binding in the last example above, it would remain pressed until td0's binding is released and the output would instead be J. Any following alphanumeric key presses would be capitalized as long as td0 is held down.