or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

components.mdcomposables.mddata-display.mddirectives.mdfeedback.mdforms.mdframework-core.mdicons.mdindex.mdinternationalization.mdlab-components.mdnavigation.mdtheming.mdtransitions.mdutilities.md

icons.mddocs/

0

# Icons

1

2

Comprehensive icon system supporting multiple icon sets including Material Design Icons, Font Awesome, and custom icon implementations with flexible configuration and theming support.

3

4

## Capabilities

5

6

### IconOptions Interface

7

8

Core configuration interface for setting up the icon system during Vuetify initialization.

9

10

```typescript { .api }

11

/**

12

* Icon system configuration options

13

*/

14

interface IconOptions {

15

/** Default icon set to use */

16

defaultSet?: string;

17

/** Icon alias mappings */

18

aliases?: IconAliases;

19

/** Available icon sets */

20

sets?: Record<string, IconSet>;

21

}

22

23

interface IconAliases {

24

/** Collapse icon */

25

collapse?: IconValue;

26

/** Complete icon */

27

complete?: IconValue;

28

/** Cancel icon */

29

cancel?: IconValue;

30

/** Close icon */

31

close?: IconValue;

32

/** Delete icon */

33

delete?: IconValue;

34

/** Clear icon */

35

clear?: IconValue;

36

/** Success icon */

37

success?: IconValue;

38

/** Info icon */

39

info?: IconValue;

40

/** Warning icon */

41

warning?: IconValue;

42

/** Error icon */

43

error?: IconValue;

44

/** Prev icon */

45

prev?: IconValue;

46

/** Next icon */

47

next?: IconValue;

48

/** Check icon */

49

checkboxOn?: IconValue;

50

/** Unchecked icon */

51

checkboxOff?: IconValue;

52

/** Indeterminate icon */

53

checkboxIndeterminate?: IconValue;

54

/** Delimiter icon */

55

delimiter?: IconValue;

56

/** Sort icon */

57

sort?: IconValue;

58

/** Expand icon */

59

expand?: IconValue;

60

/** Menu icon */

61

menu?: IconValue;

62

/** Subgroup icon */

63

subgroup?: IconValue;

64

/** Dropdown icon */

65

dropdown?: IconValue;

66

/** Radio on icon */

67

radioOn?: IconValue;

68

/** Radio off icon */

69

radioOff?: IconValue;

70

/** Edit icon */

71

edit?: IconValue;

72

/** Rating empty icon */

73

ratingEmpty?: IconValue;

74

/** Rating full icon */

75

ratingFull?: IconValue;

76

/** Rating half icon */

77

ratingHalf?: IconValue;

78

/** Loading icon */

79

loading?: IconValue;

80

/** First page icon */

81

first?: IconValue;

82

/** Last page icon */

83

last?: IconValue;

84

/** Unfold icon */

85

unfold?: IconValue;

86

/** File icon */

87

file?: IconValue;

88

/** Plus icon */

89

plus?: IconValue;

90

/** Minus icon */

91

minus?: IconValue;

92

/** Calendar icon */

93

calendar?: IconValue;

94

}

95

96

interface IconSet {

97

/** Icon component to render */

98

component: Component;

99

/** Default props for icon component */

100

props?: IconProps;

101

}

102

103

interface IconProps {

104

/** Icon color */

105

color?: string;

106

/** Icon size */

107

size?: string | number;

108

/** Icon tag */

109

tag?: string;

110

/** Icon theme */

111

theme?: string;

112

}

113

114

type IconValue = string | [string, number] | ComponentPublicInstance;

115

```

116

117

**Usage Examples:**

118

119

