or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

button-typography-components.mdcore-components.mddata-display-components.mdfeedback-components.mdform-components.mdindex.mdlayout-components.mdnavigation-components.mdoverlay-components.mdtheme-system.md

data-display-components.mddocs/

0

# Data Display Components

1

2

@mantine/core provides comprehensive components for displaying and organizing data in various formats. These components handle structured data presentation, visual elements, and content organization with accessibility and responsive design built-in.

3

4

## Table

5

6

Comprehensive table component with responsive design and accessibility features.

7

8

```typescript { .api }

9

interface TableProps {

10

/** Table data */

11

data?: TableData;

12

/** Table children */

13

children?: React.ReactNode;

14

/** Table caption */

15

captionSide?: 'top' | 'bottom';

16

/** If true, table will have striped rows */

17

striped?: boolean;

18

/** If true, table rows will have hover effect */

19

highlightOnHover?: boolean;

20

/** If true, table will have border */

21

withTableBorder?: boolean;

22

/** If true, table will have border between columns */

23

withColumnBorders?: boolean;

24

/** If true, table will have border between rows */

25

withRowBorders?: boolean;

26

/** Table layout */

27

layout?: 'auto' | 'fixed';

28

/** Horizontal spacing */

29

horizontalSpacing?: MantineSpacing;

30

/** Vertical spacing */

31

verticalSpacing?: MantineSpacing;

32

/** Font size */

33

fontSize?: MantineSize;

34

}

35

36

interface TableTheadProps {

37

/** Thead children */

38

children: React.ReactNode;

39

}

40

41

interface TableTbodyProps {

42

/** Tbody children */

43

children: React.ReactNode;

44

}

45

46

interface TableTfootProps {

47

/** Tfoot children */

48

children: React.ReactNode;

49

}

50

51

interface TableTrProps {

52

/** Tr children */

53

children: React.ReactNode;

54

/** If true, row will have hover effect */

55

hover?: boolean;

56

}

57

58

interface TableThProps {

59

/** Th children */

60

children?: React.ReactNode;

61

/** Column width */

62

w?: React.CSSProperties['width'];

63

/** Column min width */

64

miw?: React.CSSProperties['minWidth'];

65

/** Text align */

66

ta?: React.CSSProperties['textAlign'];

67

}

68

69

interface TableTdProps {

70

/** Td children */

71

children?: React.ReactNode;

72

/** Cell width */

73

w?: React.CSSProperties['width'];

74

/** Cell min width */

75

miw?: React.CSSProperties['minWidth'];

76

/** Text align */

77

ta?: React.CSSProperties['textAlign'];

78

}

79

80

interface TableCaptionProps {

81

/** Caption children */

82

children: React.ReactNode;

83

}

84

85

interface TableScrollContainerProps {

86

/** Container children */

87

children: React.ReactNode;

88

/** Minimum width before scrolling */

89

minWidth?: React.CSSProperties['minWidth'];

90

/** Scroll container type */

91

type?: 'native' | 'scrollarea';

92

}

93

94

interface TableData {

95

/** Table caption */

96

caption?: string;

97

/** Table head data */

98

head?: string[];

99

/** Table body data */

100

body?: string[][];

101

/** Table foot data */

102

foot?: string[];

103

}

104

```

105

106

**Usage Example:**

107

108

