0
# Interactive Components
1
2
JavaScript-powered components providing rich interactive functionality including modal dialogs, dropdowns, tabs, collapsibles, and other dynamic UI elements with consistent Material Design styling and behavior.
3
4
## Capabilities
5
6
### Modal
7
8
Modal dialog component for overlaying content with backdrop and customizable animations.
9
10
```javascript { .api }
11
/**
12
* Modal dialog component
13
* @param el - Modal element (usually with .modal class)
14
* @param options - Configuration options
15
*/
16
class Modal {
17
constructor(el: Element, options?: ModalOptions);
18
19
/** Initialize modal instances */
20
static init(els: Element | NodeList, options?: ModalOptions): Modal | Modal[];
21
22
/** Get existing modal instance */
23
static getInstance(el: Element): Modal;
24
25
/** Get default options */
26
static get defaults(): ModalOptions;
27
28
/** Open the modal */
29
open(trigger?: Element): void;
30
31
/** Close the modal */
32
close(): void;
33
34
/** Destroy modal instance */
35
destroy(): void;
36
37
/** Current open state */
38
isOpen: boolean;
39
40
/** Modal element */
41
el: Element;
42
43
/** Configuration options */
44
options: ModalOptions;
45
}
46
47
interface ModalOptions {
48
/** Overlay opacity (0-1) */
49
opacity?: number; // default: 0.5
50
51
/** Enter animation duration in milliseconds */
52
inDuration?: number; // default: 250
53
54
/** Exit animation duration in milliseconds */
55
outDuration?: number; // default: 250
56
57
/** Callback before modal opens */
58
onOpenStart?: () => void;
59
60
/** Callback after modal opens */
61
onOpenEnd?: () => void;
62
63
/** Callback before modal closes */
64
onCloseStart?: () => void;
65
66
/** Callback after modal closes */
67
onCloseEnd?: () => void;
68
69
/** Prevent background page scrolling when modal is open */
70
preventScrolling?: boolean; // default: true
71
72
/** Allow modal to be dismissed by clicking overlay or pressing ESC */
73
dismissible?: boolean; // default: true
74
75
/** Starting vertical position */
76
startingTop?: string; // default: "4%"
77
78
/** Ending vertical position */
79
endingTop?: string; // default: "10%"
80
}
81
```
82
83
**Usage Examples:**
84
85
```html
86
<!-- Modal HTML structure -->
87
<div id="modal1" class="modal">
88
<div class="modal-content">
89
<h4>Modal Header</h4>
90
<p>Modal content goes here.</p>
91
</div>
92
<div class="modal-footer">
93
<a href="#!" class="modal-close waves-effect btn-flat">Agree</a>
94
</div>
95
</div>
96
97
<!-- Modal trigger -->
98
<a class="waves-effect waves-light btn modal-trigger" href="#modal1">Launch Modal</a>
99
```
100
101
```javascript
102
// Initialize modal
103
const elems = document.querySelectorAll('.modal');
104
const instances = M.Modal.init(elems, {
105
opacity: 0.7,
106
dismissible: false,
107
onOpenEnd: () => console.log('Modal opened')
108
});
109
110
// Programmatic control
111
const instance = M.Modal.getInstance(document.getElementById('modal1'));
112
instance.open();
113
```
114
115
### Dropdown
116
117
Dropdown menu component for creating interactive dropdown lists and menus.
118
119
```javascript { .api }
120
/**
121
* Dropdown menu component
122
* @param el - Trigger element (usually a button)
123
* @param options - Configuration options
124
*/
125
class Dropdown {
126
constructor(el: Element, options?: DropdownOptions);
127
128
static init(els: Element | NodeList, options?: DropdownOptions): Dropdown | Dropdown[];
129
static getInstance(el: Element): Dropdown;
130
static get defaults(): DropdownOptions;
131
132
/** Open dropdown */
133
open(): void;
134
135
/** Close dropdown */
136
close(): void;
137
138
/** Recalculate dropdown dimensions */
139
recalculateDimensions(): void;
140
141
destroy(): void;
142
143
/** Current open state */
144
isOpen: boolean;
145
146
/** Indicates if dropdown content is scrollable */
147
isScrollable: boolean;
148
149
/** Touch movement state tracking */
150
isTouchMoving: boolean;
151
152
/** Currently focused item index for keyboard navigation */
153
focusedIndex: number;
154
155
/** Current filter query for keyboard navigation */
156
filterQuery: string[];
157
158
/** Dropdown element */
159
el: Element;
160
161
/** Dropdown content element */
162
dropdownEl: Element;
163
164
/** Configuration options */
165
options: DropdownOptions;
166
}
167
168
interface DropdownOptions {
169
/** Dropdown alignment relative to trigger */
170
alignment?: 'left' | 'right'; // default: 'left'
171
172
/** Automatically focus dropdown when opened */
173
autoFocus?: boolean; // default: true
174
175
/** Constrain dropdown width to trigger width */
176
constrainWidth?: boolean; // default: true
177
178
/** Container element for dropdown */
179
container?: Element; // default: document.body
180
181
/** Position dropdown over trigger */
182
coverTrigger?: boolean; // default: true
183
184
/** Close dropdown when item is clicked */
185
closeOnClick?: boolean; // default: true
186
187
/** Open dropdown on hover instead of click */
188
hover?: boolean; // default: false
189
190
/** Enter animation duration */
191
inDuration?: number; // default: 150
192
193
/** Exit animation duration */
194
outDuration?: number; // default: 250
195
196
/** Callbacks */
197
onOpenStart?: () => void;
198
onOpenEnd?: () => void;
199
onCloseStart?: () => void;
200
onCloseEnd?: () => void;
201
onItemClick?: (item: Element) => void;
202
}
203
```
204
205
**Usage Examples:**
206
207
```html
208
<!-- Dropdown structure -->
209
<a class='dropdown-trigger btn' href='#' data-target='dropdown1'>Drop Me!</a>
210
<ul id='dropdown1' class='dropdown-content'>
211
<li><a href="#!">One</a></li>
212
<li><a href="#!">Two</a></li>
213
<li class="divider" tabindex="-1"></li>
214
<li><a href="#!">Three</a></li>
215
</ul>
216
```
217
218
```javascript
219
// Initialize dropdown
220
const elems = document.querySelectorAll('.dropdown-trigger');
221
const instances = M.Dropdown.init(elems, {
222
coverTrigger: false,
223
alignment: 'right'
224
});
225
```
226
227
### Tabs
228
229
Tab navigation component for organizing content into tabbed interfaces.
230
231
```javascript { .api }
232
/**
233
* Tab navigation component
234
* @param el - Tabs container element
235
* @param options - Configuration options
236
*/
237
class Tabs {
238
constructor(el: Element, options?: TabsOptions);
239
240
static init(els: Element | NodeList, options?: TabsOptions): Tabs | Tabs[];
241
static getInstance(el: Element): Tabs;
242
static get defaults(): TabsOptions;
243
244
/** Select tab by ID */
245
select(tabId: string): void;
246
247
/** Update tab indicator position */
248
updateTabIndicator(): void;
249
250
destroy(): void;
251
}
252
253
interface TabsOptions {
254
/** Tab change animation duration */
255
duration?: number; // default: 300
256
257
/** Callback when tab is shown */
258
onShow?: (tab: Element) => void;
259
260
/** Enable swipeable tabs */
261
swipeable?: boolean; // default: false
262
263
/** Responsive threshold for tab behavior */
264
responsiveThreshold?: number; // default: Infinity
265
}
266
```
267
268
**Usage Examples:**
269
270
```html
271
<!-- Tabs structure -->
272
<div class="row">
273
<div class="col s12">
274
<ul class="tabs">
275
<li class="tab col s3"><a href="#test1">Test 1</a></li>
276
<li class="tab col s3"><a class="active" href="#test2">Test 2</a></li>
277
<li class="tab col s3"><a href="#test3">Test 3</a></li>
278
</ul>
279
</div>
280
<div id="test1" class="col s12">Test 1 content</div>
281
<div id="test2" class="col s12">Test 2 content</div>
282
<div id="test3" class="col s12">Test 3 content</div>
283
</div>
284
```
285
286
```javascript
287
// Initialize tabs
288
const elems = document.querySelectorAll('.tabs');
289
const instances = M.Tabs.init(elems, {
290
swipeable: true,
291
onShow: (tab) => console.log('Tab shown:', tab.id)
292
});
293
294
// Programmatic tab selection
295
const instance = M.Tabs.getInstance(document.querySelector('.tabs'));
296
instance.select('test2');
297
```
298
299
### Collapsible
300
301
Expandable/accordion component for organizing content in collapsible sections.
302
303
```javascript { .api }
304
/**
305
* Collapsible/accordion component
306
* @param el - Collapsible container element
307
* @param options - Configuration options
308
*/
309
class Collapsible {
310
constructor(el: Element, options?: CollapsibleOptions);
311
312
static init(els: Element | NodeList, options?: CollapsibleOptions): Collapsible | Collapsible[];
313
static getInstance(el: Element): Collapsible;
314
static get defaults(): CollapsibleOptions;
315
316
/** Open collapsible section by index */
317
open(index: number): void;
318
319
/** Close collapsible section by index */
320
close(index: number): void;
321
322
destroy(): void;
323
}
324
325
interface CollapsibleOptions {
326
/** Accordion mode (only one section open) vs expandable (multiple open) */
327
accordion?: boolean; // default: true
328
329
/** Callback before section opens */
330
onOpenStart?: (section: Element) => void;
331
332
/** Callback after section opens */
333
onOpenEnd?: (section: Element) => void;
334
335
/** Callback before section closes */
336
onCloseStart?: (section: Element) => void;
337
338
/** Callback after section closes */
339
onCloseEnd?: (section: Element) => void;
340
341
/** Enter animation duration */
342
inDuration?: number; // default: 300
343
344
/** Exit animation duration */
345
outDuration?: number; // default: 300
346
}
347
```
348
349
**Usage Examples:**
350
351
```html
352
<!-- Collapsible structure -->
353
<ul class="collapsible">
354
<li>
355
<div class="collapsible-header"><i class="material-icons">filter_drama</i>First</div>
356
<div class="collapsible-body"><span>Lorem ipsum dolor sit amet.</span></div>
357
</li>
358
<li class="active">
359
<div class="collapsible-header"><i class="material-icons">place</i>Second</div>
360
<div class="collapsible-body"><span>Lorem ipsum dolor sit amet.</span></div>
361
</li>
362
</ul>
363
```
364
365
```javascript
366
// Initialize collapsible
367
const elems = document.querySelectorAll('.collapsible');
368
const instances = M.Collapsible.init(elems, {
369
accordion: false // Allow multiple sections open
370
});
371
```
372
373
### Toast
374
375
Notification toast component for displaying temporary messages to users.
376
377
```javascript { .api }
378
/**
379
* Toast notification component
380
* Note: Toast does not extend Component base class
381
* @param options - Toast configuration
382
*/
383
class Toast {
384
constructor(options: ToastOptions);
385
386
/** Dismiss all active toasts */
387
static dismissAll(): void;
388
389
/** Dismiss this toast */
390
dismiss(): void;
391
}
392
393
interface ToastOptions {
394
/** Toast message HTML content */
395
html: string;
396
397
/** Display duration in milliseconds */
398
displayLength?: number; // default: 4000
399
400
/** Enter animation duration */
401
inDuration?: number; // default: 300
402
403
/** Exit animation duration */
404
outDuration?: number; // default: 375
405
406
/** Additional CSS classes */
407
classes?: string;
408
409
/** Callback when toast is dismissed */
410
completeCallback?: () => void;
411
412
/** Percentage of drag distance to activate dismissal */
413
activationPercent?: number; // default: 0.8
414
}
415
416
// Convenience method on M object
417
declare const M: {
418
toast(options: ToastOptions | { html: string }): Toast;
419
};
420
```
421
422
**Usage Examples:**
423
424
```javascript
425
// Simple toast
426
M.toast({html: 'I am a toast!'});
427
428
// Styled toast with callback
429
M.toast({
430
html: 'Success! Data saved.',
431
classes: 'green',
432
displayLength: 2000,
433
completeCallback: () => console.log('Toast dismissed')
434
});
435
436
// Toast with action button
437
M.toast({
438
html: `<span>Message sent</span><button class="btn-flat toast-action">Undo</button>`,
439
classes: 'rounded'
440
});
441
```
442
443
### Tooltip
444
445
Tooltip component for displaying contextual information on hover or focus.
446
447
```javascript { .api }
448
/**
449
* Tooltip component
450
* @param el - Element that triggers tooltip
451
* @param options - Configuration options
452
*/
453
class Tooltip {
454
constructor(el: Element, options?: TooltipOptions);
455
456
static init(els: Element | NodeList, options?: TooltipOptions): Tooltip | Tooltip[];
457
static getInstance(el: Element): Tooltip;
458
static get defaults(): TooltipOptions;
459
460
/** Open tooltip manually */
461
open(isManual?: boolean): void;
462
463
/** Close tooltip manually */
464
close(): void;
465
466
destroy(): void;
467
468
/** Current open state */
469
isOpen: boolean;
470
471
/** Tooltip element */
472
el: Element;
473
474
/** Configuration options */
475
options: TooltipOptions;
476
}
477
478
interface TooltipOptions {
479
/** Delay before hiding tooltip */
480
exitDelay?: number; // default: 0
481
482
/** Delay before showing tooltip */
483
enterDelay?: number; // default: 200
484
485
/** Tooltip HTML content */
486
html?: string;
487
488
/** Margin from trigger element */
489
margin?: number; // default: 5
490
491
/** Enter animation duration */
492
inDuration?: number; // default: 300
493
494
/** Exit animation duration */
495
outDuration?: number; // default: 250
496
497
/** Tooltip position relative to trigger */
498
position?: 'top' | 'right' | 'bottom' | 'left'; // default: 'bottom'
499
500
/** Movement distance during animation */
501
transitionMovement?: number; // default: 10
502
}
503
```
504
505
**Usage Examples:**
506
507
```html
508
<!-- Tooltip via data attribute -->
509
<a class="btn tooltipped" data-position="bottom" data-tooltip="I am a tooltip">Hover me!</a>
510
511
<!-- Tooltip via HTML content -->
512
<a class="btn tooltipped" data-position="top" data-html="true"
513
data-tooltip="<b>Bold</b> tooltip content">HTML Tooltip</a>
514
```
515
516
```javascript
517
// Initialize tooltips
518
const elems = document.querySelectorAll('.tooltipped');
519
const instances = M.Tooltip.init(elems, {
520
position: 'right',
521
enterDelay: 500
522
});
523
524
// Manual tooltip control
525
const tooltip = M.Tooltip.init(document.querySelector('#help-button'));
526
527
// Programmatically open/close tooltip
528
tooltip.open(true); // Pass true for manual opening
529
530
setTimeout(() => {
531
tooltip.close();
532
}, 3000);
533
534
// Check tooltip state
535
if (tooltip.isOpen) {
536
console.log('Tooltip is currently open');
537
}
538
```
539
540
### FloatingActionButton
541
542
Floating Action Button with expandable menu for primary actions.
543
544
```javascript { .api }
545
/**
546
* Floating Action Button component
547
* @param el - FAB container element
548
* @param options - Configuration options
549
*/
550
class FloatingActionButton {
551
constructor(el: Element, options?: FloatingActionButtonOptions);
552
553
static init(els: Element | NodeList, options?: FloatingActionButtonOptions): FloatingActionButton | FloatingActionButton[];
554
static getInstance(el: Element): FloatingActionButton;
555
static get defaults(): FloatingActionButtonOptions;
556
557
/** Open FAB menu */
558
open(): void;
559
560
/** Close FAB menu */
561
close(): void;
562
563
destroy(): void;
564
}
565
566
interface FloatingActionButtonOptions {
567
/** Direction of menu expansion */
568
direction?: 'top' | 'right' | 'bottom' | 'left'; // default: 'top'
569
570
/** Enable hover to open instead of click */
571
hoverEnabled?: boolean; // default: true
572
573
/** Enable toolbar transformation */
574
toolbarEnabled?: boolean; // default: false
575
}
576
```
577
578
**Usage Examples:**
579
580
```html
581
<!-- FAB structure -->
582
<div class="fixed-action-btn">
583
<a class="btn-floating btn-large red">
584
<i class="large material-icons">mode_edit</i>
585
</a>
586
<ul>
587
<li><a class="btn-floating red"><i class="material-icons">insert_chart</i></a></li>
588
<li><a class="btn-floating yellow darken-1"><i class="material-icons">format_quote</i></a></li>
589
<li><a class="btn-floating green"><i class="material-icons">publish</i></a></li>
590
<li><a class="btn-floating blue"><i class="material-icons">attach_file</i></a></li>
591
</ul>
592
</div>
593
```
594
595
```javascript
596
// Initialize FAB
597
const elems = document.querySelectorAll('.fixed-action-btn');
598
const instances = M.FloatingActionButton.init(elems, {
599
direction: 'left',
600
hoverEnabled: false
601
});
602
```
603
604
## Common Patterns
605
606
### Component Initialization
607
608
```javascript
609
// Auto-initialization (recommended for most cases)
610
document.addEventListener('DOMContentLoaded', function() {
611
M.AutoInit();
612
});
613
614
// Manual initialization with options
615
const elems = document.querySelectorAll('.component-selector');
616
const instances = M.ComponentName.init(elems, {
617
// Component-specific options
618
});
619
620
// Individual instance creation
621
const elem = document.getElementById('my-component');
622
const instance = new M.ComponentName(elem, options);
623
```
624
625
### Event Handling
626
627
```javascript
628
// Using callback options
629
const modal = M.Modal.init(elem, {
630
onOpenStart: () => console.log('Modal opening...'),
631
onOpenEnd: () => console.log('Modal opened'),
632
onCloseStart: () => console.log('Modal closing...'),
633
onCloseEnd: () => console.log('Modal closed')
634
});
635
636
// Custom event listeners
637
elem.addEventListener('click', function() {
638
const instance = M.Modal.getInstance(this);
639
if (instance.isOpen) {
640
instance.close();
641
} else {
642
instance.open();
643
}
644
});
645
```
646
647
### Pushpin
648
649
Pushpin component for creating sticky elements that change behavior based on scroll position, ideal for navigation headers, sidebars, and content that should remain visible during scrolling.
650
651
```javascript { .api }
652
/**
653
* Pushpin component for sticky positioning behavior
654
* @param el - Element to make sticky (usually with .pushpin class)
655
* @param options - Configuration options
656
*/
657
class Pushpin {
658
constructor(el: Element, options?: PushpinOptions);
659
660
/** Initialize pushpin instances */
661
static init(els: Element | NodeList, options?: PushpinOptions): Pushpin | Pushpin[];
662
663
/** Get existing pushpin instance */
664
static getInstance(el: Element): Pushpin;
665
666
/** Get default options */
667
static get defaults(): PushpinOptions;
668
669
/** Destroy pushpin instance */
670
destroy(): void;
671
672
/** Pushpin element */
673
el: Element;
674
675
/** Configuration options */
676
options: PushpinOptions;
677
678
/** Original element offset from top */
679
originalOffset: number;
680
}
681
682
interface PushpinOptions {
683
/** Top offset position for pin activation */
684
top?: number; // default: 0
685
686
/** Bottom offset position for pin deactivation */
687
bottom?: number; // default: Infinity
688
689
/** Additional offset from scroll position */
690
offset?: number; // default: 0
691
692
/** Callback fired when pin position changes */
693
onPositionChange?: (position: 'pin-top' | 'pinned' | 'pin-bottom') => void;
694
}
695
```
696
697
**Usage Examples:**
698
699
```html
700
<!-- Basic pushpin element -->
701
<div class="pushpin">
702
<h4>This content will stick</h4>
703
<p>Navigation or content that should remain visible</p>
704
</div>
705
706
<!-- Pushpin with data attributes -->
707
<nav class="pushpin" data-target="nav-demo">
708
<div class="nav-wrapper">
709
<a href="#" class="brand-logo">Logo</a>
710
</div>
711
</nav>
712
```
713
714
```javascript
715
// Initialize pushpin
716
const elems = document.querySelectorAll('.pushpin');
717
const instances = M.Pushpin.init(elems, {
718
top: 400,
719
bottom: 1000,
720
offset: 20,
721
onPositionChange: function(position) {
722
console.log('Pushpin position changed to:', position);
723
}
724
});
725
726
// Manual initialization with specific boundaries
727
const navbar = document.querySelector('#sticky-nav');
728
M.Pushpin.init(navbar, {
729
top: navbar.offsetTop,
730
bottom: document.body.scrollHeight - navbar.offsetHeight,
731
offset: 0
732
});
733
```
734
735
**CSS Classes Applied:**
736
737
- `.pin-top` - Applied when scroll position is above the top threshold
738
- `.pinned` - Applied when element is actively pinned (between top and bottom)
739
- `.pin-bottom` - Applied when scroll position is below the bottom threshold
740
741
### TapTarget
742
743
TapTarget component for feature discovery and highlighting, creating animated overlays that guide users to specific elements or features in your application.
744
745
```javascript { .api }
746
/**
747
* TapTarget component for feature discovery and user onboarding
748
* @param el - TapTarget element (usually with .tap-target class)
749
* @param options - Configuration options
750
*/
751
class TapTarget {
752
constructor(el: Element, options?: TapTargetOptions);
753
754
/** Initialize tap target instances */
755
static init(els: Element | NodeList, options?: TapTargetOptions): TapTarget | TapTarget[];
756
757
/** Get existing tap target instance */
758
static getInstance(el: Element): TapTarget;
759
760
/** Get default options */
761
static get defaults(): TapTargetOptions;
762
763
/** Open the tap target */
764
open(): void;
765
766
/** Close the tap target */
767
close(): void;
768
769
/** Destroy tap target instance */
770
destroy(): void;
771
772
/** Current open state */
773
isOpen: boolean;
774
775
/** TapTarget element */
776
el: Element;
777
778
/** Configuration options */
779
options: TapTargetOptions;
780
781
/** Target element wrapper */
782
wrapper: Element;
783
784
/** Wave animation element */
785
waveEl: Element;
786
787
/** Origin element (the element being highlighted) */
788
originEl: Element;
789
790
/** Content container element */
791
contentEl: Element;
792
}
793
794
interface TapTargetOptions {
795
/** Callback fired when tap target opens */
796
onOpen?: (origin: Element) => void;
797
798
/** Callback fired when tap target closes */
799
onClose?: (origin: Element) => void;
800
}
801
```
802
803
**Usage Examples:**
804
805
```html
806
<!-- Target element to highlight -->
807
<a id="menu-button" class="btn-floating btn-large red">
808
<i class="material-icons">menu</i>
809
</a>
810
811
<!-- Tap target overlay -->
812
<div class="tap-target" data-target="menu-button">
813
<div class="tap-target-content">
814
<h5>Menu Button</h5>
815
<p>Click this button to open the navigation menu and access all features.</p>
816
</div>
817
</div>
818
819
<!-- Multiple tap targets for onboarding flow -->
820
<div class="tap-target" data-target="search-input">
821
<div class="tap-target-content">
822
<h5>Search</h5>
823
<p>Use this search bar to find what you're looking for quickly.</p>
824
</div>
825
</div>
826
```
827
828
```javascript
829
// Initialize tap targets
830
const elems = document.querySelectorAll('.tap-target');
831
const instances = M.TapTarget.init(elems, {
832
onOpen: function(origin) {
833
console.log('Tap target opened for:', origin);
834
},
835
onClose: function(origin) {
836
console.log('Tap target closed for:', origin);
837
}
838
});
839
840
// Manual control for onboarding flow
841
const menuTarget = M.TapTarget.getInstance(document.querySelector('[data-target="menu-button"]'));
842
const searchTarget = M.TapTarget.getInstance(document.querySelector('[data-target="search-input"]'));
843
844
// Start onboarding sequence
845
function startOnboarding() {
846
menuTarget.open();
847
848
// After user interacts, show next step
849
setTimeout(() => {
850
menuTarget.close();
851
searchTarget.open();
852
}, 3000);
853
}
854
855
// Programmatically open/close
856
const tapTarget = document.querySelector('.tap-target');
857
const instance = M.TapTarget.init(tapTarget);
858
859
// Open tap target
860
instance.open();
861
862
// Close after delay
863
setTimeout(() => instance.close(), 5000);
864
```
865
866
**Features:**
867
868
- Highlights specific UI elements with animated overlay
869
- Automatically positions content based on target element location
870
- Responsive positioning that adapts to screen size and target location
871
- Wave animation effect for drawing attention
872
- Support for rich HTML content in explanations
873
- Perfect for user onboarding and feature discovery flows
874
875
### Instance Management
876
877
```javascript
878
// Get existing instance
879
const instance = M.ComponentName.getInstance(element);
880
881
// Check instance state
882
if (instance && instance.isOpen) {
883
instance.close();
884
}
885
886
// Cleanup when component no longer needed
887
instance.destroy();
888
889
// Reinitialize after DOM changes
890
M.ComponentName.init(newElements, options);
891
```