Perfect GUI

A nice, simple and (probably not) perfect GUI for JavaScript.

See code

Options

label (string)

Label displayed at the top of the panel.

const gui = new GUI({ label: 'Basics' });

draggable (boolean)

Determines whether the panel can be moved manually.
Default is false.

const gui = new GUI({ draggable: true });

container (string|HTMLElement)

Parent element of the panel. Can be a string selector or a DOM element.
Default is document.body.

const gui = new GUI({ container: '.container' });

position (string)

GUI instances can be positioned in any corner of the screen / container.
When multiple instances share the same position (like GUI 1 and GUI 2 in the example below), they are stacked next to each other.
Possible values are top left, top right, bottom left, bottom right.
Default is top right.

const gui = new GUI({ position: 'top left' });

width (number)

Determines the width of the panel.
Default is 290.

const gui = new GUI({ width: 200 });

closed (boolean)

Just like folders, GUI panels can be closed by default by setting the closed option to true.
Default is false.

const gui = new GUI({ closed: true });

maxHeight (number)

Determines to define the maximum height of a panel beyond which scrolling is necessary.
Default is the smallest value between the height of the window and the height of the container.

const gui = new GUI({ maxHeight: 400 });

color (string)

Can be applied to GUI panels and folders to customize the background color.

const gui = new GUI({ color: '#ff0000' });

opacity (number)

Sets the default transparency of the panel. When hovered, the panel becomes fully opaque (opacity: 1).
Default is 1.

const gui = new GUI({ opacity: 0.5 });

onUpdate (function)

Callback function, triggered each time the GUI is updated.

const gui = new GUI({ onUpdate: () => console.log('updated') });

Methods

.button( parameters )

The .button() method accepts an options object. It returns the button instance, allowing you to chain the .onClick(callback) method to handle click events.

Parameter Type Description
label string Optional.
color string Optional.
hoverColor string Optional. Default is equal to color if defined.
tooltip string|boolean Descriptive text showing up on hover. If set to true, its value will be the same as the label.
import GUI from 'perfect-gui';

const gui = new GUI();

gui.button({ label: 'Button 1' }).onClick(changeColor);

gui.button({ label: 'Button 2', color: '#bb3333', hoverColor: '#cc3333' }).onClick(changeColor);

.slider()

This method can be used in 2 different modes. In both cases, it returns the component instance, allowing you to chain the .onChange(callback) method to handle events.

1. Simple Mode

Pass an options object to create a simple slider. The current value can be retrieved by chaining .onChange(callback).

gui.slider( options ).onChange( callback )

2. Binding Mode

Pass an object, its target property name, and an optional options object to bind the slider and the property value together. Such a slider will automatically update the value of the object property. Directly updating the property would also update the slider.

gui.slider( object, property, options ).onChange( callback )

Options

Parameter Type Description
label string Defaults to the property name if one is provided.
value number Only used in Simple Mode. Defaults to the average value between min and max.
min number Default is 0.
max number Default is 1.
step number Increment by which to change the value.
Default is calculated so that there are 100 steps between min and max.
tooltip string|boolean Descriptive text showing up on hover. If set to true, its value will be the same as the label.
import GUI from 'perfect-gui';

const position = { x: 0 };
const gui = new GUI();

// Simple slider with value & callback
gui.slider({ label: 'Slider 1', value: 1 }).onChange(
    value => {
        element.style.opacity = value;
    }
);

// Object binding
gui.slider(position, 'x', { label: 'Slider 2 (object binding)', min: -30, max: 30 }).onChange(
    () => {
        element.style.transform = `translateX(${position.x}px)`;
    }
);

.toggle()

This method can be used in 2 different modes. In both cases, it returns the component instance, allowing you to chain the .onChange(callback) method to handle events.

1. Simple Mode

Pass an options object to create a simple toggle button. The current value can be retrieved by chaining .onChange(callback).

gui.toggle( options ).onChange( callback )

2. Binding Mode

Pass an object, its target property name, and an optional options object to bind the toggle and the property together. Such a toggle will automatically update the value of the object property. Directly updating the property would also update the state of the toggle.

gui.toggle( object, property, options ).onChange( callback )

Options

Parameter Type Description
label string Optional.
value boolean Only used in Simple Mode. Optional. Default is false.
tooltip string|boolean Descriptive text showing up on hover. If set to true, its value will be the same as the label.
import GUI from 'perfect-gui';

const gui = new GUI();