```tsx

109

import { Table } from '@mantine/core';

110

111

const elements = [

112

{ position: 6, mass: 12.011, symbol: 'C', name: 'Carbon' },

113

{ position: 7, mass: 14.007, symbol: 'N', name: 'Nitrogen' },

114

{ position: 39, mass: 88.906, symbol: 'Y', name: 'Yttrium' },

115

{ position: 56, mass: 137.33, symbol: 'Ba', name: 'Barium' },

116

{ position: 58, mass: 140.12, symbol: 'Ce', name: 'Cerium' },

117

];

118

119

function TableDemo() {

120

const rows = elements.map((element) => (

121

<Table.Tr key={element.name}>

122

<Table.Td>{element.position}</Table.Td>

123

<Table.Td>{element.name}</Table.Td>

124

<Table.Td>{element.symbol}</Table.Td>

125

<Table.Td>{element.mass}</Table.Td>

126

</Table.Tr>

127

));

128

129

return (

130

<Table>

131

<Table.Thead>

132

<Table.Tr>

133

<Table.Th>Element position</Table.Th>

134

<Table.Th>Element name</Table.Th>

135

<Table.Th>Symbol</Table.Th>

136

<Table.Th>Atomic mass</Table.Th>

137

</Table.Tr>

138

</Table.Thead>

139

<Table.Tbody>{rows}</Table.Tbody>

140

</Table>

141

);

142

}

143

144

// Table with data prop

145

function TableWithData() {

146

return (

147

<Table

148

data={{

149

head: ['Element position', 'Element name', 'Symbol', 'Atomic mass'],

150

body: [

151

[6, 'Carbon', 'C', 12.011],

152

[7, 'Nitrogen', 'N', 14.007],

153

[39, 'Yttrium', 'Y', 88.906],

154

[56, 'Barium', 'Ba', 137.33],

155

[58, 'Cerium', 'Ce', 140.12],

156

],

157

}}

158

/>

159

);

160

}

161

162

// Responsive table with scroll container

163

function ResponsiveTable() {

164

return (

165

<Table.ScrollContainer minWidth={800}>

166

<Table>

167

{/* Table content */}

168

</Table>

169

</Table.ScrollContainer>

170

);

171

}

172

```

173

174

## List

175

176

Ordered and unordered list component with custom styling options.

177

178

```typescript { .api }

179

interface ListProps {

180

/** List type */

181

type?: 'ordered' | 'unordered';

182

/** List children */

183

children: React.ReactNode;

184

/** If true, list will have spacing between items */

185

withPadding?: boolean;

186

/** List icon */

187

icon?: React.ReactNode;

188

/** List spacing */

189

spacing?: MantineSpacing;

190

/** List item spacing */

191

size?: MantineSize;

192

/** If true, list will be centered */

193

center?: boolean;

194

}

195

196

interface ListItemProps {

197

/** Item children */

198

children: React.ReactNode;

199

/** Item icon */

200

icon?: React.ReactNode;

201

}

202

```

203

204

**Usage Example:**

205

206

```tsx

207

import { List, ThemeIcon } from '@mantine/core';

208

209

function ListDemo() {

210

return (

211

<List>

212

<List.Item>Clone or download repository from GitHub</List.Item>

213

<List.Item>Install dependencies with yarn or npm</List.Item>

214

<List.Item>To start development server run npm start command</List.Item>

215

<List.Item>Run tests to make sure your changes do not break the build</List.Item>

216

</List>

217

);

218

}

219

220

// Custom icons

221

function ListWithIcons() {

222

return (

223

<List

224

spacing="xs"

225

size="sm"

226

center

227

icon={

228

<ThemeIcon color="teal" size={24} radius="xl">

229

βœ“

230

</ThemeIcon>

231

}

232

>

233

<List.Item>Clone or download repository from GitHub</List.Item>

234

<List.Item>Install dependencies with yarn or npm</List.Item>

235

<List.Item>To start development server run npm start command</List.Item>

236

</List>

237

);

238

}

239

240

// Different item icons

241

function ListWithDifferentIcons() {

242

return (

243

<List spacing="xs" size="sm">

244

<List.Item

245

icon={

246

<ThemeIcon color="blue" size={24} radius="xl">

247

1

248

</ThemeIcon>

249

}

250

>

251

First item

252

</List.Item>

253

<List.Item

254

icon={

255

<ThemeIcon color="red" size={24} radius="xl">

256

2

257

</ThemeIcon>

258

}

259

>

260

Second item

261

</List.Item>

262

</List>

263

);

264

}

265

```

266

267

## Tree

268

269

Tree view component for hierarchical data display.

270

271

