---
title: useGameControls
description: "Binds keyboard controls and generates matching help text."
---

```tsx
import { useGameControls } from 'filedom';

const controls = useGameControls({
  shortcuts: [
    { keys: ['r'], label: 'RESTART', onPress: () => restart() },
  ],
  onQuit: () => session.exit(),
});
```

The hook listens for keydowns itself. Each key goes first to `?`, which toggles help, then to the first shortcut whose `keys` include it, then to `q` if `onQuit` is set. Help text and overlay configuration are read once on mount; handlers can change on every render.

The help panel lists the `hints` lines, then one line per visible shortcut (`KEYS - LABEL`), then `Q - QUIT` when `onQuit` is set, then `? - CLOSE`.

## Options

| Prop | Type | Default | Description |
| - | - | - | - |
| `shortcuts` | `Shortcut[]` | - | Keyboard bindings; see Shortcut below. |
| `hints?` | `string[]` | - | Help lines for non-key input such as mouse or drag, shown above the shortcut lines. |
| `onQuit?` | `(() => void)` | - | Called when Q is pressed and no shortcut claims it. Adds Q - QUIT to help. |
| `winEffect?` | `WinEffectMode` | - | 'accent' (default) shows four accent icons on a win; 'none' turns them off. |
| `messages?` | `Partial<GameResultMessages>` | - | Overrides for the won, lost and draw text. Defaults: YOU WIN, GAME OVER, DRAW. |
| `help?` | `TextStyle` | - | How the ? help panel is drawn. Default { shape: { kind: 'sliced' }, onDemand: false }. |
| `banner?` | `TextStyle` | - | How the result banner is drawn. Default { shape: { kind: 'sliced' }, onDemand: false }. |

## TextStyle

```ts
type TextStyle = {
  shape?: TextShape;   // 'sliced' (default), 'glyphs', or 'grid'
  onDemand?: boolean;  // create the tiles on show so they draw over dragged icons
};
```

`shape` sets how large the text reads and how many files it costs, and
`onDemand` sets its z; see [Text](/docs/reference/components/text). In a drag-driven
game such as solitaire or chess, set `onDemand` on the banner so it draws over
dragged icons. A `grid` help panel avoids the problem a different way: the
overlay anchors it at the bottom of the desktop, clear of the play area.

```tsx
help: { shape: { kind: 'grid', charsPerCell: 3, linesPerCell: 2 } },
banner: { onDemand: true },
```

## Shortcut

```ts
type Shortcut = {
  keys: string[];
  label: string;
  onPress: (key: string) => void;
  display?: string;
  hidden?: boolean;
};
```

`keys` are normalized key names, as described in [useKeypress](/docs/reference/hooks/use-keypress). `onPress` receives the key that matched. `display` replaces the keys column in help, which otherwise shows the keys uppercased and joined with ` / `. `hidden` leaves a binding out of help but keeps it active.

## Returns

`GameOverlayController`: `handle` (the resolved configuration), `showHelp`, `toggleHelp()`, and `onKey(key)`. `onKey` toggles help on `?` and returns whether it handled the key. Pass the controller to [GameOverlay](/docs/reference/components/game-overlay).