```javascript

120

// vuetify.js configuration

121

import { createVuetify } from 'vuetify';

122

import { aliases, mdi } from 'vuetify/iconsets/mdi';

123

import { fa } from 'vuetify/iconsets/fa';

124

import '@mdi/font/css/materialdesignicons.css';

125

import '@fortawesome/fontawesome-free/css/all.css';

126

127

const vuetify = createVuetify({

128

icons: {

129

defaultSet: 'mdi',

130

aliases,

131

sets: {

132

mdi,

133

fa,

134

custom: {

135

component: CustomIconComponent,

136

props: {

137

tag: 'i',

138

size: 'default'

139

}

140

}

141

}

142

}

143

});

144

```

145

146

### VIcon Component

147

148

Core icon display component with support for multiple icon sets and customization options.

149

150

```typescript { .api }

151

/**

152

* Icon display component

153

*/

154

const VIcon: Component;

155

156

interface IconComponentProps {

157

/** Icon identifier */

158

icon?: IconValue;

159

/** Icon color */

160

color?: string;

161

/** Icon size */

162

size?: string | number | 'x-small' | 'small' | 'default' | 'large' | 'x-large';

163

/** Icon density */

164

density?: 'default' | 'comfortable' | 'compact';

165

/** Icon tag element */

166

tag?: string;

167

/** Icon theme */

168

theme?: string;

169

/** Start icon (for text direction) */

170

start?: boolean;

171

/** End icon (for text direction) */

172

end?: boolean;

173

/** Disabled state */

174

disabled?: boolean;

175

}

176

177

// Events

178

interface IconEvents {

179

'click': (event: MouseEvent) => void;

180

}

181

```

182

183

**Usage Examples:**

184

185

```vue

186

<template>

187

<div>

188

<!-- Basic icons -->

189

<v-icon>mdi-home</v-icon>

190

<v-icon icon="mdi-account" />

191

<v-icon>$vuetify.icons.menu</v-icon>

192

193

<!-- Sized icons -->

194

<v-icon size="x-small">mdi-heart</v-icon>

195

<v-icon size="small">mdi-heart</v-icon>

196

<v-icon size="default">mdi-heart</v-icon>

197

<v-icon size="large">mdi-heart</v-icon>

198

<v-icon size="x-large">mdi-heart</v-icon>

199

<v-icon size="64">mdi-heart</v-icon>

200

201

<!-- Colored icons -->

202

<v-icon color="primary">mdi-home</v-icon>

203

<v-icon color="red">mdi-heart</v-icon>

204

<v-icon color="#FF5722">mdi-favorite</v-icon>

205

206

<!-- Clickable icons -->

207

<v-icon @click="handleClick">mdi-menu</v-icon>

208

209

<!-- Icons in buttons -->

210

<v-btn icon>

211

<v-icon>mdi-heart</v-icon>

212

</v-btn>

213

214

<v-btn prepend-icon="mdi-account" append-icon="mdi-chevron-down">

215

User Menu

216

</v-btn>

217

218

<!-- Font Awesome icons -->

219

<v-icon>fas fa-home</v-icon>

220

<v-icon>fab fa-vuejs</v-icon>

221

222

<!-- Custom icon component -->

223

<v-icon icon="custom:my-icon" />

224

225

<!-- Dynamic icons -->

226

<v-icon :icon="currentIcon" :color="iconColor" />

227

</div>

228

</template>

229

230

<script setup>

231

const currentIcon = ref('mdi-home');

232

const iconColor = ref('primary');

233

234

const handleClick = () => {

235

console.log('Icon clicked');

236

};

237

238

const cycleIcon = () => {

239

const icons = ['mdi-home', 'mdi-account', 'mdi-settings', 'mdi-heart'];

240

const currentIndex = icons.indexOf(currentIcon.value);

241

currentIcon.value = icons[(currentIndex + 1) % icons.length];

242

};

243

</script>

244

```

245

246

### Icon Sets

247

248

Pre-configured icon sets for different icon libraries with optimized loading and rendering.

249

250