```typescript { .api }

272

interface TreeProps {

273

/** Tree data */

274

data: TreeNodeData[];

275

/** Level offset in px */

276

levelOffset?: number;

277

/** Expand on click */

278

expandOnClick?: boolean;

279

/** Tree selection mode */

280

selectOnClick?: boolean;

281

/** Clear selection on outside click */

282

clearSelectionOnOutsideClick?: boolean;

283

/** Selected node value */

284

selectedState?: [string[], (value: string[]) => void];

285

/** Expanded nodes */

286

expandedState?: [string[], (value: string[]) => void];

287

/** Called when node is selected */

288

onNodeSelect?: (node: TreeNodeData) => void;

289

/** Called when node is expanded/collapsed */

290

onNodeExpand?: (node: TreeNodeData) => void;

291

/** Render node function */

292

renderNode?: (payload: {

293

node: TreeNodeData;

294

expanded: boolean;

295

selected: boolean;

296

elementProps: React.ComponentPropsWithoutRef<'div'>;

297

}) => React.ReactNode;

298

}

299

300

interface TreeNodeData {

301

/** Node value, must be unique */

302

value: string;

303

/** Node label */

304

label: React.ReactNode;

305

/** Node children */

306

children?: TreeNodeData[];

307

/** If true, node cannot be selected */

308

disabled?: boolean;

309

/** Node data for custom rendering */

310

nodeProps?: Record<string, any>;

311

}

312

```

313

314

**Usage Example:**

315

316

```tsx

317

import { Tree } from '@mantine/core';

318

319

const data = [

320

{

321

value: 'src',

322

label: 'src',

323

children: [

324

{

325

value: 'components',

326

label: 'components',

327

children: [

328

{ value: 'Accordion.tsx', label: 'Accordion.tsx' },

329

{ value: 'Tree.tsx', label: 'Tree.tsx' },

330

{ value: 'Button.tsx', label: 'Button.tsx' },

331

],

332

},

333

{ value: 'hooks', label: 'hooks' },

334

{ value: 'utils', label: 'utils' },

335

],

336

},

337

{

338

value: 'package.json',

339

label: 'package.json',

340

},

341

{

342

value: 'tsconfig.json',

343

label: 'tsconfig.json',

344

},

345

];

346

347

function TreeDemo() {

348

return <Tree data={data} />;

349

}

350

```

351

352

## Timeline

353

354

Timeline component for displaying chronological events.

355

356

```typescript { .api }

357

interface TimelineProps {

358

/** Timeline children (Timeline.Item components) */

359

children: React.ReactNode;

360

/** Timeline orientation */

361

active?: number;

362

/** Timeline color */

363

color?: MantineColor;

364

/** Timeline radius */

365

radius?: MantineRadius;

366

/** Bullet size */

367

bulletSize?: number;

368

/** Line width */

369

lineWidth?: number;

370

/** If true, timeline will be reversed */

371

reverseActive?: boolean;

372

}

373

374

interface TimelineItemProps {

375

/** Item children */

376

children?: React.ReactNode;

377

/** Item bullet */

378

bullet?: React.ReactNode;

379

/** Item title */

380

title?: React.ReactNode;

381

/** Item color */

382

color?: MantineColor;

383

/** Bullet size */

384

bulletSize?: number;

385

/** Line variant */

386

lineVariant?: 'solid' | 'dashed' | 'dotted';

387

/** If true, item bullet will be hollow */

388

radius?: MantineRadius;

389

}

390

```

391

392

**Usage Example:**

393

394

