Skip to content

Tap Dance

Tap dance is a way to allow a single physical key to work as multiple logical keys / actions without using layers. With basic tap dance, you can trigger these "nested" keys or macros through a series of taps of the physical key within a given timeout.

The resulting "logical" action works just like any other key - it can be pressed and immediately released, or it can be held. For example, let's take a key KC.TD(KC.A, KC.B). If the tap dance key is tapped and released once quickly, the letter "a" will be sent. If it is tapped and released twice quickly, the letter "b" will be sent. If it is tapped once and held, the letter "a" will be held down until the tap dance key is released. If it is tapped and released once quickly, then tapped and held (both actions within the timeout window), the letter "b" will be held down until the tap dance key is released.

To use this, you may want to define a tap_time value in your keyboard configuration. This is an integer in milliseconds, and defaults to 300. The timeout is reset after each tap and every tap dance sequence can also define an individual tap_time.

You'll then want to create a sequence of keys using KC.TD(KC.SOMETHING, KC.SOMETHING_ELSE, MAYBE_THIS_IS_A_MACRO, WHATEVER_YO), and place it in your keymap somewhere. The only limits on how many keys can go in the sequence are, theoretically, the amount of RAM your MCU/board has.

Tap dance supports all HoldTap based keys, like mod tap, layer tap, oneshot... it will even honor every option set for those keys. Individual timeouts and prefer hold behavior for every tap in the sequence? Not a problem.

Here's an example of all this in action:

from kmk.keycodes import KC
from kmk.handlers.sequences import send_string
from kmk.modules.tapdance import TapDance

keyboard = KMKKeyboard()

tapdance = TapDance()
tapdance.tap_time = 750
keyboard.modules.append(tapdance)

EXAMPLE_TD = KC.TD(
    # Tap once for "a"
    KC.A,
    # Tap twice for "b", or tap and hold for "left control"
    KC.HT(KC.B, KC.LCTL, prefer_hold=False),
    # Tap three times to send a raw string via macro
    send_string('macros in a tap dance? I think yes'),
    # Tap four times to toggle layer index 1, tap 3 times and hold for 3s to
    # momentary toggle layer index 1.
    KC.TT(1, tap_time=3000),
)

# make the default tap time really short for this tap dance:
EXAMPLE_TD2 = KC.TD(KC.A, KC.B, tap_time=80)


keyboard.keymap = [[ ...., EXAMPLE_TD, ....], ....]