0
# Navigation Components
1
2
@mantine/core provides a comprehensive set of navigation components for building user-friendly interfaces with clear navigation patterns. These components handle complex interactions while maintaining accessibility standards.
3
4
## Tabs
5
6
The Tabs component provides a tabbed interface with keyboard navigation and accessibility features.
7
8
```typescript { .api }
9
interface TabsProps {
10
/** Currently active tab key */
11
value?: string | null;
12
/** Default active tab key */
13
defaultValue?: string | null;
14
/** Called when tab changes */
15
onTabChange?: (value: string | null) => void;
16
/** Tab orientation */
17
orientation?: 'horizontal' | 'vertical';
18
/** Tab placement relative to content */
19
placement?: 'right' | 'left';
20
/** If true, tabs can be activated with keyboard */
21
activateTabWithKeyboard?: boolean;
22
/** Tab variant */
23
variant?: 'default' | 'outline' | 'pills';
24
/** Tab color theme */
25
color?: MantineColor;
26
/** Tab radius */
27
radius?: MantineRadius;
28
/** If true, tab panels are not wrapped with TabPanel */
29
keepMounted?: boolean;
30
/** Tabs children */
31
children: React.ReactNode;
32
}
33
34
interface TabsListProps {
35
/** Tabs list children (Tab components) */
36
children: React.ReactNode;
37
/** If true, tab will grow to use all available space */
38
grow?: boolean;
39
/** Tab position */
40
justify?: 'flex-start' | 'center' | 'flex-end' | 'space-between' | 'space-around';
41
}
42
43
interface TabsPanelProps {
44
/** Panel content */
45
children: React.ReactNode;
46
/** Tab key that should activate this panel */
47
value: string;
48
}
49
50
interface TabsTabProps {
51
/** Tab label */
52
children: React.ReactNode;
53
/** Tab key */
54
value: string;
55
/** Tab icon */
56
leftSection?: React.ReactNode;
57
/** Tab right section */
58
rightSection?: React.ReactNode;
59
/** Tab color when active */
60
color?: MantineColor;
61
/** If true, tab is disabled */
62
disabled?: boolean;
63
}
64
```
65
66
**Usage Example:**
67
68
```tsx
69
import { Tabs } from '@mantine/core';
70
71
function TabsDemo() {
72
return (
73
<Tabs defaultValue="gallery">
74
<Tabs.List>
75
<Tabs.Tab value="gallery" leftSection="π·">
76
Gallery
77
</Tabs.Tab>
78
<Tabs.Tab value="messages" leftSection="π¬">
79
Messages
80
</Tabs.Tab>
81
<Tabs.Tab value="settings" leftSection="βοΈ">
82
Settings
83
</Tabs.Tab>
84
</Tabs.List>
85
86
<Tabs.Panel value="gallery">
87
Gallery tab content
88
</Tabs.Panel>
89
90
<Tabs.Panel value="messages">
91
Messages tab content
92
</Tabs.Panel>
93
94
<Tabs.Panel value="settings">
95
Settings tab content
96
</Tabs.Panel>
97
</Tabs>
98
);
99
}
100
```
101
102
## Stepper
103
104
Multi-step process component with validation and navigation controls.
105
106
```typescript { .api }
107
interface StepperProps {
108
/** Active step index */
109
active: number;
110
/** Called when step changes */
111
onStepClick?: (stepIndex: number) => void;
112
/** Step icon size */
113
iconSize?: number;
114
/** Stepper orientation */
115
orientation?: 'vertical' | 'horizontal';
116
/** Icon position relative to step body */
117
iconPosition?: 'right' | 'left';
118
/** Step size */
119
size?: MantineSize;
120
/** Step radius */
121
radius?: MantineRadius;
122
/** Step color theme */
123
color?: MantineColor;
124
/** If true, steps before active can be clicked */
125
allowNextStepsSelect?: boolean;
126
/** Stepper children (Step components) */
127
children: React.ReactNode;
128
}
129
130
interface StepperStepProps {
131
/** Step label */
132
label?: React.ReactNode;
133
/** Step description */
134
description?: React.ReactNode;
135
/** Step icon, displayed instead of step number */
136
icon?: React.ReactNode;
137
/** Step content */
138
children?: React.ReactNode;
139
/** Step state */
140
state?: 'stepInactive' | 'stepProgress' | 'stepCompleted';
141
/** Step color when active */
142
color?: MantineColor;
143
/** If true, step can be clicked */
144
allowStepClick?: boolean;
145
/** If true, step is completed */
146
completedIcon?: React.ReactNode;
147
/** If true, step is loading */
148
loading?: boolean;
149
}
150
151
interface StepperCompletedProps {
152
/** Completed state content */
153
children: React.ReactNode;
154
}
155
```
156
157
**Usage Example:**
158
159
```tsx
160
import { Stepper, Button, Group } from '@mantine/core';
161
import { useState } from 'react';
162
163
function StepperDemo() {
164
const [active, setActive] = useState(0);
165
166
const nextStep = () => setActive(current =>
167
current < 3 ? current + 1 : current
168
);
169
const prevStep = () => setActive(current =>
170
current > 0 ? current - 1 : current
171
);
172
173
return (
174
<>
175
<Stepper active={active} onStepClick={setActive}>
176
<Stepper.Step label="First step" description="Create an account">
177
Step 1 content: Create an account
178
</Stepper.Step>
179
180
<Stepper.Step label="Second step" description="Verify email">
181
Step 2 content: Verify email
182
</Stepper.Step>
183
184
<Stepper.Step label="Final step" description="Get full access">
185
Step 3 content: Get full access
186
</Stepper.Step>
187
188
<Stepper.Completed>
189
Completed! Form values are:
190
</Stepper.Completed>
191
</Stepper>
192
193
<Group justify="center" mt="xl">
194
<Button variant="default" onClick={prevStep}>Back</Button>
195
<Button onClick={nextStep}>Next step</Button>
196
</Group>
197
</>
198
);
199
}
200
```
201
202
## Breadcrumbs
203
204
Navigation breadcrumb component for showing the current page location.
205
206
```typescript { .api }
207
interface BreadcrumbsProps {
208
/** Breadcrumb items */
209
children: React.ReactNode;
210
/** Separator between items */
211
separator?: React.ReactNode;
212
/** Number of items to display, other items will be hidden */
213
max?: number;
214
/** Separator for hidden items */
215
separatorMargin?: MantineSpacing;
216
}
217
```
218
219
**Usage Example:**
220
221
```tsx
222
import { Breadcrumbs, Anchor } from '@mantine/core';
223
224
const items = [
225
{ title: 'Mantine', href: '#' },
226
{ title: 'Core', href: '#' },
227
{ title: 'Breadcrumbs', href: '#' },
228
].map((item, index) => (
229
<Anchor href={item.href} key={index}>
230
{item.title}
231
</Anchor>
232
));
233
234
function BreadcrumbsDemo() {
235
return <Breadcrumbs>{items}</Breadcrumbs>;
236
}
237
```
238
239
## Pagination
240
241
Pagination controls with customizable appearance and behavior.
242
243
```typescript { .api }
244
interface PaginationProps {
245
/** Active page number */
246
value?: number;
247
/** Default active page */
248
defaultValue?: number;
249
/** Called when page changes */
250
onChange?: (value: number) => void;
251
/** Total number of pages */
252
total: number;
253
/** Number of siblings on each side of active page */
254
siblings?: number;
255
/** Number of boundaries on each side */
256
boundaries?: number;
257
/** Pagination size */
258
size?: MantineSize;
259
/** Pagination radius */
260
radius?: MantineRadius;
261
/** Pagination color theme */
262
color?: MantineColor;
263
/** If true, pagination will not wrap to next line */
264
withEdges?: boolean;
265
/** If true, controls are disabled */
266
disabled?: boolean;
267
/** Get aria-label for page button */
268
getItemAriaLabel?: (page: number) => string;
269
/** Get control aria-label */
270
getControlAriaLabel?: (control: string) => string;
271
}
272
273
interface PaginationRootProps {
274
/** Root element children */
275
children: React.ReactNode;
276
/** Pagination size */
277
size?: MantineSize;
278
/** Total number of pages */
279
total: number;
280
/** Active page number */
281
value?: number;
282
/** Default active page */
283
defaultValue?: number;
284
/** Called when page changes */
285
onChange?: (value: number) => void;
286
/** If true, controls are disabled */
287
disabled?: boolean;
288
/** Number of siblings */
289
siblings?: number;
290
/** Number of boundaries */
291
boundaries?: number;
292
/** Get aria-label for page */
293
getItemAriaLabel?: (page: number) => string;
294
}
295
296
interface PaginationControlProps {
297
/** Control content */
298
children?: React.ReactNode;
299
/** Control action */
300
onClick?: () => void;
301
/** If true, control is disabled */
302
disabled?: boolean;
303
/** If true, control is active */
304
active?: boolean;
305
/** Control aria-label */
306
'aria-label'?: string;
307
}
308
```
309
310
**Usage Example:**
311
312
```tsx
313
import { Pagination } from '@mantine/core';
314
import { useState } from 'react';
315
316
function PaginationDemo() {
317
const [activePage, setPage] = useState(1);
318
319
return (
320
<Pagination
321
value={activePage}
322
onChange={setPage}
323
total={10}
324
siblings={1}
325
boundaries={3}
326
/>
327
);
328
}
329
330
// Compound components usage
331
function CustomPagination() {
332
return (
333
<Pagination.Root total={10}>
334
<Pagination.First />
335
<Pagination.Previous />
336
<Pagination.Items />
337
<Pagination.Next />
338
<Pagination.Last />
339
</Pagination.Root>
340
);
341
}
342
```
343
344
## NavLink
345
346
Navigation link component with active state and nested structure support.
347
348
```typescript { .api }
349
interface NavLinkProps {
350
/** Link label */
351
label: React.ReactNode;
352
/** Link description */
353
description?: React.ReactNode;
354
/** Link left section (usually icon) */
355
leftSection?: React.ReactNode;
356
/** Link right section */
357
rightSection?: React.ReactNode;
358
/** If true, link will have active styles */
359
active?: boolean;
360
/** Link variant */
361
variant?: 'light' | 'filled' | 'subtle';
362
/** Link color theme */
363
color?: MantineColor;
364
/** If true, link is disabled */
365
disabled?: boolean;
366
/** Link children for nested structure */
367
children?: React.ReactNode;
368
/** Called when link is clicked */
369
onClick?: () => void;
370
/** If true, children will not be rendered */
371
childrenOffset?: MantineSpacing;
372
/** If true, link cannot be activated with click */
373
disableRightSectionRotation?: boolean;
374
/** Collapse icon */
375
collapseIcon?: React.ReactNode;
376
}
377
```
378
379
**Usage Example:**
380
381
```tsx
382
import { NavLink } from '@mantine/core';
383
384
function NavLinkDemo() {
385
return (
386
<NavLink
387
label="With icon"
388
leftSection="π "
389
rightSection="β"
390
active
391
/>
392
);
393
}
394
395
// Nested NavLinks
396
function NestedNavLinks() {
397
return (
398
<NavLink label="Dashboard" leftSection="π">
399
<NavLink label="Analytics" />
400
<NavLink label="Reports" active />
401
<NavLink label="Settings" />
402
</NavLink>
403
);
404
}
405
```
406
407
## TableOfContents
408
409
Table of contents component for navigation within documents.
410
411
```typescript { .api }
412
interface TableOfContentsProps {
413
/** Table of contents links */
414
links: TableOfContentsLink[];
415
/** Active link */
416
active?: string;
417
/** Called when link is clicked */
418
onLinkClick?: (link: TableOfContentsLink) => void;
419
}
420
421
interface TableOfContentsLink {
422
/** Link label */
423
label: string;
424
/** Link id */
425
link: string;
426
/** Nested links */
427
links?: TableOfContentsLink[];
428
/** Link order for sorting */
429
order?: number;
430
}
431
```
432
433
**Usage Example:**
434
435
```tsx
436
import { TableOfContents } from '@mantine/core';
437
438
const links = [
439
{
440
label: 'Usage',
441
link: '#usage',
442
order: 1,
443
},
444
{
445
label: 'API Reference',
446
link: '#api',
447
order: 1,
448
links: [
449
{ label: 'Props', link: '#props', order: 2 },
450
{ label: 'Methods', link: '#methods', order: 2 },
451
],
452
},
453
{
454
label: 'Examples',
455
link: '#examples',
456
order: 1,
457
},
458
];
459
460
function TableOfContentsDemo() {
461
return (
462
<TableOfContents
463
links={links}
464
active="#usage"
465
onLinkClick={(link) => console.log(link)}
466
/>
467
);
468
}
469
```
470
471
## Theme Integration
472
473
All navigation components integrate seamlessly with the Mantine theme system:
474
475
```tsx
476
import { MantineProvider, Tabs, Stepper, Pagination } from '@mantine/core';
477
478
const theme = {
479
components: {
480
Tabs: {
481
defaultProps: {
482
color: 'blue',
483
variant: 'pills',
484
},
485
},
486
Stepper: {
487
defaultProps: {
488
size: 'sm',
489
color: 'teal',
490
},
491
},
492
Pagination: {
493
defaultProps: {
494
size: 'md',
495
radius: 'md',
496
},
497
},
498
},
499
};
500
501
function App() {
502
return (
503
<MantineProvider theme={theme}>
504
{/* Navigation components will use theme defaults */}
505
</MantineProvider>
506
);
507
}
508
```
509
510
## Accessibility Features
511
512
Navigation components include comprehensive accessibility support:
513
514
- **Keyboard Navigation**: Full keyboard support with arrow keys, Enter, Space
515
- **ARIA Labels**: Proper labeling for screen readers
516
- **Focus Management**: Logical focus flow and visible focus indicators
517
- **Role Attributes**: Correct semantic roles (tab, tablist, tabpanel, etc.)
518
- **State Announcement**: Active and disabled states are properly announced
519
520
## Common Patterns
521
522
**Responsive Navigation:**
523
```tsx
524
import { useMediaQuery } from '@mantine/hooks';
525
import { Tabs, Burger, Drawer } from '@mantine/core';
526
527
function ResponsiveNavigation() {
528
const isMobile = useMediaQuery('(max-width: 768px)');
529
530
return isMobile ? (
531
<MobileBurgerMenu />
532
) : (
533
<Tabs>
534
<Tabs.List>
535
<Tabs.Tab value="home">Home</Tabs.Tab>
536
<Tabs.Tab value="about">About</Tabs.Tab>
537
<Tabs.Tab value="contact">Contact</Tabs.Tab>
538
</Tabs.List>
539
</Tabs>
540
);
541
}
542
```
543
544
**Multi-level Navigation:**
545
```tsx
546
function MultiLevelNavigation() {
547
return (
548
<NavLink label="Products" leftSection="π¦">
549
<NavLink label="Software">
550
<NavLink label="Desktop Apps" />
551
<NavLink label="Mobile Apps" />
552
</NavLink>
553
<NavLink label="Hardware">
554
<NavLink label="Computers" />
555
<NavLink label="Accessories" />
556
</NavLink>
557
</NavLink>
558
);
559
}
560
```