```typescript { .api }

251

/**

252

* Material Design Icons (MDI) icon set

253

*/

254

interface MdiIconSet extends IconSet {

255

component: Component;

256

props: {

257

tag: 'i';

258

class: 'mdi';

259

};

260

}

261

262

/**

263

* Font Awesome icon set

264

*/

265

interface FontAwesomeIconSet extends IconSet {

266

component: Component;

267

props: {

268

tag: 'i';

269

class: string;

270

};

271

}

272

273

/**

274

* Material Design (Google) icon set

275

*/

276

interface MaterialIconSet extends IconSet {

277

component: Component;

278

props: {

279

tag: 'i';

280

class: 'material-icons';

281

};

282

}

283

284

/**

285

* SVG icon set for custom implementations

286

*/

287

interface SvgIconSet extends IconSet {

288

component: Component;

289

props: {

290

tag: 'svg';

291

viewBox: '0 0 24 24';

292

};

293

}

294

295

// Available icon sets

296

const mdi: MdiIconSet;

297

const fa: FontAwesomeIconSet;

298

const fa4: FontAwesomeIconSet; // Font Awesome 4 compatibility

299

const faSvg: SvgIconSet; // Font Awesome SVG

300

const md: MaterialIconSet; // Google Material Design

301

const mdiSvg: SvgIconSet; // MDI SVG format

302

```

303

304

**Usage Examples:**

305

306

