Keyboard navigation shouldn't be animated

When a command menu is driven by the keyboard, animated hover states feel laggy. Detect input modality with data attributes and skip transitions for keyboard users.

Arrow keys vs. mouse

With animation

PressKto open/close

Without animation

PressKto open/close

cmdk is Paco Coursey's headless command menu - it ships filtering, keyboard navigation, and ARIA roles, and leaves styling to you. Install it:

pnpm add cmdk

We lean on one detail: Command.Item gets data-selected="true" on whichever item is active - arrow key or hover. That single attribute is our hook for both modalities.

Each item carries four classes:

transition-colors
hover:bg-white/10
data-[selected=true]:bg-white/10
group-data-kbd/menu:transition-none

cmdk sets data-selected="true" on the active item, so hover and keyboard share the same background rule. The last class kills the transition while the menu carries data-kbd - flipped on by onKeyDown, off by onPointerMove.

const [kbd, setKbd] = useState(false);
const dataKbd = kbd ? "" : undefined;

<Command
  data-kbd={dataKbd}
  onKeyDown={() => setKbd(true)}
  onPointerMove={() => setKbd(false)}
/>

Pass undefined when off so React omits the attribute - data-kbd="false" would still match [data-kbd].

Newsletter

Stay updated with my latest articles and projects. No spam, no nonsense.