```tsx

395

import { Timeline, Text } from '@mantine/core';

396

397

function TimelineDemo() {

398

return (

399

<Timeline active={1} bulletSize={24} lineWidth={2}>

400

<Timeline.Item bullet="πŸ“§" title="New email">

401

<Text color="dimmed" size="sm">You've got new email from Kristina Groves</Text>

402

<Text size="xs" mt={4}>2 minutes ago</Text>

403

</Timeline.Item>

404

405

<Timeline.Item bullet="πŸ“±" title="Another notification">

406

<Text color="dimmed" size="sm">You've got new message from Sarah Johnson</Text>

407

<Text size="xs" mt={4}>5 minutes ago</Text>

408

</Timeline.Item>

409

410

<Timeline.Item title="Bug fix" bullet="πŸ›" lineVariant="dashed">

411

<Text color="dimmed" size="sm">You've fixed a bug</Text>

412

<Text size="xs" mt={4}>10 minutes ago</Text>

413

</Timeline.Item>

414

415

<Timeline.Item title="User left a comment" bullet="πŸ’¬">

416

<Text color="dimmed" size="sm">You've got a comment from Robert</Text>

417

<Text size="xs" mt={4}>12 minutes ago</Text>

418

</Timeline.Item>

419

</Timeline>

420

);

421

}

422

```

423

424

## Card

425

426

Container component for grouping related content with optional sections.

427

428

```typescript { .api }

429

interface CardProps {

430

/** Card children */

431

children: React.ReactNode;

432

/** Card padding */

433

padding?: MantineSpacing;

434

/** Card radius */

435

radius?: MantineRadius;

436

/** If true, card will have border */

437

withBorder?: boolean;

438

/** Card shadow */

439

shadow?: MantineShadow;

440

}

441

442

interface CardSectionProps {

443

/** Section children */

444

children: React.ReactNode;

445

/** If true, section will inherit card padding */

446

inheritPadding?: boolean;

447

/** If true, section will have border */

448

withBorder?: boolean;

449

/** Section padding */

450

p?: MantineSpacing;

451

/** Section margin */

452

m?: MantineSpacing;

453

}

454

```

455

456

**Usage Example:**

457

458

```tsx

459

import { Card, Image, Text, Badge, Button, Group } from '@mantine/core';

460

461

function CardDemo() {

462

return (

463

<Card shadow="sm" padding="lg" radius="md" withBorder>

464

<Card.Section>

465

<Image

466

src="https://images.unsplash.com/photo-1527004013197-933c4bb611b3?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=720&q=80"

467

height={160}

468

alt="Norway"

469

/>

470

</Card.Section>

471

472

<Group justify="space-between" mt="md" mb="xs">

473

<Text fw={500}>Norway Fjord Adventures</Text>

474

<Badge color="pink" variant="light">

475

On Sale

476

</Badge>

477

</Group>

478

479

<Text size="sm" c="dimmed">

480

With Fjord Tours you can explore more of the magical fjord landscapes with tours and

481

activities on and around the fjords of Norway

482

</Text>

483

484

<Button color="blue" fullWidth mt="md" radius="md">

485

Book classic tour now

486

</Button>

487

</Card>

488

);

489

}

490

```

491

492

## Paper

493

494

Simple container component with background color and optional shadow/border.

495

496

```typescript { .api }

497

interface PaperProps {

498

/** Paper children */

499

children?: React.ReactNode;

500

/** Paper shadow */

501

shadow?: MantineShadow;

502

/** Paper padding */

503

p?: MantineSpacing;

504

/** Paper radius */

505

radius?: MantineRadius;

506

/** If true, paper will have border */

507

withBorder?: boolean;

508

}

509

```

510

511

**Usage Example:**

512

513

```tsx

514

import { Paper, Text } from '@mantine/core';

515

516

function PaperDemo() {

517

return (

518

<Paper shadow="xs" p="md">

519

<Text>Paper is the most basic ui component</Text>

520

</Paper>

521

);

522

}

523

```

524

525

## Badge

526

527

Small status or category indicator component.

528

529

```typescript { .api }

530

interface BadgeProps {

531

/** Badge children */

532

children: React.ReactNode;

533

/** Badge variant */

534

variant?: 'light' | 'filled' | 'outline' | 'dot' | 'transparent';

535

/** Badge size */

536

size?: MantineSize;

537

/** Badge radius */

538

radius?: MantineRadius;

539

/** Badge color */

540

color?: MantineColor;

541

/** Badge left section */

542

leftSection?: React.ReactNode;

543

/** Badge right section */

544

rightSection?: React.ReactNode;

545

/** If true, badge will take full width of container */

546

fullWidth?: boolean;

547

}

548

```