```vue

307

<template>

308

<div>

309

<!-- Material Design Icons -->

310

<v-card class="mb-4">

311

<v-card-title>

312

<v-icon>mdi-palette</v-icon>

313

Material Design Icons

314

</v-card-title>

315

<v-card-text>

316

<div class="icon-grid">

317

<div v-for="icon in mdiIcons" :key="icon.name" class="icon-item">

318

<v-icon :size="32">{{ icon.name }}</v-icon>

319

<span class="icon-label">{{ icon.label }}</span>

320

</div>

321

</div>

322

</v-card-text>

323

</v-card>

324

325

<!-- Font Awesome Icons -->

326

<v-card class="mb-4">

327

<v-card-title>

328

<v-icon>fab fa-font-awesome</v-icon>

329

Font Awesome Icons

330

</v-card-title>

331

<v-card-text>

332

<div class="icon-grid">

333

<div v-for="icon in faIcons" :key="icon.name" class="icon-item">

334

<v-icon :size="32">{{ icon.name }}</v-icon>

335

<span class="icon-label">{{ icon.label }}</span>

336

</div>

337

</div>

338

</v-card-text>

339

</v-card>

340

341

<!-- Google Material Icons -->

342

<v-card class="mb-4">

343

<v-card-title>

344

<v-icon>md:home</v-icon>

345

Google Material Icons

346

</v-card-title>

347

<v-card-text>

348

<div class="icon-grid">

349

<div v-for="icon in materialIcons" :key="icon.name" class="icon-item">

350

<v-icon :size="32">{{ icon.name }}</v-icon>

351

<span class="icon-label">{{ icon.label }}</span>

352

</div>

353

</div>

354

</v-card-text>

355

</v-card>

356

357

<!-- SVG Icons -->

358

<v-card class="mb-4">

359

<v-card-title>

360

<CustomSvgIcon />

361

Custom SVG Icons

362

</v-card-title>

363

<v-card-text>

364

<div class="icon-grid">

365

<div v-for="icon in svgIcons" :key="icon.name" class="icon-item">

366

<component :is="icon.component" :size="32" />

367

<span class="icon-label">{{ icon.label }}</span>

368

</div>

369

</div>

370

</v-card-text>

371

</v-card>

372

373

<!-- Icon set comparison -->

374

<v-card>

375

<v-card-title>Icon Set Comparison</v-card-title>

376

<v-card-text>

377

<v-simple-table>

378

<template #default>

379

<thead>

380

<tr>

381

<th>Icon Set</th>

382

<th>Format</th>

383

<th>Size</th>

384

<th>Icons Count</th>

385

<th>Example</th>

386

</tr>

387

</thead>

388

<tbody>

389

<tr>

390

<td>Material Design Icons</td>

391

<td>Font/SVG</td>

392

<td>~500KB</td>

393

<td>7000+</td>

394

<td><v-icon>mdi-vuetify</v-icon></td>

395

</tr>

396

<tr>

397

<td>Font Awesome</td>

398

<td>Font/SVG</td>

399

<td>~400KB</td>

400

<td>1600+</td>

401

<td><v-icon>fas fa-star</v-icon></td>

402

</tr>

403

<tr>

404

<td>Google Material</td>

405

<td>Font</td>

406

<td>~50KB</td>

407

<td>1000+</td>

408

<td><v-icon>md:star</v-icon></td>

409

</tr>

410

<tr>

411

<td>Custom SVG</td>

412

<td>SVG</td>

413

<td>Varies</td>

414

<td>Custom</td>

415

<td><CustomSvgIcon size="24" /></td>

416

</tr>

417

</tbody>

418

</template>

419

</v-simple-table>

420

</v-card-text>

421

</v-card>

422

</div>

423

</template>

424

425

<script setup>

426

const mdiIcons = [

427

{ name: 'mdi-home', label: 'Home' },

428

{ name: 'mdi-account', label: 'Account' },

429

{ name: 'mdi-settings', label: 'Settings' },

430

{ name: 'mdi-heart', label: 'Heart' },

431

{ name: 'mdi-star', label: 'Star' },

432

{ name: 'mdi-check', label: 'Check' },

433

{ name: 'mdi-close', label: 'Close' },

434

{ name: 'mdi-menu', label: 'Menu' },

435

{ name: 'mdi-search', label: 'Search' },

436

{ name: 'mdi-shopping', label: 'Shopping' }

437

];

438

439

const faIcons = [

440

{ name: 'fas fa-home', label: 'Home' },

441

{ name: 'fas fa-user', label: 'User' },

442

{ name: 'fas fa-cog', label: 'Settings' },

443

{ name: 'fas fa-heart', label: 'Heart' },

444

{ name: 'fas fa-star', label: 'Star' },

445

{ name: 'fas fa-check', label: 'Check' },

446

{ name: 'fas fa-times', label: 'Close' },

447

{ name: 'fas fa-bars', label: 'Menu' },

448

{ name: 'fas fa-search', label: 'Search' },

449

{ name: 'fas fa-shopping-cart', label: 'Shopping' }

450

];

451

452

const materialIcons = [

453

{ name: 'md:home', label: 'Home' },

454

{ name: 'md:person', label: 'Person' },

455

{ name: 'md:settings', label: 'Settings' },

456

{ name: 'md:favorite', label: 'Favorite' },

457

{ name: 'md:star', label: 'Star' },

458

{ name: 'md:check', label: 'Check' },

459

{ name: 'md:close', label: 'Close' },

460

{ name: 'md:menu', label: 'Menu' },

461

{ name: 'md:search', label: 'Search' },

462

{ name: 'md:shopping_cart', label: 'Shopping' }

463

];

464

465

const svgIcons = [

466

{ name: 'custom-icon-1', label: 'Custom 1', component: CustomIcon1 },

467

{ name: 'custom-icon-2', label: 'Custom 2', component: CustomIcon2 },

468

];

469

</script>

470

471

<style>

472

.icon-grid {

473

display: grid;

474

grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));

475

gap: 16px;

476

}

477

478

.icon-item {

479

display: flex;

480

flex-direction: column;

481

align-items: center;

482

gap: 8px;

483

padding: 16px;

484

border-radius: 8px;

485

background: rgba(0,0,0,0.02);

486

transition: background-color 0.2s;

487

}

488

489

.icon-item:hover {

490

background: rgba(0,0,0,0.05);

491

}

492

493

.icon-label {

494

font-size: 0.75rem;

495

text-align: center;

496

color: rgba(0,0,0,0.6);

497

}

498

</style>

499

```

