0
# DOM Events & Interactions
1
2
Event handling hooks for click detection, keyboard shortcuts, mouse interactions, hover states, focus management, and touch gestures.
3
4
## Capabilities
5
6
### useClickOutside
7
8
Detect clicks outside target element(s) with configurable events and multiple node support.
9
10
```typescript { .api }
11
/**
12
* Detect clicks outside target element(s)
13
* @param handler - Function to call when click outside occurs
14
* @param events - Array of event names to listen for (default: ['mousedown', 'touchstart'])
15
* @param nodes - Additional nodes to consider as "inside"
16
* @returns Ref callback to attach to target element
17
*/
18
function useClickOutside<T extends HTMLElement = any>(
19
handler: () => void,
20
events?: string[] | null,
21
nodes?: HTMLElement[]
22
): React.RefCallback<T | null>;
23
```
24
25
**Usage Examples:**
26
27
```typescript
28
import { useClickOutside } from "@mantine/hooks";
29
import { useRef } from "react";
30
31
// Basic modal/dropdown
32
function Modal({ onClose }: { onClose: () => void }) {
33
const ref = useClickOutside(onClose);
34
35
return <div ref={ref}>Modal content</div>;
36
}
37
38
// Multiple elements considered "inside"
39
function ComplexDropdown() {
40
const triggerRef = useRef<HTMLButtonElement>(null);
41
const dropdownRef = useClickOutside(
42
() => setOpened(false),
43
['mousedown', 'touchstart'],
44
[triggerRef.current] // Don't close when clicking trigger
45
);
46
47
return (
48
<>
49
<button ref={triggerRef}>Open</button>
50
<div ref={dropdownRef}>Dropdown content</div>
51
</>
52
);
53
}
54
```
55
56
### useHotkeys
57
58
Keyboard shortcuts handler with key combinations and configurable options.
59
60
```typescript { .api }
61
/**
62
* Keyboard shortcuts handler
63
* @param hotkeys - Array of [key combination, handler, options] tuples
64
* @param tagsToIgnore - HTML tags to ignore (default: ['INPUT', 'TEXTAREA', 'SELECT'])
65
* @param triggerOnContentEditable - Whether to trigger on contentEditable elements
66
*/
67
function useHotkeys(
68
hotkeys: HotkeyItem[],
69
tagsToIgnore?: string[],
70
triggerOnContentEditable?: boolean
71
): void;
72
73
/**
74
* Get hotkey handler for manual event handling
75
* @param hotkeys - Array of hotkey configurations
76
* @returns Event handler function
77
*/
78
function getHotkeyHandler(hotkeys: HotkeyItem[]): (event: React.KeyboardEvent<HTMLElement> | KeyboardEvent) => void;
79
80
type HotkeyItem = [string, (event: KeyboardEvent) => void, HotkeyItemOptions?];
81
82
interface HotkeyItemOptions {
83
preventDefault?: boolean;
84
usePhysicalKeys?: boolean;
85
}
86
```
87
88
**Usage Examples:**
89
90
```typescript
91
import { useHotkeys, getHotkeyHandler } from "@mantine/hooks";
92
93
// Global hotkeys
94
function App() {
95
useHotkeys([
96
['mod+S', () => save()], // Cmd+S on Mac, Ctrl+S on Windows
97
['mod+K', () => openSearch(), { preventDefault: true }],
98
['Escape', () => closeModal()],
99
['shift+?', () => showHelp()],
100
]);
101
}
102
103
// Manual event handling
104
function Editor() {
105
const handleKeyDown = getHotkeyHandler([
106
['mod+B', () => toggleBold()],
107
['mod+I', () => toggleItalic()],
108
]);
109
110
return <textarea onKeyDown={handleKeyDown} />;
111
}
112
```
113
114
### useHover
115
116
Detect hover state on elements with ref-based attachment.
117
118
```typescript { .api }
119
/**
120
* Detect hover state on elements
121
* @returns Object with hover state and ref callback
122
*/
123
function useHover<T extends HTMLElement = any>(): UseHoverReturnValue<T>;
124
125
interface UseHoverReturnValue<T extends HTMLElement = any> {
126
hovered: boolean;
127
ref: React.RefCallback<T | null>;
128
}
129
```
130
131
**Usage Examples:**
132
133
```typescript
134
import { useHover } from "@mantine/hooks";
135
136
function HoverCard() {
137
const { hovered, ref } = useHover();
138
139
return (
140
<div ref={ref} style={{ background: hovered ? 'blue' : 'gray' }}>
141
{hovered ? 'Hovered!' : 'Hover me'}
142
</div>
143
);
144
}
145
```
146
147
### useMove
148
149
Mouse/touch drag interactions with position tracking and directional support.
150
151
```typescript { .api }
152
/**
153
* Mouse/touch drag interactions with position tracking
154
* @param onChange - Callback fired when position changes
155
* @param handlers - Optional start/end handlers
156
* @param dir - Text direction for RTL support
157
* @returns Object with ref callback and active state
158
*/
159
function useMove<T extends HTMLElement = any>(
160
onChange: (value: UseMovePosition) => void,
161
handlers?: UseMoveHandlers,
162
dir?: 'ltr' | 'rtl'
163
): UseMoveReturnValue<T>;
164
165
/**
166
* Clamp position values to 0-1 range
167
* @param position - Position object to clamp
168
* @returns Clamped position
169
*/
170
function clampUseMovePosition(position: UseMovePosition): UseMovePosition;
171
172
interface UseMovePosition {
173
x: number; // 0-1 range
174
y: number; // 0-1 range
175
}
176
177
interface UseMoveHandlers {
178
onScrubStart?: () => void;
179
onScrubEnd?: () => void;
180
}
181
182
interface UseMoveReturnValue<T extends HTMLElement = any> {
183
ref: React.RefCallback<T | null>;
184
active: boolean;
185
}
186
```
187
188
**Usage Examples:**
189
190
```typescript
191
import { useMove, clampUseMovePosition } from "@mantine/hooks";
192
193
// Color picker
194
function ColorPicker() {
195
const [value, setValue] = useState({ x: 0.5, y: 0.5 });
196
197
const { ref, active } = useMove((position) => {
198
setValue(clampUseMovePosition(position));
199
}, {
200
onScrubStart: () => console.log('Started dragging'),
201
onScrubEnd: () => console.log('Stopped dragging')
202
});
203
204
return (
205
<div ref={ref} style={{ position: 'relative', width: 200, height: 200 }}>
206
<div
207
style={{
208
position: 'absolute',
209
left: `${value.x * 100}%`,
210
top: `${value.y * 100}%`,
211
transform: 'translate(-50%, -50%)'
212
}}
213
>
214
Thumb
215
</div>
216
</div>
217
);
218
}
219
```
220
221
### useFocusWithin
222
223
Detect focus within element tree with callbacks for focus/blur events.
224
225
```typescript { .api }
226
/**
227
* Detect focus within element tree
228
* @param options - Configuration for focus callbacks
229
* @returns Object with focus state and ref callback
230
*/
231
function useFocusWithin<T extends HTMLElement = any>(options?: UseFocusWithinOptions): UseFocusWithinReturnValue<T>;
232
233
interface UseFocusWithinOptions {
234
onFocus?: () => void;
235
onBlur?: () => void;
236
}
237
238
interface UseFocusWithinReturnValue<T extends HTMLElement = any> {
239
focused: boolean;
240
ref: React.RefCallback<T | null>;
241
}
242
```
243
244
### useFocusTrap
245
246
Trap focus within element for accessibility (modals, dropdowns).
247
248
```typescript { .api }
249
/**
250
* Trap focus within element for accessibility
251
* @param active - Whether focus trap is active
252
* @returns Ref callback to attach to container element
253
*/
254
function useFocusTrap(active?: boolean): React.RefCallback<HTMLElement | null>;
255
```
256
257
### useLongPress
258
259
Detect long press gestures with configurable threshold and callbacks.
260
261
```typescript { .api }
262
/**
263
* Detect long press gestures
264
* @param callback - Function to call on long press
265
* @param options - Configuration for threshold and callbacks
266
* @returns Object with ref callback
267
*/
268
function useLongPress<T extends HTMLElement = any>(
269
callback: () => void,
270
options?: UseLongPressOptions
271
): UseLongPressReturnValue<T>;
272
273
interface UseLongPressOptions {
274
threshold?: number; // Duration in ms (default: 500)
275
onStart?: () => void;
276
onFinish?: () => void;
277
onCancel?: () => void;
278
}
279
280
interface UseLongPressReturnValue<T extends HTMLElement = any> {
281
ref: React.RefCallback<T | null>;
282
}
283
```
284
285
### useEventListener
286
287
Attach event listeners to elements with ref callback and automatic cleanup.
288
289
```typescript { .api }
290
/**
291
* Attach event listeners to elements
292
* @param type - Event type
293
* @param listener - Event handler function
294
* @param options - Event listener options
295
* @returns Ref callback to attach to target element
296
*/
297
function useEventListener<K extends keyof HTMLElementEventMap, T extends HTMLElement = any>(
298
type: K,
299
listener: (this: HTMLDivElement, ev: HTMLElementEventMap[K]) => any,
300
options?: boolean | AddEventListenerOptions
301
): React.RefCallback<T | null>;
302
```
303
304
### useWindowEvent
305
306
Attach event listeners to window object with automatic cleanup.
307
308
```typescript { .api }
309
/**
310
* Attach event listeners to window object
311
* @param type - Event type
312
* @param listener - Event handler function
313
* @param options - Event listener options
314
*/
315
function useWindowEvent<K extends string>(
316
type: K,
317
listener: K extends keyof WindowEventMap
318
? (this: Window, ev: WindowEventMap[K]) => void
319
: (this: Window, ev: CustomEvent) => void,
320
options?: boolean | AddEventListenerOptions
321
): void;
322
```
323
324
**Usage Examples:**
325
326
```typescript
327
import { useEventListener, useWindowEvent } from "@mantine/hooks";
328
329
// Element-specific events
330
function InteractiveElement() {
331
const ref = useEventListener('click', (event) => {
332
console.log('Element clicked', event);
333
});
334
335
return <div ref={ref}>Click me</div>;
336
}
337
338
// Global window events
339
function WindowEventHandler() {
340
useWindowEvent('resize', () => {
341
console.log('Window resized');
342
});
343
344
useWindowEvent('keydown', (event) => {
345
if (event.key === 'Escape') {
346
console.log('Escape pressed');
347
}
348
});
349
350
return <div>Component with window event handlers</div>;
351
}
352
```