549

550

**Usage Example:**

551

552

```tsx

553

import { Badge, Group } from '@mantine/core';

554

555

function BadgeDemo() {

556

return (

557

<Group>

558

<Badge variant="light">Default</Badge>

559

<Badge variant="filled">Filled</Badge>

560

<Badge variant="outline">Outline</Badge>

561

<Badge variant="dot">Dot</Badge>

562

<Badge leftSection="πŸ“§" rightSection="5">

563

With sections

564

</Badge>

565

</Group>

566

);

567

}

568

```

569

570

## ThemeIcon

571

572

Icon wrapper component with theme-based styling.

573

574

```typescript { .api }

575

interface ThemeIconProps {

576

/** Icon children */

577

children: React.ReactNode;

578

/** Icon size */

579

size?: MantineSize | number;

580

/** Icon radius */

581

radius?: MantineRadius;

582

/** Icon variant */

583

variant?: 'filled' | 'light' | 'outline' | 'transparent' | 'white' | 'subtle';

584

/** Icon color */

585

color?: MantineColor;

586

/** Icon gradient (only for gradient variant) */

587

gradient?: MantineGradient;

588

/** If true, icon will auto adjust contrast */

589

autoContrast?: boolean;

590

}

591

```

592

593

**Usage Example:**

594

595

```tsx

596

import { ThemeIcon, Group } from '@mantine/core';

597

598

function ThemeIconDemo() {

599

return (

600

<Group>

601

<ThemeIcon variant="filled" size="lg">

602

πŸ“§

603

</ThemeIcon>

604

<ThemeIcon variant="light" color="red">

605

❀️

606

</ThemeIcon>

607

<ThemeIcon variant="outline" color="teal">

608

βœ“

609

</ThemeIcon>

610

<ThemeIcon variant="transparent">

611

πŸ”

612

</ThemeIcon>

613

</Group>

614

);

615

}

616

```

617

618

## Avatar

619

620

User avatar component with fallback and group support.

621

622

```typescript { .api }

623

interface AvatarProps {

624

/** Avatar image src */

625

src?: string | null;

626

/** Avatar alt text */

627

alt?: string;

628

/** Avatar radius */

629

radius?: MantineRadius;

630

/** Avatar size */

631

size?: MantineSize | number;

632

/** Avatar variant */

633

variant?: 'filled' | 'light' | 'outline' | 'transparent' | 'white';

634

/** Avatar color */

635

color?: MantineColor;

636

/** Avatar children (displayed when no image) */

637

children?: React.ReactNode;

638

/** Image props */

639

imageProps?: Record<string, any>;

640

}

641

642

interface AvatarGroupProps {

643

/** Group children */

644

children: React.ReactNode;

645

/** Space between avatars */

646

spacing?: MantineSpacing | number;

647

}

648

```

649

650

**Usage Example:**

651

652

```tsx

653

import { Avatar, Group } from '@mantine/core';

654

655

function AvatarDemo() {

656

return (

657

<Group>

658

<Avatar

659

src="https://images.unsplash.com/photo-1508214751196-bcfd4ca60f91?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=255&q=80"

660

alt="User Avatar"

661

/>

662

<Avatar color="cyan" radius="xl">MK</Avatar>

663

<Avatar color="blue">+5</Avatar>

664

</Group>

665

);

666

}

667

668

// Avatar group

669

function AvatarGroupDemo() {

670

return (

671

<Avatar.Group spacing="sm">

672

<Avatar src="image1.png" radius="xl" />

673

<Avatar src="image2.png" radius="xl" />

674

<Avatar src="image3.png" radius="xl" />

675

<Avatar radius="xl">+5</Avatar>

676

</Avatar.Group>

677

);

678

}

679

```

680

681

## Image

682

683

Enhanced image component with loading states and fallbacks.

684

685

