v1.13

DHGui

A modern, dependency-free GUI panel for debugging and tuning parameters in the browser. Drop in a single file, bind your settings object, and iterate in real time.

Features

  • Controllers: int, float, color, checkbox, select, button, text, image, canvas, pose2d, pose3d, angle, joystick, bezier, range, gradient
  • Nested folders with smooth expand/collapse animations
  • Spotlight search over controllers and folders — fuzzy match, layout-agnostic typing, path hints
  • Auto-generate UI from objects via import() and connect()
  • Export / persist state with exportJSON(), saveLocal(), loadLocal()
  • Draggable panel, resizable width, shake gesture to toggle folders
  • Dark & light themes (theme: 'toggle' | 'dark' | 'light'), style isolation via Shadow DOM
  • Viewport-fixed layout with compact density on narrow screens or when the panel is resized below ~240px

Quick start

Create a panel and attach it to the page.

import DHGui from './DHGui.js';

const gui = new DHGui('Settings', document.body, {
  width: 280,
  searchEnabled: true,
  theme: 'toggle', // 'toggle' | 'dark' | 'light'
});
gui.show();

Search

Click the magnifier in the title bar (or call openSearch()). Matches controller labels, bound property keys, and folder names. Suggestions show a structural path; folders are marked with a badge. Enter expands ancestors, scrolls the target into view, and highlights it.

const gui = new DHGui('Debug', document.body, {
  searchEnabled: true,
  searchZIndex: 99999,
});

gui.openSearch();  // Spotlight overlay
gui.closeSearch();

Theme

By default the title bar shows a theme toggle. Pass theme: 'dark' or theme: 'light' to lock a fixed theme (no button).

new DHGui('Debug', document.body, { theme: 'toggle' }); // default
new DHGui('Debug', document.body, { theme: 'dark' });
new DHGui('Debug', document.body, { theme: 'light' });

gui.toggleTheme(); // still works from code

Manual controllers

Add controls one by one and react to changes.

const speed = gui.int('Speed', 5, 0, 10);
const color = gui.color('Background', '#2563eb');
const aim = gui.pose2d('Aim', { x: 0.5, y: 0.5 });
const orient = gui.pose3d('Orientation'); // quaternion { x, y, z, w }
const heading = gui.angle('Heading', 0); // radians, 0 = +X, CCW
const stick = gui.joystick('Stick', { x: 0.4, y: -0.2 });
const ease = gui.bezier('Ease', { x1: 0.25, y1: 0.1, x2: 0.25, y2: 1 });
const windowRange = gui.range('Range', { min: 0.2, max: 0.8 }, 0, 1);
const ramp = gui.gradient('Gradient', [
  { offset: 0, color: '#0f172a' },
  { offset: 1, color: '#38bdf8' },
]);

speed.onChange((value) => {
  console.log('Speed:', value);
});

gui.button('Reset', () => gui.reset());

Bind a settings object

connect() walks your object, creates folders for nested properties, and keeps controllers in sync with the source data.

import Settings from './Settings.js';

const gui = new DHGui('Debug', document.body);
gui.connect(Settings, 4);

Image & canvas previews

Embed static images or live HTMLCanvasElement previews inside the panel.

const media = gui.folder('Media');

media.image('./assets/images/sample.png');
media.canvas(myCanvasElement);

API reference

Public methods on DHGui and nested Folder instances. Controller factory methods are available on both.

Constructor

  • new DHGui(title?, container?, options?) — create a panel (defaults: 'DHGui', document.body, { width: 280, searchEnabled: true, searchZIndex: 2147483000, theme: 'toggle' })
  • options.width — initial panel width in pixels
  • options.searchEnabled — show search icon in the title bar (default true)
  • options.searchZIndex — z-index of the search overlay host
  • options.theme — 'toggle' (default, show theme button), or fixed 'dark' / 'light'

Controllers

  • int(name, value?, min?, max?) — integer slider + input
  • float(name, value?, min?, max?) — float slider + input
  • color(name, value?) — color picker (hex)
  • checkbox(name, value?) — boolean toggle
  • select(name, values, selectedValue?) — dropdown
  • button(name, callback) — clickable action
  • text(value?) — read-only text
  • image(src) — image preview (URL or HTMLImageElement)
  • canvas(canvas) — live HTMLCanvasElement preview
  • pose2d(name, value?) — 2D pad (10×10 grid + draggable point); value { x, y } in 0..1; live readout + animated reset
  • pose3d(name, value?) — orientation cube you can drag; value unit quaternion { x, y, z, w }; live readout + animated reset
  • angle(name, value?) — angle dial (ray + handle); value radians in [0, 2π), 0 = +X, CCW; UI shows degrees; live readout + animated reset
  • joystick(name, value?) — joystick pad (unit disk); value { x, y } in [-1, 1], clamped to circle
  • bezier(name, value?) — cubic-bezier easing editor; value { x1, y1, x2, y2 } (CSS cubic-bezier)
  • range(name, value?, boundMin?, boundMax?) — dual-thumb range; value { min, max }
  • gradient(name, value?) — gradient stops [{ offset, color }, …]; drag / drag away to remove / double-click recolor / click empty to add (min 2 stops)

Folders

  • folder(name, boundData?) — nested group; optional live data for copy/export
  • bind(data) — bind a live data object to a folder (Folder only)
  • getDataObject() — deep copy of bound data or collected values (Folder only)
  • copyData() — copy folder data to the clipboard as a JS object literal (Folder only)

Visibility & layout

  • show() / hide() — fade the panel in or out
  • toggle() — expand or collapse with animation
  • expand() / collapse() — open or close with animation
  • open() / close() — open or close instantly
  • expandAll() / collapseAll() — recursively open or close all folders
  • constrainToViewport(immediate?) — keep the panel inside the viewport (DHGui only)
  • toggleTheme() — switch dark / light theme (DHGui only)
  • openSearch() / closeSearch() — Spotlight search overlay (DHGui only; requires searchEnabled)

Data & lifecycle

  • import(obj, options?) — build UI from an object; optional name / filter. Detects colors as hex strings, packed ints (0xRRGGBB / keys with “color”), and { r, g, b[, a] }
  • connect(obj, level?) — bind a live object with max nesting depth (DHGui only, default 4); same color detection as import()
  • exportJSON() — export controller values and folder structure
  • loadJSON(data) — apply exported values to the existing structure
  • saveLocal(storageKey?) — persist state to localStorage (DHGui only)
  • loadLocal(storageKey?) — restore state from localStorage (DHGui only)
  • reset() — restore all controllers to their initial values
  • clear() — remove all controllers and folders
  • destroy() — tear down the panel and remove it from the DOM

Controller / Folder instance

  • value(v?) — get or set the current value (Controller)
  • name(n?) — get or set the label
  • title(t?) — get or set the tooltip (Controller)
  • min(v?) / max(v?) — get or set numeric bounds (Controller)
  • onChange(handler) — listen for value changes (Controller)
  • propertyKey(key?) — bound property name used by search (Controller)
  • highlight() — briefly flash the controller or folder title
  • show() / hide() / reset() / destroy()
  • updateDisplay() — refresh the UI from the current value (Controller)

The panel on this page is fully interactive — drag it, resize, open search, tweak settings, and explore folders in real time.

Download source

Michael Chistyakov — front-end & interactions developer
© 2026