500

501

### Custom Icon Implementation

502

503

Creating and registering custom icon sets and components for specialized use cases.

504

505

```typescript { .api }

506

/**

507

* Custom icon component interface

508

*/

509

interface CustomIconComponent {

510

/** Icon name or identifier */

511

name?: string;

512

/** Icon size */

513

size?: string | number;

514

/** Icon color */

515

color?: string;

516

/** Additional CSS classes */

517

class?: string | string[];

518

/** Inline styles */

519

style?: Record<string, any>;

520

/** Accessibility label */

521

'aria-label'?: string;

522

/** Icon title for tooltips */

523

title?: string;

524

}

525

526

/**

527

* SVG icon definition

528

*/

529

interface SvgIconDefinition {

530

/** SVG path data */

531

path: string;

532

/** ViewBox dimensions */

533

viewBox?: string;

534

/** Icon width */

535

width?: number;

536

/** Icon height */

537

height?: number;

538

}

539

540

/**

541

* Icon registry for custom icons

542

*/

543

interface IconRegistry {

544

/** Register new icon */

545

register: (name: string, definition: SvgIconDefinition | Component) => void;

546

/** Unregister icon */

547

unregister: (name: string) => void;

548

/** Get icon definition */

549

get: (name: string) => SvgIconDefinition | Component | undefined;

550

/** List all registered icons */

551

list: () => string[];

552

}

553

```

554

555

**Usage Examples:**

556

557