```typescript { .api }

686

interface ImageProps {

687

/** Image src */

688

src?: string | null;

689

/** Image alt text */

690

alt?: string;

691

/** Image width */

692

w?: React.CSSProperties['width'];

693

/** Image height */

694

h?: React.CSSProperties['height'];

695

/** Image fit */

696

fit?: React.CSSProperties['objectFit'];

697

/** Image radius */

698

radius?: MantineRadius;

699

/** Fallback component */

700

fallbackSrc?: string;

701

/** Called when image fails to load */

702

onError?: () => void;

703

/** Called when image loads */

704

onLoad?: () => void;

705

}

706

```

707

708

**Usage Example:**

709

710

```tsx

711

import { Image } from '@mantine/core';

712

713

function ImageDemo() {

714

return (

715

<Image

716

radius="md"

717

h={200}

718

src="https://images.unsplash.com/photo-1511216335778-7cb8f49fa7a3?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=720&q=80"

719

alt="Random image"

720

fallbackSrc="https://placehold.co/600x400?text=Fallback"

721

/>

722

);

723

}

724

```

725

726

## ColorSwatch

727

728

Small color sample display component.

729

730

```typescript { .api }

731

interface ColorSwatchProps {

732

/** Swatch color */

733

color: string;

734

/** Swatch size */

735

size?: number;

736

/** Swatch radius */

737

radius?: MantineRadius;

738

/** If true, swatch will have border */

739

withShadow?: boolean;

740

/** Called when swatch is clicked */

741

onClick?: () => void;

742

/** Swatch children */

743

children?: React.ReactNode;

744

}

745

```

746

747

**Usage Example:**

748

749

```tsx

750

import { ColorSwatch, Group } from '@mantine/core';

751

752

function ColorSwatchDemo() {

753

return (

754

<Group>

755

<ColorSwatch color="#ff6b6b" />

756

<ColorSwatch color="#4ecdc4" />

757

<ColorSwatch color="#45b7d1" />

758

<ColorSwatch color="#96ceb4" size={50} />

759

<ColorSwatch color="#feca57" radius="xs" withShadow />

760

</Group>

761

);

762

}

763

```

764

765

## Divider

766

767

Content separator component with optional labels.

768

769

```typescript { .api }

770

interface DividerProps {

771

/** Divider color */

772

color?: MantineColor;

773

/** Divider orientation */

774

orientation?: 'horizontal' | 'vertical';

775

/** Divider size */

776

size?: MantineSize | number;

777

/** Divider variant */

778

variant?: 'solid' | 'dashed' | 'dotted';

779

/** Divider label */

780

label?: React.ReactNode;

781

/** Label position */

782

labelPosition?: 'left' | 'center' | 'right';

783

}

784

```

785

786

**Usage Example:**

787

788

```tsx

789

import { Divider, Text } from '@mantine/core';

790

791

function DividerDemo() {

792

return (

793

<div>

794

<Text>

795

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

796

</Text>

797

798

<Divider my="sm" />

799

800

<Text>

801

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.

802

</Text>

803

804

<Divider my="sm" variant="dashed" />

805

806

<Text>

807

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum.

808

</Text>

809

810

<Divider

811

my="xs"

812

label="Label on the left"

813

labelPosition="left"

814

/>

815

816

<Divider

817

my="xs"

818

label="Label in the center"

819

labelPosition="center"

820

/>

821

822

<Divider

823

my="xs"

824

label="Label on the right"

825

labelPosition="right"

826

/>

827

</div>

828

);

829

}

830

```

831

832

## Spoiler

833

834

Collapsible content component with show more/less functionality.

835

836

```typescript { .api }

837

interface SpoilerProps {

838

/** Spoiler children */

839

children: React.ReactNode;

840

/** Maximum height when collapsed */

841

maxHeight: number;

842

/** Show label */

843

showLabel?: React.ReactNode;

844

/** Hide label */

845

hideLabel?: React.ReactNode;

846

/** Transition duration */

847

transitionDuration?: number;

848

/** Called when spoiler state changes */

849

onExpandedChange?: (expanded: boolean) => void;

850

/** If true, spoiler is controlled */

851

expanded?: boolean;

852

/** Default expanded state */

853

defaultExpanded?: boolean;

854

}

855

```

