Collection of easy to use and lightweight (~5.2kb css, ~11.7kb js gzipped) vanilla GUI widgets for the web.

Require no dependencies, all widgets can be used on their own.

There is a dark and a bright theme, the dark theme is the default theme and is more polished than the bright one.

Good for single page apps, experiments and the like.

####Demo - Demo
- Demo repository

####Links - Documentation - Compatibility - License



There is a minified and gzipped up to date ready-to-use js file in the dist folder, to use the entire library, just include it in your HTML file

There is also a minified and gzipped up to date ready-to-use css file for each themes in the _dist/[themename] folder, to use it, just include it in your HTML file

<link rel="stylesheet" type="text/css" href="wui.min.css"/>
<script type="text/javascript" src="wui.min.js"></script>

If you need a single (or more) widget, you can find minified files of each widget in the dist/widgets folder


####Building with Node and Grunt

npm install
grunt dist



The WUI API is simple, all widgets have a method “create” which take a DOM element identifier as first argument (which is used as a bind target) and an option object as second argument to customize it, WUI_ToolBar has a third argument which is used to specify the content of the toolbar.

All “create” methods return a reference of the widget which can be used later to do stuff with the widget like destroying them, the reference is a string (it is the dialog element id).

All widgets also have a method “destroy”.

HTML elements with a specific layout are required to use some widgets (like tabs, see the documentation)

A bit of style hacking may be necessary if you want widgets to suit your need or your taste, the demo page can be helpful.



Not really a widget but a collection of tools, can be helpful if you want to add draggable functionality to an element or apply fade in/out.

Fade in/Fade out method default to 500ms if no duration is provided

  • draggable(element, draggable_state, on_drag_cb)
  • lockDraggable(element, axis)
  • fadeIn(element, duration_ms)
  • fadeOut(element, duration_ms, fade_finish_cb, hide_when_fade_finish)


// make the element draggable
// Note: If you want to remove the element while it is draggable, make it undraggable first by passing false as second argument of this function, this is because WUI keep a reference of the element and it may cause memory leaks, passing false will make the reference go away
// a callback for the third argument can be specified to gather the new position, like: function (element, x, y) {  }
WUI.draggable(my_element, true);

// lock draggable element to a specific axis ('x' or 'y', to clear the lock, just call it without specifying axis or specify whatever)
WUI.lockDraggable(my_element, 'x');

// apply a 500ms fade in effect to an element
WUI.fadeIn(my_element, 500);

// apply a 500ms fade out effect to an element, when finished output "finished" to the browser console and hide the element (display: none)
WUI.fadeOut(my_element, 500, function () { console.log("finished!"); }, true);




  • create(id, options)
  • destroy(wui_tabs)
  • getContentElement(wui_tabs, tab_index)
  • getTabName(wui_tabs, tab_index)


<div id="my_tabs">
		<!-- a list of tabs name -->
		<div>Tab 1</div>
        <div>Tab 2</div>
		<!-- a list of tabs content -->
			Tab 1 content
	        Tab 2 content
