0
# Interactive Components
1
2
Built-in UI components for legends, colorbars, toolbars, and interactive controls that enhance user interaction with plots.
3
4
## Legend Component
5
6
Interactive legend showing trace names with click behavior for toggling visibility.
7
8
```javascript { .api }
9
interface LegendConfig {
10
// Visibility and positioning
11
x?: number; // 0-1, horizontal position
12
y?: number; // 0-1, vertical position
13
xanchor?: 'auto' | 'left' | 'center' | 'right';
14
yanchor?: 'auto' | 'top' | 'middle' | 'bottom';
15
orientation?: 'v' | 'h';
16
17
// Appearance
18
bgcolor?: string;
19
bordercolor?: string;
20
borderwidth?: number;
21
font?: FontConfig;
22
23
// Item behavior
24
itemclick?: 'toggle' | 'toggleothers' | false;
25
itemdoubleclick?: 'toggle' | 'toggleothers' | false;
26
itemsizing?: 'trace' | 'constant';
27
itemwidth?: number;
28
29
// Grouping
30
tracegroupgap?: number;
31
traceorder?: 'normal' | 'reversed' | 'grouped' | 'reversed+grouped';
32
33
// Interaction
34
uirevision?: any;
35
valign?: 'top' | 'middle' | 'bottom';
36
}
37
```
38
39
**Usage Examples:**
40
41
```javascript
42
// Basic legend configuration
43
const layout = {
44
showlegend: true,
45
legend: {
46
x: 1,
47
y: 1,
48
xanchor: 'right',
49
yanchor: 'top',
50
bgcolor: 'rgba(255,255,255,0.8)',
51
bordercolor: 'rgba(0,0,0,0.2)',
52
borderwidth: 1
53
}
54
};
55
56
// Horizontal legend at bottom
57
const horizontalLegend = {
58
legend: {
59
orientation: 'h',
60
x: 0.5,
61
y: -0.1,
62
xanchor: 'center',
63
yanchor: 'top'
64
}
65
};
66
67
// Custom click behavior
68
const customLegend = {
69
legend: {
70
itemclick: 'toggleothers', // Click to show only this trace
71
itemdoubleclick: 'toggle', // Double-click to toggle
72
font: { size: 14, color: 'blue' }
73
}
74
};
75
76
// Grouped legend
77
const groupedLegend = {
78
legend: {
79
traceorder: 'grouped',
80
tracegroupgap: 10,
81
itemsizing: 'constant'
82
}
83
};
84
```
85
86
## Colorbar Component
87
88
Color scale display for traces that use color mapping.
89
90
```javascript { .api }
91
interface ColorbarConfig {
92
// Title
93
title?: string | ColorbarTitleConfig;
94
95
// Positioning and size
96
x?: number; // 0-1, horizontal position
97
y?: number; // 0-1, vertical position
98
xanchor?: 'left' | 'center' | 'right';
99
yanchor?: 'bottom' | 'middle' | 'top';
100
xpad?: number;
101
ypad?: number;
102
len?: number; // 0-1, length
103
lenmode?: 'fraction' | 'pixels';
104
thickness?: number;
105
thicknessmode?: 'fraction' | 'pixels';
106
107
// Appearance
108
bgcolor?: string;
109
bordercolor?: string;
110
borderwidth?: number;
111
outlinecolor?: string;
112
outlinewidth?: number;
113
114
// Ticks and labels
115
tickmode?: 'auto' | 'linear' | 'array';
116
tick0?: number;
117
dtick?: number | string;
118
tickvals?: number[];
119
ticktext?: string[];
120
ticklen?: number;
121
tickwidth?: number;
122
tickcolor?: string;
123
tickfont?: FontConfig;
124
tickformat?: string;
125
tickformatstops?: TickFormatStop[];
126
ticklabelposition?: 'outside' | 'inside' | 'outside top' | 'inside top' | 'outside bottom' | 'inside bottom';
127
tickprefix?: string;
128
ticksuffix?: string;
129
tickangle?: number;
130
131
// Visibility
132
showticklabels?: boolean;
133
showtickprefix?: 'all' | 'first' | 'last' | 'none';
134
showticksuffix?: 'all' | 'first' | 'last' | 'none';
135
}
136
137
interface ColorbarTitleConfig {
138
text?: string;
139
font?: FontConfig;
140
side?: 'right' | 'top' | 'bottom';
141
}
142
```
143
144
**Usage Examples:**
145
146
```javascript
147
// Basic colorbar on heatmap
148
const heatmapTrace = {
149
z: [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
150
type: 'heatmap',
151
colorbar: {
152
title: 'Temperature',
153
titleside: 'right',
154
thickness: 20,
155
len: 0.8,
156
x: 1.02,
157
tickmode: 'linear',
158
tick0: 0,
159
dtick: 1
160
}
161
};
162
163
// Custom positioned colorbar
164
const scatterTrace = {
165
x: [1, 2, 3, 4],
166
y: [10, 11, 12, 13],
167
mode: 'markers',
168
marker: {
169
color: [1, 2, 3, 4],
170
colorscale: 'Viridis',
171
showscale: true,
172
colorbar: {
173
title: {
174
text: 'Color Scale',
175
font: { size: 16 }
176
},
177
x: 1.15,
178
len: 0.5,
179
thickness: 15,
180
bgcolor: 'rgba(255,255,255,0.8)',
181
bordercolor: 'black',
182
borderwidth: 1
183
}
184
},
185
type: 'scatter'
186
};
187
188
// Horizontal colorbar
189
const horizontalColorbar = {
190
colorbar: {
191
orientation: 'h',
192
x: 0.5,
193
y: -0.2,
194
xanchor: 'center',
195
len: 0.8,
196
thickness: 20
197
}
198
};
199
```
200
201
## Modebar (Toolbar)
202
203
Interactive toolbar providing zoom, pan, selection, and export tools.
204
205
```javascript { .api }
206
interface ModebarConfig {
207
// Controlled via config object, not layout
208
displayModeBar?: boolean | 'hover';
209
displaylogo?: boolean;
210
modeBarButtons?: ModebarButton[][];
211
modeBarButtonsToAdd?: ModebarButton[];
212
modeBarButtonsToRemove?: string[];
213
locale?: string;
214
215
// Style via CSS classes
216
// .modebar - main container
217
// .modebar-btn - individual buttons
218
// .modebar-group - button groups
219
}
220
221
interface ModebarButton {
222
name: string;
223
title?: string;
224
icon?: string | IconConfig;
225
click?: (gd: HTMLElement) => void;
226
attr?: string;
227
val?: any;
228
toggle?: boolean;
229
}
230
```
231
232
**Usage Examples:**
233
234
```javascript
235
// Basic modebar configuration
236
const config = {
237
displayModeBar: true,
238
displaylogo: false,
239
modeBarButtonsToRemove: ['pan2d', 'lasso2d']
240
};
241
242
// Custom modebar buttons
243
const customConfig = {
244
modeBarButtonsToAdd: [
245
{
246
name: 'myCustomButton',
247
title: 'Custom Action',
248
icon: {
249
width: 1000,
250
height: 1000,
251
path: 'M100 200 L900 200 L500 800 Z', // SVG path
252
},
253
click: function(gd) {
254
alert('Custom button clicked!');
255
}
256
}
257
]
258
};
259
260
// Modebar positioning and styling
261
const styledConfig = {
262
displayModeBar: 'hover',
263
displaylogo: false,
264
modeBarButtons: [
265
['zoom2d', 'pan2d'],
266
['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetScale2d'],
267
['downloadImage']
268
]
269
};
270
271
// Hide modebar completely
272
const noModebarConfig = {
273
displayModeBar: false
274
};
275
```
276
277
## Annotations
278
279
Text labels and arrows overlaid on the plot.
280
281
```javascript { .api }
282
interface AnnotationConfig {
283
// Text content
284
text?: string;
285
textangle?: number;
286
font?: FontConfig;
287
288
// Positioning
289
x?: number | string | Date;
290
y?: number | string | Date;
291
xref?: 'paper' | 'x' | 'x2' | 'x3' | string;
292
yref?: 'paper' | 'y' | 'y2' | 'y3' | string;
293
xanchor?: 'auto' | 'left' | 'center' | 'right';
294
yanchor?: 'auto' | 'top' | 'middle' | 'bottom';
295
xshift?: number;
296
yshift?: number;
297
298
// Arrow
299
showarrow?: boolean;
300
arrowhead?: number; // 0-8
301
arrowsize?: number;
302
arrowwidth?: number;
303
arrowcolor?: string;
304
ax?: number; // Arrow x position (relative to annotation)
305
ay?: number; // Arrow y position (relative to annotation)
306
axref?: 'pixel';
307
ayref?: 'pixel';
308
standoff?: number;
309
startstandoff?: number;
310
311
// Appearance
312
bgcolor?: string;
313
bordercolor?: string;
314
borderwidth?: number;
315
borderpad?: number;
316
opacity?: number;
317
318
// Interaction
319
clicktoshow?: 'onoff' | 'onout' | false;
320
captureevents?: boolean;
321
visible?: boolean;
322
323
// Hover
324
hovertext?: string;
325
hoverlabel?: HoverLabelConfig;
326
}
327
```
328
329
**Usage Examples:**
330
331
```javascript
332
// Simple text annotation
333
const layout = {
334
annotations: [
335
{
336
x: 2,
337
y: 5,
338
text: 'Important Point',
339
showarrow: true,
340
arrowhead: 2,
341
ax: 0,
342
ay: -30
343
}
344
]
345
};
346
347
// Multiple annotations with different styles
348
const multiAnnotations = {
349
annotations: [
350
{
351
text: 'Maximum Value',
352
x: 3,
353
y: 15,
354
xref: 'x',
355
yref: 'y',
356
showarrow: true,
357
arrowhead: 4,
358
arrowsize: 1,
359
arrowcolor: 'red',
360
ax: 0,
361
ay: -40,
362
bgcolor: 'yellow',
363
bordercolor: 'black',
364
borderwidth: 2
365
},
366
{
367
text: 'Data Source: Survey 2023',
368
x: 0.5,
369
y: 0.02,
370
xref: 'paper',
371
yref: 'paper',
372
xanchor: 'center',
373
showarrow: false,
374
font: { size: 10, color: 'gray' }
375
}
376
]
377
};
378
379
// Interactive annotations
380
const interactiveAnnotations = {
381
annotations: [
382
{
383
text: 'Click to toggle',
384
x: 1,
385
y: 1,
386
xref: 'paper',
387
yref: 'paper',
388
clicktoshow: 'onoff',
389
captureevents: true,
390
bgcolor: 'lightblue',
391
bordercolor: 'blue'
392
}
393
]
394
};
395
```
396
397
## Shapes
398
399
Geometric shapes overlaid on the plot area.
400
401
```javascript { .api }
402
interface ShapeConfig {
403
// Shape type and coordinates
404
type: 'line' | 'rect' | 'circle' | 'path';
405
x0?: number | string | Date;
406
y0?: number | string | Date;
407
x1?: number | string | Date;
408
y1?: number | string | Date;
409
xref?: 'paper' | 'x' | 'x2' | string;
410
yref?: 'paper' | 'y' | 'y2' | string;
411
412
// Path shape
413
path?: string; // SVG path string
414
415
// Appearance
416
line?: {
417
color?: string;
418
width?: number;
419
dash?: 'solid' | 'dot' | 'dash' | 'longdash' | 'dashdot' | 'longdashdot';
420
};
421
fillcolor?: string;
422
opacity?: number;
423
424
// Layering
425
layer?: 'below' | 'above';
426
427
// Visibility and interaction
428
visible?: boolean;
429
editable?: boolean;
430
}
431
```
432
433
**Usage Examples:**
434
435
```javascript
436
// Highlight regions with rectangles
437
const layout = {
438
shapes: [
439
{
440
type: 'rect',
441
x0: 1,
442
y0: 0,
443
x1: 3,
444
y1: 10,
445
fillcolor: 'rgba(255, 0, 0, 0.2)',
446
line: { color: 'red', width: 2 },
447
layer: 'below'
448
}
449
]
450
};
451
452
// Reference lines
453
const referenceLines = {
454
shapes: [
455
{
456
type: 'line',
457
x0: 0,
458
y0: 5,
459
x1: 10,
460
y1: 5,
461
xref: 'x',
462
yref: 'y',
463
line: {
464
color: 'red',
465
width: 2,
466
dash: 'dash'
467
}
468
}
469
]
470
};
471
472
// Circle highlighting
473
const circleHighlight = {
474
shapes: [
475
{
476
type: 'circle',
477
x0: 1,
478
y0: 1,
479
x1: 3,
480
y1: 3,
481
fillcolor: 'rgba(0, 255, 0, 0.2)',
482
line: { color: 'green' }
483
}
484
]
485
};
486
487
// Custom path shape
488
const customPath = {
489
shapes: [
490
{
491
type: 'path',
492
path: 'M 1,1 L 2,2 L 3,1 Z',
493
fillcolor: 'blue',
494
line: { color: 'darkblue', width: 2 }
495
}
496
]
497
};
498
```
499
500
## Update Menus
501
502
Dropdown menus and buttons for interactive plot updates.
503
504
```javascript { .api }
505
interface UpdateMenuConfig {
506
// Button configuration
507
buttons?: UpdateMenuButton[];
508
direction?: 'left' | 'right' | 'up' | 'down';
509
type?: 'dropdown' | 'buttons';
510
511
// Positioning
512
x?: number; // 0-1
513
y?: number; // 0-1
514
xanchor?: 'auto' | 'left' | 'center' | 'right';
515
yanchor?: 'auto' | 'top' | 'middle' | 'bottom';
516
pad?: PaddingConfig;
517
518
// Appearance
519
bgcolor?: string;
520
bordercolor?: string;
521
borderwidth?: number;
522
font?: FontConfig;
523
524
// Behavior
525
active?: number; // Index of active button
526
showactive?: boolean;
527
visible?: boolean;
528
}
529
530
interface UpdateMenuButton {
531
// Action
532
method?: 'restyle' | 'relayout' | 'animate' | 'update' | 'skip';
533
args?: any[];
534
args2?: any[]; // For toggle behavior
535
536
// Display
537
label?: string;
538
visible?: boolean;
539
540
// Execution
541
execute?: boolean;
542
}
543
```
544
545
**Usage Examples:**
546
547
```javascript
548
// Dropdown menu for trace visibility
549
const layout = {
550
updatemenus: [
551
{
552
type: 'dropdown',
553
direction: 'down',
554
x: 1.15,
555
y: 1,
556
buttons: [
557
{
558
label: 'All Traces',
559
method: 'restyle',
560
args: ['visible', [true, true, true]]
561
},
562
{
563
label: 'Trace 1 Only',
564
method: 'restyle',
565
args: ['visible', [true, false, false]]
566
},
567
{
568
label: 'Trace 2 Only',
569
method: 'restyle',
570
args: ['visible', [false, true, false]]
571
}
572
]
573
}
574
]
575
};
576
577
// Button group for chart type switching
578
const chartTypeButtons = {
579
updatemenus: [
580
{
581
type: 'buttons',
582
direction: 'left',
583
x: 0.5,
584
y: 1.15,
585
xanchor: 'center',
586
buttons: [
587
{
588
label: 'Line',
589
method: 'restyle',
590
args: [{'type': 'scatter', 'mode': 'lines'}]
591
},
592
{
593
label: 'Markers',
594
method: 'restyle',
595
args: [{'type': 'scatter', 'mode': 'markers'}]
596
},
597
{
598
label: 'Bar',
599
method: 'restyle',
600
args: [{'type': 'bar'}]
601
}
602
]
603
}
604
]
605
};
606
607
// Layout update buttons
608
const layoutButtons = {
609
updatemenus: [
610
{
611
type: 'buttons',
612
buttons: [
613
{
614
label: 'Linear Y',
615
method: 'relayout',
616
args: [{'yaxis.type': 'linear'}]
617
},
618
{
619
label: 'Log Y',
620
method: 'relayout',
621
args: [{'yaxis.type': 'log'}]
622
}
623
]
624
}
625
]
626
};
627
```
628
629
## Sliders
630
631
Interactive sliders for parameter control and animation.
632
633
```javascript { .api }
634
interface SliderConfig {
635
// Steps
636
steps?: SliderStep[];
637
active?: number; // Index of active step
638
639
// Positioning and size
640
x?: number; // 0-1
641
y?: number; // 0-1
642
len?: number; // 0-1
643
lenmode?: 'fraction' | 'pixels';
644
pad?: PaddingConfig;
645
xanchor?: 'auto' | 'left' | 'center' | 'right';
646
yanchor?: 'auto' | 'top' | 'middle' | 'bottom';
647
648
// Appearance
649
bgcolor?: string;
650
bordercolor?: string;
651
borderwidth?: number;
652
tickcolor?: string;
653
ticklen?: number;
654
tickwidth?: number;
655
minorticklen?: number;
656
font?: FontConfig;
657
658
// Current value display
659
currentvalue?: {
660
font?: FontConfig;
661
offset?: number;
662
prefix?: string;
663
suffix?: string;
664
visible?: boolean;
665
xanchor?: 'left' | 'center' | 'right';
666
};
667
668
// Animation
669
transition?: TransitionConfig;
670
visible?: boolean;
671
}
672
673
interface SliderStep {
674
// Action
675
method?: 'animate' | 'relayout' | 'restyle' | 'update' | 'skip';
676
args?: any[];
677
678
// Display
679
label?: string;
680
value?: string | number;
681
visible?: boolean;
682
683
// Execution
684
execute?: boolean;
685
}
686
```
687
688
**Usage Examples:**
689
690
```javascript
691
// Animation slider
692
const animationLayout = {
693
sliders: [
694
{
695
active: 0,
696
currentvalue: {
697
prefix: 'Year: ',
698
visible: true,
699
xanchor: 'right',
700
font: { size: 20, color: '#666' }
701
},
702
steps: years.map((year, i) => ({
703
label: year.toString(),
704
method: 'animate',
705
args: [[`frame-${year}`], {
706
mode: 'immediate',
707
transition: { duration: 300 },
708
frame: { duration: 300, redraw: false }
709
}]
710
})),
711
x: 0.1,
712
len: 0.9,
713
y: 0,
714
pad: { t: 50, b: 10 }
715
}
716
]
717
};
718
719
// Parameter control slider
720
const parameterSlider = {
721
sliders: [
722
{
723
currentvalue: {
724
prefix: 'Threshold: ',
725
visible: true
726
},
727
steps: [
728
{
729
label: '0',
730
method: 'restyle',
731
args: [{'line.width': 1}]
732
},
733
{
734
label: '1',
735
method: 'restyle',
736
args: [{'line.width': 2}]
737
},
738
{
739
label: '2',
740
method: 'restyle',
741
args: [{'line.width': 3}]
742
}
743
]
744
}
745
]
746
};
747
```
748
749
## Event Handling
750
751
Interactive components emit events for custom behavior:
752
753
```javascript { .api }
754
interface InteractiveEvents {
755
'plotly_legendclick': (eventData: { curveNumber: number; data: any }) => boolean;
756
'plotly_legenddoubleclick': (eventData: { curveNumber: number; data: any }) => boolean;
757
'plotly_sliderchange': (eventData: { slider: SliderConfig; step: SliderStep; interaction: boolean; previousActive: number }) => void;
758
'plotly_sliderend': (eventData: { slider: SliderConfig; step: SliderStep }) => void;
759
'plotly_sliderstart': (eventData: { slider: SliderConfig }) => void;
760
'plotly_buttonclicked': (eventData: { menu: UpdateMenuConfig; button: UpdateMenuButton; active: number }) => void;
761
}
762
```
763
764
**Usage Examples:**
765
766
```javascript
767
const chartDiv = document.getElementById('interactive-chart');
768
769
// Custom legend click behavior
770
chartDiv.on('plotly_legendclick', (eventData) => {
771
console.log('Legend clicked:', eventData.curveNumber);
772
// Return false to prevent default behavior
773
return false;
774
});
775
776
// Slider interaction handling
777
chartDiv.on('plotly_sliderchange', (eventData) => {
778
console.log('Slider changed to step:', eventData.step.label);
779
});
780
781
// Button click handling
782
chartDiv.on('plotly_buttonclicked', (eventData) => {
783
console.log('Button clicked:', eventData.button.label);
784
});
785
```
786
787
## Styling and Customization
788
789
### CSS Classes for Styling
790
791
```css
792
/* Modebar styling */
793
.modebar {
794
background: rgba(255, 255, 255, 0.7) !important;
795
border-radius: 4px;
796
}
797
798
.modebar-btn {
799
color: #333 !important;
800
}
801
802
.modebar-btn:hover {
803
background: rgba(0, 0, 0, 0.1) !important;
804
}
805
806
/* Legend styling */
807
.legend {
808
cursor: pointer;
809
}
810
811
/* Update menu styling */
812
.updatemenu-header {
813
background: #f0f0f0;
814
}
815
816
.updatemenu-item {
817
background: white;
818
}
819
820
.updatemenu-item:hover {
821
background: #e0e0e0;
822
}
823
```
824
825
### Responsive Design
826
827
```javascript
828
// Mobile-friendly interactive components
829
const mobileLayout = {
830
showlegend: false, // Hide legend on small screens
831
annotations: [], // Minimize annotations
832
updatemenus: [{
833
type: 'buttons',
834
direction: 'left',
835
x: 0.5,
836
y: 1.1,
837
xanchor: 'center',
838
buttons: [] // Simplified buttons
839
}]
840
};
841
842
// Tablet configuration
843
const tabletLayout = {
844
legend: {
845
orientation: 'h',
846
x: 0.5,
847
y: -0.1,
848
xanchor: 'center'
849
}
850
};
851
```