// Approach 1: using a callback function
gui.toggle({ label: 'Toggle', value: true }).onChange(value => {
    if ( value ) element.classList.remove('round');
    else element.classList.add('round');
});

// Approach 2: using object binding
const isRound = { state: true };
gui.toggle(isRound, 'state', { label: 'Toggle (object binding)' }).onChange(() => {
    if ( isRound.state ) element.classList.remove('round');
    else element.classList.add('round');
});

.list()

This method can be used in 2 different modes. In both cases, it returns the component instance, allowing you to chain the .onChange(callback) method to handle events.

1. Simple Mode

Pass an options object to create a simple list. The current value can be retrieved by chaining .onChange(callback).

gui.list( options ).onChange( callback )

2. Binding Mode

Pass an object, its target property name, and an optional options object to bind the list and the property together. Such a list will automatically update the value of the object property. Directly updating the property would also update the state of the list.

gui.list( object, property, options ).onChange( callback )

Options

Parameter Type Description
label string Optional.
values array Options to be displayed.
value string | number Only used in Simple Mode. Defines the default selected value in the options array. This can either be a string, which must correspond to one of the values within the options array, or a number, representing the index of the selected value in the array of options.
tooltip string|boolean Descriptive text showing up on hover. If set to true, its value will be the same as the label.
import GUI from 'perfect-gui';

const gui = new GUI();

// Approach 1: Simple mode
gui.list({
    label: 'Simple mode',
    values: ['red', 'pink', 'yellow', 'blue'],
    value: 1
}).onChange((value) => {
    element.style.backgroundColor = value;
});

// Approach 2: binding mode (strings)
const values = ['red', 'pink', 'yellow', 'blue'];
const color = { value: 'yellow' };

gui.list(color, 'value', {
    label: 'Binding mode (strings)',
    values
}).onChange((value, index) => {
    element.style.backgroundColor = value;
});

// Approach 3: binding mode (objects)
// The "label" property is only used to control what's displayed in the option list
// The intrinsic value of each item is the "value" property
const color2 = { value: '#993333' };
const objectValues = [
    { label: 'reddish', value: '#993333' },
    { label: 'pinkish', value: '#aa33aa' },
    { label: 'yellowish', value: '#999933' },
    { label: 'blueish', value: '#333399' }
];

gui.list(color2, 'value', {
    label: 'Binding mode (objects)',
    values: objectValues
}).onChange((obj, index) => {
    element.style.backgroundColor = obj.value;
});

.image( parameters )

The .image() method acts similar to a button but uses an image instead of text. It returns the component instance, allowing you to chain the .onClick(callback) method to handle click events.

Parameter Type Description
label string Optional. Default is the image file label.
path string Image file path.
selected boolean Default state of the item. Default is false.
selectionBorder boolean Defines if a border is visible around the selected element. Default is true.
width number | string A number type value specifies the width in pixels, while a string value allows for defining the width using various units of measurement, such as '50%' or '5vw'. Default is 33.333%.
height number Defines the height of the element in pixels. Default is 90.
tooltip string|boolean Descriptive text showing up on hover. If set to true, its value will be the same as the label.
import GUI from 'perfect-gui';

const gui = new GUI();

gui.image({ label: 'Image 1', path: 'path/to/image1.jpg'}).onClick(changeBackground);
gui.image({ label: 'Image 2', path: 'path/to/image2.jpg', selected: true}).onClick(changeBackground);
gui.image({ label: 'Image 3', path: 'path/to/image3.jpg'}).onClick(changeBackground);
gui.image({ label: 'Image 4', path: 'path/to/image4.jpg'}).onClick(changeBackground);
gui.image({ label: 'Image 5', path: 'path/to/image5.jpg'}).onClick(changeBackground);

function changeBackground(evt) {
    element.style.backgroundImage = `url( ${evt.path} )`;
}

.color()

This method can be used in 2 different modes. In both cases, it returns the component instance, allowing you to chain the .onChange(callback) method to handle events.

1. Simple Mode

Pass an options object to create a simple color picker. The current value can be retrieved by chaining .onChange(callback).

gui.color( options ).onChange( callback )

2. Binding Mode

Pass an object, its target property name, and an optional options object to bind the color picker and the property together. Such a color picker will automatically update the value of the object property. Directly updating the property would also update the state of the color picker.

gui.color( object, property, options ).onChange( callback )

Options