856

857

**Usage Example:**

858

859

```tsx

860

import { Spoiler } from '@mantine/core';

861

862

function SpoilerDemo() {

863

return (

864

<Spoiler maxHeight={120} showLabel="Show more" hideLabel="Hide">

865

{/* Long content that will be collapsed */}

866

Lorem ipsum dolor sit amet consectetur adipisicing elit. Unde

867

provident eos fugiat id necessitatibus magni ducimus molestias. Placeat

868

consectetur consequuntur quod voluptatum perspiciatis repellat

869

consequatur, maxime mollitia, illo rerum sunt debitis aliquam in

870

inventore facere obcaecati harum vero molestias distinctio eaque.

871

Aspernatur corporis soluta dicta temporibus. Enim quia voluptatum

872

consequatur fugiat eos, distinctio excepturi amet est! Aut corporis

873

veritatis laboriosam distinctio stone unde aliquam minima. Modi

874

consectetur tempore maiores esse dolorum nemo voluptatum culpa

875

voluptatem non facilis eligendi explicabo quis vel, placeat quasi

876

dignissimos. Voluptatibus laudantium distinctio reiciendis eius ex

877

aliquid quis sit dolor eum reprehenderit quae placeat provident

878

mollitia eos aliquam quibusdam sapiente aperiam accusamus non velit,

879

illo quam eaque!

880

</Spoiler>

881

);

882

}

883

```

884

885

## AspectRatio

886

887

Container that maintains aspect ratio of its content.

888

889

```typescript { .api }

890

interface AspectRatioProps {

891

/** Aspect ratio */

892

ratio: number;

893

/** Container children */

894

children: React.ReactNode;

895

}

896

```

897

898

**Usage Example:**

899

900

```tsx

901

import { AspectRatio } from '@mantine/core';

902

903

function AspectRatioDemo() {

904

return (

905

<AspectRatio ratio={16 / 9}>

906

<iframe

907

src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3024.1399415657293!2d-74.00369368459418!3d40.741895479327494!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x89c259a9b3117469%3A0xd134e199a405a163!2sEmpire%20State%20Building!5e0!3m2!1sen!2sus!4v1616590069614!5m2!1sen!2sus"

908

title="Google map"

909

style={{ border: 0 }}

910

/>

911

</AspectRatio>

912

);

913

}

914

```

915

916

## Indicator

917

918

Badge overlay component for showing notifications or status.

919

920

```typescript { .api }

921

interface IndicatorProps {

922

/** Indicator children (element to add indicator to) */

923

children: React.ReactNode;

924

/** Indicator content */

925

label?: React.ReactNode;

926

/** Indicator size */

927

size?: number;

928

/** Indicator radius */

929

radius?: MantineRadius;

930

/** Indicator color */

931

color?: MantineColor;

932

/** Indicator position */

933

position?: 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end';

934

/** Indicator offset */

935

offset?: number;

936

/** If true, indicator will be disabled */

937

disabled?: boolean;

938

/** If true, indicator will not render when label is empty */

939

showZero?: boolean;

940

/** If true, indicator will have dot style */

941

dot?: boolean;

942

/** If true, indicator will be inline */

943

inline?: boolean;

944

/** Processing animation */

945

processing?: boolean;

946

/** If true, indicator will have border */

947

withBorder?: boolean;

948

}

949

```

950

951

**Usage Example:**

952

953

```tsx

954

import { Indicator, Avatar, Button, Group } from '@mantine/core';

955

956

function IndicatorDemo() {

957

return (

958

<Group>

959

<Indicator>

960

<Avatar

961

size="lg"

962

src="https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=250&q=80"

963

/>

964

</Indicator>

965

966

<Indicator label="New" size={16}>

967

<Avatar

968

size="lg"

969

src="https://images.unsplash.com/photo-1508214751196-bcfd4ca60f91?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=250&q=80"

970

/>

971

</Indicator>

972

973

<Indicator label="99+" inline size={22} color="red">

974

<Button variant="outline">Button</Button>

975

</Indicator>

976

</Group>

977

);

978

}

979

```

