# onClick Without Keyboard Handler

**MUST** · **ID:** `interactions-rams-keyboard-handlers` · **Category:** interactions
**Source:** [RAMS](https://www.rams.ai/)
**Interactive version:** https://ui-guides-agent-rules.netlify.app/principles/interactions-rams-keyboard-handlers

> MUST: Interactive elements with onClick must also handle keyboard events (Enter/Space for buttons). Use semantic elements (<button>) which handle this automatically.

Elements with onClick should also handle keyboard events

Rams ships this as a Serious checklist row, not prose. Our reading: elements that only respond to the mouse are unreachable for keyboard-only users. Semantic elements like button and a fire click on Enter/Space for free — reach for those first, and only add explicit onKeyDown when you genuinely cannot.

## Bad — do not do this

`interactions-rams-keyboard-handlers-bad`

```tsx
import { useState } from 'react';

export function RamsKeyboardHandlersBad() {
  const [count, setCount] = useState(0);

  return (
    <div className="w-full max-w-sm space-y-4">
      <div className="bg-card border border-border rounded-lg p-4">
        <h4 className="font-medium mb-3">Click-Only Action</h4>
        <div className="space-y-3">
          <div className="flex items-center gap-4 p-3 bg-muted rounded-lg">
            {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
            <div
              onClick={() => setCount((c) => c + 1)}
              className="px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors cursor-pointer"
            >
              Increment
            </div>
            <span className="font-mono text-lg">{count}</span>
          </div>
          <div className="bg-muted rounded p-2 font-mono text-xs">
            <code className="text-error">{'<div onClick={...}>Increment</div>'}</code>
          </div>
          <p className="text-sm text-muted-foreground">
            Tab to element, then try Enter - nothing happens
          </p>
        </div>
      </div>
      <p className="text-xs text-error">
        Only works with mouse - keyboard users cannot activate
      </p>
    </div>
  );
}
```

## Good — do this

`interactions-rams-keyboard-handlers-good`

```tsx
import { useState } from 'react';

export function RamsKeyboardHandlersGood() {
  const [count, setCount] = useState(0);

  return (
    <div className="w-full max-w-sm space-y-4">
      <div className="bg-card border border-border rounded-lg p-4">
        <h4 className="font-medium mb-3">Keyboard-Accessible Actions</h4>
        <div className="space-y-3">
          <div className="flex items-center gap-4 p-3 bg-muted rounded-lg">
            <button
              onClick={() => setCount((c) => c + 1)}
              className="px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-muted"
            >
              Increment
            </button>
            <span className="font-mono text-lg">{count}</span>
          </div>
          <div className="bg-muted rounded p-2 font-mono text-xs">
            <code>{'<button onClick={...}>Increment</button>'}</code>
          </div>
          <p className="text-sm text-muted-foreground">
            Try pressing Tab then Enter/Space
          </p>
        </div>
      </div>
      <p className="text-xs text-success">
        Works with click, Enter key, and Space key
      </p>
    </div>
  );
}
```

## References

- [Rams review checklist](https://www.rams.ai/rams.md)
- [WCAG 2.1.1](https://www.w3.org/WAI/WCAG21/Understanding/keyboard.html)
