Panels Tutorial

ProControls for p5.js — by David Stein
Panel, ModalPanel, Bevel, MessageDialog & InputDialog — step-by-step for beginners — all examples live and editable
↗ Full Docs
Welcome! This tutorial covers the panel and dialog controls in ProControls — the Panel (a scrollable container for grouping controls), the ModalPanel (an await-able dialog that blocks the canvas until the user saves or cancels), the Bevel (a decorative separator line), the MessageDialog (a modal alert with buttons), and the InputDialog (a modal prompt for collecting text from the user). Each control is explained in four steps, from a single line of code up to real-world usage patterns. Every code block is live and editable — click inside one, make a change, and the preview updates automatically.
First time here? Visit Getting Started for the HTML setup and script tags needed before running these examples in your own project.
Panel ModalPanel Bevel MessageDialog InputDialog

Panel

Container

A Panel is a movable, resizable window that groups other controls together. Think of it like a rack unit on a hardware synthesizer — you drop controls inside and they scroll as a unit if there are too many to fit. Panels can be minimized, dragged around the canvas, and resized by the user at runtime. You build the contents by calling pnl.add(control) for each control you want inside.

Step 1 Your first Panel

Create a Panel with x, y, width, height, and a label. An empty panel is just a chrome frame — but you can already drag it, minimize it with the − button, and resize it by dragging the bottom-right corner.

editable — try dragging the panel or clicking −
Step 2 Adding controls with pnl.add()

Pass any ProControls control to pnl.add() and it becomes a child of the panel. Child coordinates are relative to the panel's top-left content area, not the canvas. You can mix any control types — dials, sliders, switches, and more.

editable — try changing labels or adding more controls
Tip: Controls added to a Panel still have their own onChange callbacks — wire them up the same way you would on the canvas directly.
Step 3 Scrolling — more controls than fit

When the total content is taller than the panel, a scrollbar appears automatically and the user can scroll with the mouse wheel inside the panel. You don't need to do anything special — just add controls and let ProControls handle the overflow. Try scrolling in the preview below.

editable — scroll inside the panel with the mouse wheel
Step 4 Reading values with onRelease and .values

The Panel fires onRelease whenever the user finishes interacting with any child control. You can read pnl.values at any time — it returns an object keyed by each child control's label, with the current value. This is the easiest way to snapshot all the controls in a panel at once.

editable — interact with controls and watch the console
Tip: Read pnl.values inside your draw() loop without any callbacks if you prefer — it always reflects the current state of all child controls.

ModalPanel

Dialog

A ModalPanel is a promise-based dialog you can fill with any ProControls — sliders, switches, selectors, and more. Call await modal.show() to open it; your code pauses at that line until the user clicks Save or Cancel. While the dialog is open, a semi-transparent backdrop covers the rest of the canvas and all other control events are blocked. This makes it ideal for collecting a small set of values before proceeding with an action.

Step 1 Create the modal and add controls

Create a ModalPanel in setup() and call .add() for each control you want inside it. The controls are not shown yet — they appear only when show() is called. Give each control a name so you can read its value from the result later.

editable — click the canvas to open the modal
Note: mousePressed must be declared async so that await modal.show() works. p5.js fully supports async event handlers — the draw() loop continues running while the dialog is open.
Step 2 Reading the result

When the user clicks Save, show() resolves with an object containing each control's current value, keyed by its name. When the user clicks Cancel, it resolves with null. Always check for null before using the result.

editable — click canvas, adjust controls, then Save or Cancel
Step 3 Changing the title on each open with show(opts)

Pass options to show() to override the constructor values for that particular invocation. This is useful when the same modal serves multiple purposes — for example, an "Edit" dialog that shows the name of the item being edited in the title bar. Options accepted by show() are the same as the constructor: label, width, x, and y.

editable — click the canvas multiple times to see the counter
Step 4 Practical pattern — edit then apply

The most common ModalPanel pattern is to open it when the user triggers an "Edit" or "Configure" action, then apply the returned values to the sketch. Because draw() keeps running while the modal is open, you can show live feedback behind the backdrop — for example, an animated waveform that responds to the controls as the user adjusts them.

editable — click canvas to configure, Save to apply
Tip: Use modal.isOpen to guard against opening the modal twice. Since mousePressed fires on every click, a second click while the modal is already showing would otherwise try to open it again. The guard if (modal.isOpen) return; prevents this.