Parameter Type Description
label string Optional.
value string Hexadecimal color value.
Only used in Simple Mode. Optional. Default is #000000.
tooltip string|boolean Descriptive text showing up on hover. If set to true, its value will be the same as the label.
import GUI from 'perfect-gui';

const gui = new GUI();

// Approach 1: simple mode
gui.color({ label: 'Color (simple mode)', value: '#06ff89' }).onChange(color => {
    element.style.backgroundColor = color;
});

// Approach 2: binding mode
const color = { value: '#06ff89' };
gui.color(color, 'value', { label: 'Color (binding mode)' }).onChange(() => {
    element.style.backgroundColor = color.value;
});

.vector2( object, xProp, yProp, options )

The vector2() component uses an object binding mode. It returns the component instance, allowing you to chain the .onChange(callback) method to handle events.

gui.vector2( object, propertyX, propertyY, options ).onChange( callback )

Options

Parameter Type Description
label string Optional.
min number Optional. Minimum value for both axes.
max number Optional. Maximum value for both axes.
step number Optional. Increment by which to change the values.
tooltip string|boolean Descriptive text showing up on hover. If set to true, its value will be the same as the label.

A vector2() component will automatically update the values of the target object properties, therefore a callback isn't necessarily needed to bind data. Directly updating the object properties will also update the vector2() component.

import GUI from 'perfect-gui';
        
const position = { x: 0, y: 0 };
const gui = new GUI();

gui.vector2(position, 'x', 'y', { label: 'Position', min: -50, max: 50 }).onChange((x, y) => {
    element.style.transform = `translate(${x}px, ${-y}px)`;
});

.folder( parameters )

Parameter Type Description
label string Optional.
closed boolean Optional. Default is false.
color string Optional. Background color of the folder.
maxHeight number Optional.
import GUI from 'perfect-gui';

const gui = new GUI();

let folder_1 = gui.folder({ label: 'Folder 1' });
folder_1.button({ label: 'Random color' }).onClick(changeColor);
folder_1.slider({ label: 'Size', value: 1 }).onChange(changeScale);

let folder_2 = gui.folder({ label: 'Folder 2', color: '#993333' });
folder_2.button({ label: 'Random color' }).onClick(changeColor);

let folder_3 = gui.folder({ label: 'Folder 3', closed: true });
folder_3.button({ label: 'Random color' }).onClick(changeColor);

.tabs( parameters )

Parameter Type Description
tabs array Required. Array of tab labels.
active number Optional. Index of the initially active tab. Default is 0.

Method Description
.getTab(index) Returns the GUI instance for the tab at the specified index.
.getActiveTab() Returns the index of the currently active tab.
.getTabElement(index) Returns the DOM element for the tab at the specified index.
.setActiveTab(index) Sets the active tab to the specified index.
import GUI from 'perfect-gui';

const gui = new GUI({label: 'Tabs' });

const tabs = gui.tabs({
    tabs: ['Controls', 'Settings'],
    active: 1
});

const tab1 = tabs.getTab(0);
tab1.button({ label: 'Action Button' });
tab1.slider({ label: 'Value', value: 0.5, min: 0, max: 1 });

const tab2 = tabs.getTab(1);
tab2.toggle({ label: 'Enable Feature', value: true });
tab2.color({ label: 'Color', value: '#ff0000' });
// Tab methods
console.log('Active tab:', tabs.getActiveTab());
console.log('Tab 0 element:', tabs.getTabElement(0));

// Programmatically switch tabs
tabs.setActiveTab(0);

.toggleClose()

import GUI from 'perfect-gui';
        
const gui_1 = new GUI();

gui_1.button({ label: 'gui_2.toggleClose();' }).onClick(() => {
    gui_2.toggleClose();
});

const gui_2 = new GUI();

gui_2.button({ label: 'gui_1.toggleClose();' }).onClick(() => {
    gui_1.toggleClose();
});

.kill()

See code
const guis = [];

let gui_1 = new GUI({
    label: 'GUI 1',
});

gui_1.button({ label: 'Create GUI panel' }).onClick(() => {
    guis[guis.length] = new GUI({
        label: 'Created GUI',
        position: 'bottom left',
        width: 150,
        color: 'red'
    });
});

gui_1.button({ label: 'Kill GUI panel' }).onClick(() => {
    const index = guis.length - 1;
    if ( index >= 0 ) {
        // Removes html elements
        guis[index].kill(); 

        // Frees up memory
        guis[index] = null;

        // Removes null value from array
        guis.splice(index, 1);
    }
});