WUI_Tabs.create("my_tabs", {
	// function called when a tab is clicked (tab index will be passed as argument)
	on_tab_click: tab_clicked,
    // style value for the content height
    height: "calc(100% - 32px)" // this is the default value



Dialogs can be draggable, closable, minimizable, resizable, detachable, modal and act as panels, they also go in front of others when you move them.

One of the coolest (and maybe ‘unique’) feature of the dialog widget is the ability to be detached from the window it is on and act as a proper window without breaking the content (including events), this may be very useful, the user can detach any dialogs and move them on other screens etc.

All WUI widgets work very well with the detachable feature, what you change in the detachable dialog will be changed in the ‘original’ dialog, this should be the same dialog after all, for example, if you toggle a WUI_ToolBar button in the detached dialog and close it, when you open the dialog again (detached or not) the button will be toggled, the only thing which is not synced is the size of the detached dialog and its position.

>Notes: > >On iPad, the detach feature will work but Safari will open the dialog as a new tab. > >===== > The detach feature keep track of events by overriding addEventListener, in order to work correctly the WUI_Dialog/WUI library should be loaded before you or other libs add events. > >===== >When a dialog is detached, it will add back event listeners added with addEventListener only (and also inline events), if you attach events to elements in the dialog content using elem.onclick etc, the event will not be added back, also since the dialog content will be in another window/document, events attached to the initial window or document and acting on the dialog content will not work, because the dialog is now in another window, you will have to take care of attaching to/using element.ownerDocument or element.parentWindow instead of document or window. > >===== >Dialogs zIndex is between 100 and 101.


  • create(id, options)
  • destroy(wui_dialog)
  • open(wui_dialog, detach)
  • close(wui_dialog, propagate)
  • focus(wui_dialog)
  • setStatusBarContent(wui_dialog, html_content)


<div id="my_dialog">
		the dialog content
var my_dialog = WUI_Dialog.create("my_dialog", {
	title: "dialog title",
    width: "20%",
    height: "50%",
    // 'left', 'center', 'right', default to 'left'
    halign: "left",
    // 'top', 'center', 'bottom', default to 'top'
    valign: "center",
    // wether the dialog is opened or not after creation
    open: true,
    // wether the dialog is minimized or not after creation
    minimized: false,
    // function called when the dialog has been closed
    on_close: null,
    // function called when the dialog is detached, the new `window` object is passed as argument
    on_detach: function (new_window) {
        // you can modify the detachable window there, example:
        new_window.document.title = "My detached window"; // replace the detached dialog title
    // function called when the dialog is resized, `new_width` and `new_height` is the new dimension of the dialog content
    on_resize: function (new_width, new_height) {
    modal: false,
    // wether the dialog have a status bar
    status_bar: true,
    // HTML content of the status bar
    status_bar_content: "status bar content",
    closable: false,
    draggable: true,
    minimizable: true,
    resizable: true,
    detachable: true,
    // the minimun width/height the dialog can be when resized (min_width accept a value or "title")
    min_width: "title",
    min_height: 64,
    // option to keep the align when resized, example: if the dialog is centered in the window, the dialog will always be in center when it is resized
    keep_align_when_resized: true,
    // can be used to position the dialog, default to 0
    top: 0,
    left: 0

Closed and want to open it again?

// second argument is optional (default to false) and tell wether the dialog is opened in its own window
WUI_Dialog.open(my_dialog, false);

Open and want to close it programmatically?

WUI_Dialog.close(my_dialog, true); // last argument is optional (default to false) mean the on_close function will be called

Focusing a specific dialog


Want to change the status bar content?

WUI_Dialog.setStatusBarContent(my_dialog, "My new status bar content");


A simple and automatically opening/closing dropdown.


  • create(id, options, entry_name_array)
  • destroy(wui_dropdown)


<div id="my_dropdown"></div>
WUI_DropDown.create("my_dropdown", {
		width: "100px",
	    height: "24px",
	    // the space between the floating list of items and the dropdown "button"
	    vspacing: 4,
	    // time before the floating list close
	    ms_before_hiding: 1000,
	    // default item (id) to be selected after creation
	    selected_id: 0,
	    vertical: false,
	    // function called when an item is selected, the item index is passed as argument
	    on_item_selected: item_selected
    // a list of items
    ["First item", "Second item", "Third item"]



The toolbar can be horizontal or vertical, have groups and minimizable groups, have three type of buttons, simple, toggle and dropdown (useful to make menu bar), a set of toggle buttons can be linked (grouped), buttons can be an icon, a text or both.


  • create(id, options, tools)
  • destroy(wui_toolbar)
  • hideGroup(wui_toolbar, group_index)
  • showGroup(wui_toolbar, group_index)
  • toggle(wui_toolbar, tool_id, propagate)
  • getItemElement(wui_toolbar, tool_id)


<div id="my_toolbar"></div>
var my_toolbar = WUI_ToolBar.create("my_toolbar", {
    // display the minimize icon for each groups
    allow_groups_minimize: true,
    // this will modify the size of the button
    item_width: 32,
    item_height: 32,
    // this set the spacing between buttons, aka margin to left/right or top/bottom
    item_hmargin: 0,
    item_vmargin: 0,
    icon_width: 32,
    icon_height: 32,
    vertical: false
	// properties added to this object are recognized automatically as new groups by the widget
    my_first_group_of_tools: [
        // CSS class name
        icon: "pencil-icon",
        // button text
        text: "",
        // can be "toggle", "dropdown" or nothing for a simple button
        type: "toggle",
        // a toggling group id, another button with the same toggling group id will be linked to this one and will be off when this one will be switched on
        toggle_group: 0,
        // toggle state of the button after creation, only if it is a toggle button
        toggle_state: true,
        // function called when a button is clicked, if the item is of type "toggle", an object containing a field "id" (id of the toolbar tool), "type" (will contain "toggle") and "state" (0 or 1) will be passed as argument
        on_click: toolbar_item_toggle,
        // tooltip
        tooltip: "Toggle me!"
    my_second_group_of_tools:    [
      { icon: "undo-icon", on_click: toolbar_item_click, tooltip: "Click me!" },
      { icon: "redo-icon", on_click: toolbar_item_click, tooltip: "Click me!" }
    // a typical menu with a list of clickable items
    my_menu: [
        text: "File",
        on_click: toolbar_item_click,
        tooltip: "Click me!",
        type: "dropdown",
        // define where the list of items will appear around the item when it will be opened
        // can be "s", "sw", "se", "nw", "ne", anything else will default to "n" (north)
        orientation: "n",
        // define the width of the list items
        // can be a CSS width (auto, 64px etc) or "tb_item" so the list items have the same width as the toolbar item button
        dropdown_items_width: "tb_item",
        // items of the dropdown are defined here
        items: [
            title: "New",
            // function called when the item is clicked
            on_click: my_new_file
            title: "Open",
            // function called when the item is clicked
            on_click: my_open_file

You can toggle a specific button programmatically with:

WUI_ToolBar.toggle(my_toolbar, 0, true); // the last argument is optional and mean that the toggle event will call the onClick function



Range slider widget can be horizontal or vertical, can be user configurable (step, min, max etc options can be set by the user as he want it), have a negative/positive range, the value can be changed with the mouse wheel or by moving the hook point by dragging or by clicking on the slider bar, a double click on the slider will reset the value to its default value, the value also appear as an input which perform automatically all sanity check and will indicate if the value is correct or not (red)


  • create(id, options)
  • destroy(wui_rangeslider)


<div id="my_range_slider"></div>
WUI_RangeSlider.create("my_range_slider", {
    // width/height of the slider, if you make a vertical slider, you should swap theses values
    width: 300,
    height: 8,
    // the value range, -100 <-> 100
    min: -100,
    max: 100,
    // standard increment when dragging
    step: 1,
    // on mouse wheel increment
    scroll_step: 2,
    vertical: false,
    default_value: 0,
    // this will place the title on top and the value at the bottom, good for vertical sliders
    title_on_top: true,
    title: "my range slider",
    // used to line up multiple sliders perfectly
    title_min_width: 150,
    value_min_width: 48,
    // allow the user to configure the parameters of the slider, a settings button will appear around the slider and when it is clicked, a box with input fields will allow the user to change range and step values
    // this can be usefull if an "unlimited" slider is needed or simply to allow the step to be changed by the user
    // Note: if you want a few parameters to be configurable, just remove those you don't want in that object
    configurable: {
    	// this allow the "min" parameter of the slider to be configurable
    	// "min" and "max" is the allowed range of the created input field, it is used to set some boundaries to what range of values the user can set
    	// it is also possible to leave the object empty (like "max" below) to allow unlimited sliders (any values for min/max will be then allowed, allowing the user to extend the range as he like)
    	min: { min: -100, max: 100 },
    	max: { },
    	step: { min: 0.1, max: 2 },
    	scroll_step: { max: 5 }
    // function to call when the slider value change with the value passed as argument
    on_change: slider_change



Show a menu with items arranged in a circle/ellipse.

This widget create function does not return anything and the widget do not have a destroy method, it is automatically destroyed by the library, thus you need to call create each time you want it to appear somewhere.

The menu can be shown around an element or a position, if an element is specified in the options, x y properties will be ignored, x y or element need to be set in order to use this widget, all other properties are optional.

Items are simple round buttons, an icon class name can be specified, a tooltip and a callback.


  • create(options, items)


    x: 64,
    y: 64,
    element: null, // if an element is specified, the menu will be shown around it
    // radius
    rx: 64,
    ry: 64,

    // dimension of the items
    item_width:  32,
    item_height: 32,

    // if you want to display the widget at a position x, y in another window, you may need to specify the target window here
    window: null
    { icon: "css-icon-class", tooltip: "first button",  on_click: function () { } },
    { icon: "css-icon-class", tooltip: "second button", on_click: function () { } },
    { icon: "css-icon-class", tooltip: "third button",  on_click: function () { } },
    { icon: "css-icon-class", tooltip: "fourth button", on_click: function () { } },



Not well tested but should work in all modern browsers supporting ECMAScript 5 and CSS3.

It was not built to target mobile devices, but it still support touch events and should work well on iPad and the like.

Tested and work ok with IE 11, Opera 12, Chrome (30, 35, 40), Firefox (31, 37) and Safari (6, 7, 8).

Mostly work (problems with the ToolBar and Dialog) under IE 10 but i do not support it.



Revised BSD


This was made for an audio app and the map editor of a wargame engine.

Related Repositories



OSSEC Web User Interface - Unmaintained!! ...



Collection of GUI widgets for the web ...



WUI for Clojure. ...



Web UI for you-get ...



Another webkit ui. For teaching purposes ...

Top Contributors