preact-conventionslisted
Install: claude install-skill qol-tools/qol-skills
# Preact Patterns
Preact + htm (tagged template literals), no JSX, no build step.
## HARD RULE: Keyboard-First
Every interactive component MUST be fully operable via keyboard BEFORE adding mouse/click handlers. This is non-negotiable.
- Every list/grid: arrow key navigation with visible selected state
- Every tab bar: Left/Right arrows to switch tabs
- Every action: Enter/Space to activate
- Every dialog/panel: Escape to dismiss, Tab to cycle focusables
- Every view: receives focus when navigated to
- ARIA roles on all interactive elements (`role="tablist"`, `role="tab"`, `role="list"`, `role="listitem"`)
- `tabIndex="0"` on containers that handle keyboard events
- `data-selected` attribute on selected items for scroll-into-view
If a PR adds a new view or component without keyboard navigation, it is incomplete.
## Imports
```js
import { html } from '../lib/html.js';
import { useState, useEffect, useCallback, useRef, useMemo } from 'preact/hooks';
```
htm uses `html` tagged templates, not JSX:
```js
return html`<div class="foo" onClick=${handler}>${children}</div>`;
```
## htm Gotchas
- **Fragments**: multiple root elements return an array, not a Fragment. Keys on direct children of fragments work for reconciliation.
- **Boolean attributes**: use `tabIndex="0"` not `tabindex="0"`. Preact uses camelCase DOM properties.
- **Events**: `onClick`, `onKeyDown`, `onBlur`, `onFocus`, `onWheel`, `onMouseEnter` — camelCase.
- **`ref`**: works on elements and components, set du