or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

animation.mdchart-types.mdcore-plotting.mddata-streaming.mddata-updates.mdexport-utilities.mdindex.mdinteractive-components.mdlayout-system.mdtrace-management.md

interactive-components.mddocs/

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

```