980

981

## Pill

982

983

Pill-shaped tag component for labels and selections.

984

985

```typescript { .api }

986

interface PillProps {

987

/** Pill children */

988

children?: React.ReactNode;

989

/** If true, pill will have remove button */

990

withRemoveButton?: boolean;

991

/** Called when remove button is clicked */

992

onRemove?: () => void;

993

/** Remove button aria-label */

994

removeButtonProps?: React.ComponentPropsWithoutRef<'button'>;

995

/** Pill size */

996

size?: MantineSize;

997

}

998

```

999

1000

**Usage Example:**

1001

1002

```tsx

1003

import { Pill, Group } from '@mantine/core';

1004

1005

function PillDemo() {

1006

return (

1007

<Group>

1008

<Pill>React</Pill>

1009

<Pill>Vue</Pill>

1010

<Pill withRemoveButton onRemove={() => console.log('removed')}>

1011

Angular

1012

</Pill>

1013

</Group>

1014

);

1015

}

1016

```

1017

1018

## Theme Integration

1019

1020

Data display components integrate with the Mantine theme system:

1021

1022

```tsx

1023

import { MantineProvider } from '@mantine/core';

1024

1025

const theme = {

1026

components: {

1027

Table: {

1028

defaultProps: {

1029

striped: true,

1030

highlightOnHover: true,

1031

withBorder: true,

1032

},

1033

},

1034

Card: {

1035

defaultProps: {

1036

shadow: 'sm',

1037

radius: 'md',

1038

withBorder: true,

1039

},

1040

},

1041

Badge: {

1042

defaultProps: {

1043

variant: 'light',

1044

size: 'sm',

1045

},

1046

},

1047

},

1048

};

1049

```

1050

1051

## Common Usage Patterns

1052

1053

**Responsive Table:**

1054

```tsx

1055

import { Table, ScrollArea } from '@mantine/core';

1056

1057

function ResponsiveTable({ data }) {

1058

return (

1059

<ScrollArea>

1060

<Table>

1061

<Table.Thead>

1062

<Table.Tr>

1063

{data.headers.map(header => (

1064

<Table.Th key={header}>{header}</Table.Th>

1065

))}

1066

</Table.Tr>

1067

</Table.Thead>

1068

<Table.Tbody>

1069

{data.rows.map(row => (

1070

<Table.Tr key={row.id}>

1071

{row.cells.map(cell => (

1072

<Table.Td key={cell.id}>{cell.value}</Table.Td>

1073

))}

1074

</Table.Tr>

1075

))}

1076

</Table.Tbody>

1077

</Table>

1078

</ScrollArea>

1079

);

1080

}

1081

```

1082

1083

**Data Card Grid:**

1084

```tsx

1085

import { Card, SimpleGrid, Image, Text, Badge, Button } from '@mantine/core';

1086

1087

function DataCardGrid({ items }) {

1088

return (

1089

<SimpleGrid cols={{ base: 1, sm: 2, lg: 3 }}>

1090

{items.map(item => (

1091

<Card key={item.id} shadow="sm" padding="lg" radius="md" withBorder>

1092

<Card.Section>

1093

<Image src={item.image} height={160} alt={item.title} />

1094

</Card.Section>

1095

1096

<Group justify="space-between" mt="md" mb="xs">

1097

<Text fw={500}>{item.title}</Text>

1098

<Badge color={item.status === 'new' ? 'pink' : 'gray'}>

1099

{item.status}

1100

</Badge>

1101

</Group>

1102

1103

<Text size="sm" c="dimmed">

1104

{item.description}

1105

</Text>

1106

1107

<Button color="blue" fullWidth mt="md" radius="md">

1108

View Details

1109

</Button>

1110

</Card>

1111

))}

1112

</SimpleGrid>

1113

);

1114

}

1115

```