```vue

558

<template>

559

<div>

560

<!-- Custom SVG icon component -->

561

<svg-icon name="custom-logo" :size="48" color="primary" />

562

563

<!-- Custom icon with animation -->

564

<animated-icon name="loading-spinner" :size="32" />

565

566

<!-- Icon with custom styling -->

567

<custom-icon

568

name="brand-icon"

569

:size="40"

570

:style="{ filter: 'drop-shadow(2px 2px 4px rgba(0,0,0,0.3))' }"

571

/>

572

573

<!-- Custom icon gallery -->

574

<v-card>

575

<v-card-title>Custom Icons</v-card-title>

576

<v-card-text>

577

<div class="custom-icon-grid">

578

<div

579

v-for="icon in customIcons"

580

:key="icon.name"

581

class="custom-icon-item"

582

>

583

<component

584

:is="icon.component"

585

:name="icon.name"

586

:size="48"

587

:color="icon.color"

588

/>

589

<span>{{ icon.label }}</span>

590

</div>

591

</div>

592

</v-card-text>

593

</v-card>

594

</div>

595

</template>

596

597

<script setup>

598

// Custom SVG Icon Component

599

const SvgIcon = defineComponent({

600

props: {

601

name: String,

602

size: {

603

type: [String, Number],

604

default: 24

605

},

606

color: {

607

type: String,

608

default: 'currentColor'

609

}

610

},

611

setup(props) {

612

const iconDefinitions = {

613

'custom-logo': {

614

path: 'M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5',

615

viewBox: '0 0 24 24'

616

},

617

'brand-icon': {

618

path: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z',

619

viewBox: '0 0 24 24'

620

}

621

};

622

623

const iconDef = computed(() => iconDefinitions[props.name]);

624

625

return () => {

626

if (!iconDef.value) return null;

627

628

return h('svg', {

629

width: props.size,

630

height: props.size,

631

viewBox: iconDef.value.viewBox,

632

fill: props.color,

633

class: 'custom-svg-icon'

634

}, [

635

h('path', { d: iconDef.value.path })

636

]);

637

};

638

}

639

});

640

641

// Animated Icon Component

642

const AnimatedIcon = defineComponent({

643

props: {

644

name: String,

645

size: {

646

type: [String, Number],

647

default: 24

648

}

649

},

650

setup(props) {

651

const animations = {

652

'loading-spinner': {

653

path: 'M12,4V2A10,10 0 0,0 2,12H4A8,8 0 0,1 12,4Z',

654

animation: 'spin 1s linear infinite'

655

},

656

'pulse-heart': {

657

path: 'M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5 2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z',

658

animation: 'pulse 2s ease-in-out infinite'

659

}

660

};

661

662

const iconDef = computed(() => animations[props.name]);

663

664

return () => {

665

if (!iconDef.value) return null;

666

667

return h('svg', {

668

width: props.size,

669

height: props.size,

670

viewBox: '0 0 24 24',

671

fill: 'currentColor',

672

style: {

673

animation: iconDef.value.animation

674

},

675

class: 'animated-icon'

676

}, [

677

h('path', { d: iconDef.value.path })

678

]);

679

};

680

}

681

});

682

683

const customIcons = [

684

{

685

name: 'custom-logo',

686

label: 'Custom Logo',

687

component: SvgIcon,

688

color: 'primary'

689

},

690

{

691

name: 'brand-icon',

692

label: 'Brand Icon',

693

component: SvgIcon,

694

color: 'success'

695

},

696

{

697

name: 'loading-spinner',

698

label: 'Loading',

699

component: AnimatedIcon,

700

color: 'info'

701

},

702

{

703

name: 'pulse-heart',

704

label: 'Pulse Heart',

705

component: AnimatedIcon,

706

color: 'error'

707

}

708

];

709

</script>

710

711

<style>

712

@keyframes spin {

713

from { transform: rotate(0deg); }

714

to { transform: rotate(360deg); }

715

}

716

717

@keyframes pulse {

718

0%, 100% { transform: scale(1); }

719

50% { transform: scale(1.2); }

720

}

721

722

.custom-icon-grid {

723

display: grid;

724

grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));

725

gap: 20px;

726

}

727

728

.custom-icon-item {

729

display: flex;

730

flex-direction: column;

731

align-items: center;

732

gap: 12px;

733

padding: 20px;

734

border-radius: 12px;

735

background: rgba(0,0,0,0.02);

736

transition: all 0.3s ease;

737

}

738

739

.custom-icon-item:hover {

740

background: rgba(0,0,0,0.05);

741

transform: translateY(-2px);

742

}

743

744

.animated-icon {

745

transform-origin: center;

746

}

747

748

.custom-svg-icon {

749

transition: all 0.2s ease;

750

}

751

</style>

752

```

753

754

### Icon Loading and Performance

755

756

Optimization strategies for icon loading, bundle size management, and performance considerations.

757

758

```typescript { .api }

759

/**

760

* Icon loading strategies

761

*/

762

interface IconLoadingOptions {

763

/** Lazy load icons */

764

lazy?: boolean;

765

/** Preload critical icons */

766

preload?: string[];

767

/** Icon bundle splitting */

768

bundles?: IconBundle[];

769

/** Cache configuration */

770

cache?: IconCacheOptions;

771

}

772

773

interface IconBundle {

774

/** Bundle name */

775

name: string;

776

/** Icons in bundle */

777

icons: string[];

778

/** Loading strategy */

779

strategy: 'eager' | 'lazy' | 'preload';

780

}

781

782

interface IconCacheOptions {

783

/** Cache duration in milliseconds */

784

duration?: number;

785

/** Maximum cache size */

786

maxSize?: number;

787

/** Storage type */

788

storage?: 'memory' | 'localStorage' | 'sessionStorage';

789

}

790

791

/**

792

* Tree shaking support for icons

793

*/

794

interface TreeShakableIconSet {

795

/** Only include used icons */

796

treeShake: boolean;

797

/** Icon usage tracking */

798

usage?: IconUsageTracker;

799

}

800

801

interface IconUsageTracker {

802

/** Track icon usage */

803

track: (iconName: string) => void;

804

/** Get usage statistics */

805

getStats: () => IconUsageStats;

806

/** Reset tracking data */

807

reset: () => void;

808

}

809

810

interface IconUsageStats {

811

/** Total icons used */

812

totalUsed: number;

813

/** Most used icons */

814

mostUsed: Array<{ name: string; count: number }>;

815

/** Unused icons */

816

unused: string[];

817

}

818

```

