JavaScript data visualization library for creating interactive charts, graphs, and scientific visualizations
81
Built-in UI components for legends, colorbars, toolbars, and interactive controls that enhance user interaction with plots.
Interactive legend showing trace names with click behavior for toggling visibility.
interface LegendConfig {
// Visibility and positioning
x?: number; // 0-1, horizontal position
y?: number; // 0-1, vertical position
xanchor?: 'auto' | 'left' | 'center' | 'right';
yanchor?: 'auto' | 'top' | 'middle' | 'bottom';
orientation?: 'v' | 'h';
// Appearance
bgcolor?: string;
bordercolor?: string;
borderwidth?: number;
font?: FontConfig;
// Item behavior
itemclick?: 'toggle' | 'toggleothers' | false;
itemdoubleclick?: 'toggle' | 'toggleothers' | false;
itemsizing?: 'trace' | 'constant';
itemwidth?: number;
// Grouping
tracegroupgap?: number;
traceorder?: 'normal' | 'reversed' | 'grouped' | 'reversed+grouped';
// Interaction
uirevision?: any;
valign?: 'top' | 'middle' | 'bottom';
}Usage Examples:
// Basic legend configuration
const layout = {
showlegend: true,
legend: {
x: 1,
y: 1,
xanchor: 'right',
yanchor: 'top',
bgcolor: 'rgba(255,255,255,0.8)',
bordercolor: 'rgba(0,0,0,0.2)',
borderwidth: 1
}
};
// Horizontal legend at bottom
const horizontalLegend = {
legend: {
orientation: 'h',
x: 0.5,
y: -0.1,
xanchor: 'center',
yanchor: 'top'
}
};
// Custom click behavior
const customLegend = {
legend: {
itemclick: 'toggleothers', // Click to show only this trace
itemdoubleclick: 'toggle', // Double-click to toggle
font: { size: 14, color: 'blue' }
}
};
// Grouped legend
const groupedLegend = {
legend: {
traceorder: 'grouped',
tracegroupgap: 10,
itemsizing: 'constant'
}
};Color scale display for traces that use color mapping.
interface ColorbarConfig {
// Title
title?: string | ColorbarTitleConfig;
// Positioning and size
x?: number; // 0-1, horizontal position
y?: number; // 0-1, vertical position
xanchor?: 'left' | 'center' | 'right';
yanchor?: 'bottom' | 'middle' | 'top';
xpad?: number;
ypad?: number;
len?: number; // 0-1, length
lenmode?: 'fraction' | 'pixels';
thickness?: number;
thicknessmode?: 'fraction' | 'pixels';
// Appearance
bgcolor?: string;
bordercolor?: string;
borderwidth?: number;
outlinecolor?: string;
outlinewidth?: number;
// Ticks and labels
tickmode?: 'auto' | 'linear' | 'array';
tick0?: number;
dtick?: number | string;
tickvals?: number[];
ticktext?: string[];
ticklen?: number;
tickwidth?: number;
tickcolor?: string;
tickfont?: FontConfig;
tickformat?: string;
tickformatstops?: TickFormatStop[];
ticklabelposition?: 'outside' | 'inside' | 'outside top' | 'inside top' | 'outside bottom' | 'inside bottom';
tickprefix?: string;
ticksuffix?: string;
tickangle?: number;
// Visibility
showticklabels?: boolean;
showtickprefix?: 'all' | 'first' | 'last' | 'none';
showticksuffix?: 'all' | 'first' | 'last' | 'none';
}
interface ColorbarTitleConfig {
text?: string;
font?: FontConfig;
side?: 'right' | 'top' | 'bottom';
}Usage Examples:
// Basic colorbar on heatmap
const heatmapTrace = {
z: [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
type: 'heatmap',
colorbar: {
title: 'Temperature',
titleside: 'right',
thickness: 20,
len: 0.8,
x: 1.02,
tickmode: 'linear',
tick0: 0,
dtick: 1
}
};
// Custom positioned colorbar
const scatterTrace = {
x: [1, 2, 3, 4],
y: [10, 11, 12, 13],
mode: 'markers',
marker: {
color: [1, 2, 3, 4],
colorscale: 'Viridis',
showscale: true,
colorbar: {
title: {
text: 'Color Scale',
font: { size: 16 }
},
x: 1.15,
len: 0.5,
thickness: 15,
bgcolor: 'rgba(255,255,255,0.8)',
bordercolor: 'black',
borderwidth: 1
}
},
type: 'scatter'
};
// Horizontal colorbar
const horizontalColorbar = {
colorbar: {
orientation: 'h',
x: 0.5,
y: -0.2,
xanchor: 'center',
len: 0.8,
thickness: 20
}
};Interactive toolbar providing zoom, pan, selection, and export tools.
interface ModebarConfig {
// Controlled via config object, not layout
displayModeBar?: boolean | 'hover';
displaylogo?: boolean;
modeBarButtons?: ModebarButton[][];
modeBarButtonsToAdd?: ModebarButton[];
modeBarButtonsToRemove?: string[];
locale?: string;
// Style via CSS classes
// .modebar - main container
// .modebar-btn - individual buttons
// .modebar-group - button groups
}
interface ModebarButton {
name: string;
title?: string;
icon?: string | IconConfig;
click?: (gd: HTMLElement) => void;
attr?: string;
val?: any;
toggle?: boolean;
}Usage Examples:
// Basic modebar configuration
const config = {
displayModeBar: true,
displaylogo: false,
modeBarButtonsToRemove: ['pan2d', 'lasso2d']
};
// Custom modebar buttons
const customConfig = {
modeBarButtonsToAdd: [
{
name: 'myCustomButton',
title: 'Custom Action',
icon: {
width: 1000,
height: 1000,
path: 'M100 200 L900 200 L500 800 Z', // SVG path
},
click: function(gd) {
alert('Custom button clicked!');
}
}
]
};
// Modebar positioning and styling
const styledConfig = {
displayModeBar: 'hover',
displaylogo: false,
modeBarButtons: [
['zoom2d', 'pan2d'],
['zoomIn2d', 'zoomOut2d', 'autoScale2d', 'resetScale2d'],
['downloadImage']
]
};
// Hide modebar completely
const noModebarConfig = {
displayModeBar: false
};Text labels and arrows overlaid on the plot.
interface AnnotationConfig {
// Text content
text?: string;
textangle?: number;
font?: FontConfig;
// Positioning
x?: number | string | Date;
y?: number | string | Date;
xref?: 'paper' | 'x' | 'x2' | 'x3' | string;
yref?: 'paper' | 'y' | 'y2' | 'y3' | string;
xanchor?: 'auto' | 'left' | 'center' | 'right';
yanchor?: 'auto' | 'top' | 'middle' | 'bottom';
xshift?: number;
yshift?: number;
// Arrow
showarrow?: boolean;
arrowhead?: number; // 0-8
arrowsize?: number;
arrowwidth?: number;
arrowcolor?: string;
ax?: number; // Arrow x position (relative to annotation)
ay?: number; // Arrow y position (relative to annotation)
axref?: 'pixel';
ayref?: 'pixel';
standoff?: number;
startstandoff?: number;
// Appearance
bgcolor?: string;
bordercolor?: string;
borderwidth?: number;
borderpad?: number;
opacity?: number;
// Interaction
clicktoshow?: 'onoff' | 'onout' | false;
captureevents?: boolean;
visible?: boolean;
// Hover
hovertext?: string;
hoverlabel?: HoverLabelConfig;
}Usage Examples:
// Simple text annotation
const layout = {
annotations: [
{
x: 2,
y: 5,
text: 'Important Point',
showarrow: true,
arrowhead: 2,
ax: 0,
ay: -30
}
]
};
// Multiple annotations with different styles
const multiAnnotations = {
annotations: [
{
text: 'Maximum Value',
x: 3,
y: 15,
xref: 'x',
yref: 'y',
showarrow: true,
arrowhead: 4,
arrowsize: 1,
arrowcolor: 'red',
ax: 0,
ay: -40,
bgcolor: 'yellow',
bordercolor: 'black',
borderwidth: 2
},
{
text: 'Data Source: Survey 2023',
x: 0.5,
y: 0.02,
xref: 'paper',
yref: 'paper',
xanchor: 'center',
showarrow: false,
font: { size: 10, color: 'gray' }
}
]
};
// Interactive annotations
const interactiveAnnotations = {
annotations: [
{
text: 'Click to toggle',
x: 1,
y: 1,
xref: 'paper',
yref: 'paper',
clicktoshow: 'onoff',
captureevents: true,
bgcolor: 'lightblue',
bordercolor: 'blue'
}
]
};Geometric shapes overlaid on the plot area.
interface ShapeConfig {
// Shape type and coordinates
type: 'line' | 'rect' | 'circle' | 'path';
x0?: number | string | Date;
y0?: number | string | Date;
x1?: number | string | Date;
y1?: number | string | Date;
xref?: 'paper' | 'x' | 'x2' | string;
yref?: 'paper' | 'y' | 'y2' | string;
// Path shape
path?: string; // SVG path string
// Appearance
line?: {
color?: string;
width?: number;
dash?: 'solid' | 'dot' | 'dash' | 'longdash' | 'dashdot' | 'longdashdot';
};
fillcolor?: string;
opacity?: number;
// Layering
layer?: 'below' | 'above';
// Visibility and interaction
visible?: boolean;
editable?: boolean;
}Usage Examples:
// Highlight regions with rectangles
const layout = {
shapes: [
{
type: 'rect',
x0: 1,
y0: 0,
x1: 3,
y1: 10,
fillcolor: 'rgba(255, 0, 0, 0.2)',
line: { color: 'red', width: 2 },
layer: 'below'
}
]
};
// Reference lines
const referenceLines = {
shapes: [
{
type: 'line',
x0: 0,
y0: 5,
x1: 10,
y1: 5,
xref: 'x',
yref: 'y',
line: {
color: 'red',
width: 2,
dash: 'dash'
}
}
]
};
// Circle highlighting
const circleHighlight = {
shapes: [
{
type: 'circle',
x0: 1,
y0: 1,
x1: 3,
y1: 3,
fillcolor: 'rgba(0, 255, 0, 0.2)',
line: { color: 'green' }
}
]
};
// Custom path shape
const customPath = {
shapes: [
{
type: 'path',
path: 'M 1,1 L 2,2 L 3,1 Z',
fillcolor: 'blue',
line: { color: 'darkblue', width: 2 }
}
]
};Dropdown menus and buttons for interactive plot updates.
interface UpdateMenuConfig {
// Button configuration
buttons?: UpdateMenuButton[];
direction?: 'left' | 'right' | 'up' | 'down';
type?: 'dropdown' | 'buttons';
// Positioning
x?: number; // 0-1
y?: number; // 0-1
xanchor?: 'auto' | 'left' | 'center' | 'right';
yanchor?: 'auto' | 'top' | 'middle' | 'bottom';
pad?: PaddingConfig;
// Appearance
bgcolor?: string;
bordercolor?: string;
borderwidth?: number;
font?: FontConfig;
// Behavior
active?: number; // Index of active button
showactive?: boolean;
visible?: boolean;
}
interface UpdateMenuButton {
// Action
method?: 'restyle' | 'relayout' | 'animate' | 'update' | 'skip';
args?: any[];
args2?: any[]; // For toggle behavior
// Display
label?: string;
visible?: boolean;
// Execution
execute?: boolean;
}Usage Examples:
// Dropdown menu for trace visibility
const layout = {
updatemenus: [
{
type: 'dropdown',
direction: 'down',
x: 1.15,
y: 1,
buttons: [
{
label: 'All Traces',
method: 'restyle',
args: ['visible', [true, true, true]]
},
{
label: 'Trace 1 Only',
method: 'restyle',
args: ['visible', [true, false, false]]
},
{
label: 'Trace 2 Only',
method: 'restyle',
args: ['visible', [false, true, false]]
}
]
}
]
};
// Button group for chart type switching
const chartTypeButtons = {
updatemenus: [
{
type: 'buttons',
direction: 'left',
x: 0.5,
y: 1.15,
xanchor: 'center',
buttons: [
{
label: 'Line',
method: 'restyle',
args: [{'type': 'scatter', 'mode': 'lines'}]
},
{
label: 'Markers',
method: 'restyle',
args: [{'type': 'scatter', 'mode': 'markers'}]
},
{
label: 'Bar',
method: 'restyle',
args: [{'type': 'bar'}]
}
]
}
]
};
// Layout update buttons
const layoutButtons = {
updatemenus: [
{
type: 'buttons',
buttons: [
{
label: 'Linear Y',
method: 'relayout',
args: [{'yaxis.type': 'linear'}]
},
{
label: 'Log Y',
method: 'relayout',
args: [{'yaxis.type': 'log'}]
}
]
}
]
};Interactive sliders for parameter control and animation.
interface SliderConfig {
// Steps
steps?: SliderStep[];
active?: number; // Index of active step
// Positioning and size
x?: number; // 0-1
y?: number; // 0-1
len?: number; // 0-1
lenmode?: 'fraction' | 'pixels';
pad?: PaddingConfig;
xanchor?: 'auto' | 'left' | 'center' | 'right';
yanchor?: 'auto' | 'top' | 'middle' | 'bottom';
// Appearance
bgcolor?: string;
bordercolor?: string;
borderwidth?: number;
tickcolor?: string;
ticklen?: number;
tickwidth?: number;
minorticklen?: number;
font?: FontConfig;
// Current value display
currentvalue?: {
font?: FontConfig;
offset?: number;
prefix?: string;
suffix?: string;
visible?: boolean;
xanchor?: 'left' | 'center' | 'right';
};
// Animation
transition?: TransitionConfig;
visible?: boolean;
}
interface SliderStep {
// Action
method?: 'animate' | 'relayout' | 'restyle' | 'update' | 'skip';
args?: any[];
// Display
label?: string;
value?: string | number;
visible?: boolean;
// Execution
execute?: boolean;
}Usage Examples:
// Animation slider
const animationLayout = {
sliders: [
{
active: 0,
currentvalue: {
prefix: 'Year: ',
visible: true,
xanchor: 'right',
font: { size: 20, color: '#666' }
},
steps: years.map((year, i) => ({
label: year.toString(),
method: 'animate',
args: [[`frame-${year}`], {
mode: 'immediate',
transition: { duration: 300 },
frame: { duration: 300, redraw: false }
}]
})),
x: 0.1,
len: 0.9,
y: 0,
pad: { t: 50, b: 10 }
}
]
};
// Parameter control slider
const parameterSlider = {
sliders: [
{
currentvalue: {
prefix: 'Threshold: ',
visible: true
},
steps: [
{
label: '0',
method: 'restyle',
args: [{'line.width': 1}]
},
{
label: '1',
method: 'restyle',
args: [{'line.width': 2}]
},
{
label: '2',
method: 'restyle',
args: [{'line.width': 3}]
}
]
}
]
};Interactive components emit events for custom behavior:
interface InteractiveEvents {
'plotly_legendclick': (eventData: { curveNumber: number; data: any }) => boolean;
'plotly_legenddoubleclick': (eventData: { curveNumber: number; data: any }) => boolean;
'plotly_sliderchange': (eventData: { slider: SliderConfig; step: SliderStep; interaction: boolean; previousActive: number }) => void;
'plotly_sliderend': (eventData: { slider: SliderConfig; step: SliderStep }) => void;
'plotly_sliderstart': (eventData: { slider: SliderConfig }) => void;
'plotly_buttonclicked': (eventData: { menu: UpdateMenuConfig; button: UpdateMenuButton; active: number }) => void;
}Usage Examples:
const chartDiv = document.getElementById('interactive-chart');
// Custom legend click behavior
chartDiv.on('plotly_legendclick', (eventData) => {
console.log('Legend clicked:', eventData.curveNumber);
// Return false to prevent default behavior
return false;
});
// Slider interaction handling
chartDiv.on('plotly_sliderchange', (eventData) => {
console.log('Slider changed to step:', eventData.step.label);
});
// Button click handling
chartDiv.on('plotly_buttonclicked', (eventData) => {
console.log('Button clicked:', eventData.button.label);
});/* Modebar styling */
.modebar {
background: rgba(255, 255, 255, 0.7) !important;
border-radius: 4px;
}
.modebar-btn {
color: #333 !important;
}
.modebar-btn:hover {
background: rgba(0, 0, 0, 0.1) !important;
}
/* Legend styling */
.legend {
cursor: pointer;
}
/* Update menu styling */
.updatemenu-header {
background: #f0f0f0;
}
.updatemenu-item {
background: white;
}
.updatemenu-item:hover {
background: #e0e0e0;
}// Mobile-friendly interactive components
const mobileLayout = {
showlegend: false, // Hide legend on small screens
annotations: [], // Minimize annotations
updatemenus: [{
type: 'buttons',
direction: 'left',
x: 0.5,
y: 1.1,
xanchor: 'center',
buttons: [] // Simplified buttons
}]
};
// Tablet configuration
const tabletLayout = {
legend: {
orientation: 'h',
x: 0.5,
y: -0.1,
xanchor: 'center'
}
};Install with Tessl CLI
npx tessl i tessl/npm-plotly-js-distdocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10