Bevel

Cosmetic

A Bevel is a decorative separator line — the visual equivalent of the engraved dividing lines you find on hardware mixers and synthesizer panels. Place one on the canvas or inside a Panel to visually group related controls. Provide y for a horizontal line or x for a vertical line. Positions can be in pixels or as a percentage of the containing area.

Step 1 Horizontal bevel with y

Set y to place a horizontal bevel line at that pixel position from the top of the canvas (or parent Panel). The line spans the full width of its container. The dials above and below the line are separate controls — the bevel just sits between them.

editable — try changing y to move the line
Step 2 Vertical bevel with x

Set x instead of y to get a vertical dividing line. Inside a Panel you can also use percentage strings like '50%' to position the bevel relative to the panel's width or height — so it stays centred even if the panel is resized.

editable — try x:'50%' inside a panel
Step 3 Three styles: thin, deep, color

The style option changes how the line is drawn. thin (default) is a subtle two-tone engraved line. deep adds a wider shadow for a more pronounced groove. color draws the line using your theme's accent colour — useful for highlighting a section boundary. Try editing style in the example below.

editable — try style:'deep' or style:'color'
Step 4 Adding a label

The label option adds text centered on the bevel line, displayed in a rounded pill badge so it sits cleanly on top of the line. Vertical bevels rotate the label text automatically. Labels are great for naming sections of a panel — like "AUX", "FX", or "INPUTS".

editable — try different label text

MessageDialog

Dialog

A MessageDialog is a modal alert box — like the "Are you sure?" dialogs you see in desktop applications. It displays a title, a message, and one or more buttons. While it is open, it blocks interaction with everything behind it. It is ideal for confirming destructive actions, displaying warnings, or presenting a brief status message.

Step 1 Your first MessageDialog

Pass a label (the dialog title), a message (the body text), and a buttons array. The dialog appears immediately. Clicking any button dismisses it.

editable — click a button to dismiss the dialog
Step 2 Customizing the message and buttons

You can use any number of button labels and any message text. Convention matches operating system dialogs: the last button is the primary action, the first is Cancel or the safer option. Keep messages short and specific — users scan dialogs quickly.

editable — try adding a third button or changing button labels
Step 3 Responding to buttons with onButton

The onButton callback fires when any button is clicked, passing the button's index and label. Use the index to decide what action to take — 0 is the first button (Cancel), the last index is the primary action. Click the buttons below and watch the console!

editable — click buttons and watch the console
Step 4 Show on demand — create when needed

A common pattern is to create the dialog only when an action is triggered, rather than at startup. For example, show a confirm dialog when the user clicks a "Clear" button. Because ProControls dialogs appear immediately on construction, just call new MessageDialog() inside your event handler and it will pop up right away.

editable — click CLEAR to trigger the confirm dialog
Tip: Only one dialog can be visible at a time. If you create a new dialog while one is already open, the new one replaces it.

InputDialog

Dialog

An InputDialog is a modal prompt — it displays a title, message, a text input field, and buttons. Use it any time you need the user to type something: renaming a preset, entering a BPM value, or providing a filename. Like MessageDialog, it blocks the rest of the canvas while open.

Step 1 Your first InputDialog

Create with a label, message, and buttons. An optional inputPlaceholder shows hint text in the empty field. The dialog appears immediately — click in the field and type something!

editable — click in the text field and type
Step 2 Pre-filling the input with inputValue

Set inputValue to pre-populate the text field with an existing value. This is useful when the user is editing something that already has a name — they see the current value and can change just what they need to.

editable — try changing the inputValue default text
Step 3 Reading the input with onSubmit and onButton

onSubmit fires when the user presses Enter or clicks the last button, passing the typed string. onButton fires for any button click and also passes the string. Use onSubmit for the primary action and onButton if you need to distinguish between buttons. Type in the field below and press Enter or click OK!

editable — type something and press Enter or click OK
Step 4 Show on demand — trigger from another control

Just like MessageDialog, the best pattern is to create the InputDialog only when an action is triggered. The example below uses a switch to simulate a "rename" button. Clicking it opens the dialog, and submitting the form logs the new name. Try it!

editable — click RENAME to open the dialog
Tip: The input field inside the dialog is a native HTML <input> element — keyboard shortcuts, copy/paste, and IME all work exactly as expected.