819

820

**Usage Examples:**

821

822

```javascript

823

// Optimized icon configuration

824

import { createVuetify } from 'vuetify';

825

826

// Tree-shaken icon imports (only imports used icons)

827

import {

828

mdiHome,

829

mdiAccount,

830

mdiSettings,

831

mdiHeart,

832

mdiStar

833

} from '@mdi/js';

834

835

// Custom icon set with tree shaking

836

const optimizedMdi = {

837

component: (props) => h(SvgIcon, props),

838

props: {

839

tag: 'svg'

840

},

841

// Define only the icons you need

842

icons: {

843

home: mdiHome,

844

account: mdiAccount,

845

settings: mdiSettings,

846

heart: mdiHeart,

847

star: mdiStar

848

}

849

};

850

851

const vuetify = createVuetify({

852

icons: {

853

defaultSet: 'optimizedMdi',

854

sets: {

855

optimizedMdi

856

}

857

}

858

});

859

860

// Lazy loading icon strategy

861

const lazyIconLoader = {

862

async loadIcon(iconName) {

863

// Dynamic import for unused icons

864

const iconModule = await import(`@mdi/js/${iconName}`);

865

return iconModule[iconName];

866

},

867

868

cache: new Map(),

869

870

async getIcon(iconName) {

871

if (this.cache.has(iconName)) {

872

return this.cache.get(iconName);

873

}

874

875

const iconData = await this.loadIcon(iconName);

876

this.cache.set(iconName, iconData);

877

return iconData;

878

}

879

};

880

881

// Performance monitoring

882

const iconPerformanceMonitor = {

883

startTimes: new Map(),

884

885

startLoad(iconName) {

886

this.startTimes.set(iconName, performance.now());

887

},

888

889

endLoad(iconName) {

890

const startTime = this.startTimes.get(iconName);

891

if (startTime) {

892

const loadTime = performance.now() - startTime;

893

console.log(`Icon ${iconName} loaded in ${loadTime.toFixed(2)}ms`);

894

this.startTimes.delete(iconName);

895

}

896

}

897

};

898

```

899

900

## Types

901

902

```typescript { .api }

903

// Core icon types

904

type IconIdentifier = string;

905

type IconSize = 'x-small' | 'small' | 'default' | 'large' | 'x-large' | number | string;

906

type IconColor = string;

907

908

// Icon value types

909

type IconValue =

910

| string // Icon name: 'mdi-home'

911

| [string, number] // Icon with rotation: ['mdi-home', 90]

912

| ComponentPublicInstance; // Custom component

913

914

// Icon set types

915

type IconSetName = 'mdi' | 'fa' | 'fa4' | 'fa-svg' | 'md' | 'mdi-svg' | string;

916

917

// Icon format types

918

type IconFormat = 'font' | 'svg' | 'component';

919

920

// Icon component types

921

interface IconComponentType {

922

name: string;

923

props: Record<string, any>;

924

render: () => VNode;

925

}

926

927

// Accessibility types

928

interface IconAccessibility {

929

label?: string;

930

describedBy?: string;

931

hidden?: boolean;

932

role?: string;

933

}

934

935

// Icon state types

936

type IconState = 'loading' | 'loaded' | 'error' | 'cached';

937

938

// Icon metrics

939

interface IconMetrics {

940

loadTime: number;

941

renderTime: number;

942

cacheHit: boolean;

943

bundleSize: number;

944

}

945

946

// Icon theme integration

947

interface IconTheme {

948

colors: Record<string, string>;

949

sizes: Record<string, number>;

950

variants: Record<string, IconProps>;

951

}

952

```