Jforrester has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/356313 )

Change subject: Update OOjs UI to v0.22.0
......................................................................

Update OOjs UI to v0.22.0

Release notes:
 
https://phabricator.wikimedia.org/diffusion/GOJU/browse/master/History.md;v0.22.0

Change-Id: I93b66d5339e6766f46dfcc5b22abaeadd74d8da0
---
M composer.json
M composer.lock
M composer/autoload_classmap.php
M composer/autoload_static.php
M composer/installed.json
M oojs/oojs-ui/.mailmap
M oojs/oojs-ui/AUTHORS.txt
M oojs/oojs-ui/History.md
M oojs/oojs-ui/README.md
M oojs/oojs-ui/bin/generate-JSPHP-for-karma.php
M oojs/oojs-ui/bin/testsuitegenerator.rb
M oojs/oojs-ui/demos/classes/CapsuleNumberPopupMultiselectWidget.js
M oojs/oojs-ui/demos/classes/NumberLookupTextInputWidget.js
M oojs/oojs-ui/demos/demo.js
M oojs/oojs-ui/demos/demos.php
M oojs/oojs-ui/demos/index.html
M oojs/oojs-ui/demos/pages/widgets.js
M oojs/oojs-ui/demos/pages/widgets.php
M oojs/oojs-ui/demos/styles/demo.css
M oojs/oojs-ui/i18n/id.json
M oojs/oojs-ui/package.json
M oojs/oojs-ui/php/themes/MediaWikiTheme.php
A oojs/oojs-ui/php/themes/WikimediaUITheme.php
M oojs/oojs-ui/php/widgets/CheckboxInputWidget.php
A oojs/oojs-ui/php/widgets/HiddenInputWidget.php
M oojs/oojs-ui/php/widgets/InputWidget.php
M oojs/oojs-ui/php/widgets/RadioInputWidget.php
M oojs/oojs-ui/php/widgets/TextInputWidget.php
28 files changed, 1,679 insertions(+), 1,045 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/vendor 
refs/changes/13/356313/1

diff --git a/composer.json b/composer.json
index 069e0a1..bd33908 100644
--- a/composer.json
+++ b/composer.json
@@ -45,7 +45,7 @@
                "monolog/monolog": "1.22.1",
                "mustangostang/spyc": "0.6.2",
                "nmred/kafka-php": "0.1.5",
-               "oojs/oojs-ui": "0.21.4",
+               "oojs/oojs-ui": "0.22.0",
                "oyejorge/less.php": "1.7.0.14",
                "pear/console_getopt": "1.4.1",
                "pear/mail": "1.3.0",
diff --git a/composer.lock b/composer.lock
index 8baa3b0..09a7ae4 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at 
https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file";,
         "This file is @generated automatically"
     ],
-    "content-hash": "c718138a0d49641945b13ec3d33e43c4",
+    "content-hash": "b11c2cf5cde1b9f593e047ef0f5ceba7",
     "packages": [
         {
             "name": "composer/semver",
@@ -516,16 +516,16 @@
         },
         {
             "name": "oojs/oojs-ui",
-            "version": "v0.21.4",
+            "version": "v0.22.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/wikimedia/oojs-ui.git";,
-                "reference": "ed5dd92664b765a160e68e46ec0337e75451b0ad"
+                "reference": "7266f93803bafb52df22925fda743cbe35a84b98"
             },
             "dist": {
                 "type": "zip",
-                "url": 
"https://api.github.com/repos/wikimedia/oojs-ui/zipball/ed5dd92664b765a160e68e46ec0337e75451b0ad";,
-                "reference": "ed5dd92664b765a160e68e46ec0337e75451b0ad",
+                "url": 
"https://api.github.com/repos/wikimedia/oojs-ui/zipball/7266f93803bafb52df22925fda743cbe35a84b98";,
+                "reference": "7266f93803bafb52df22925fda743cbe35a84b98",
                 "shasum": ""
             },
             "require": {
@@ -591,7 +591,7 @@
             ],
             "description": "Provides library of common widgets, layouts, and 
windows.",
             "homepage": "https://www.mediawiki.org/wiki/OOjs_UI";,
-            "time": "2017-05-16T22:09:22+00:00"
+            "time": "2017-05-30T22:02:38+00:00"
         },
         {
             "name": "oyejorge/less.php",
diff --git a/composer/autoload_classmap.php b/composer/autoload_classmap.php
index eebf93e..f67b0ac 100644
--- a/composer/autoload_classmap.php
+++ b/composer/autoload_classmap.php
@@ -534,6 +534,7 @@
     'OOUI\\FlaggedElement' => $vendorDir . 
'/oojs/oojs-ui/php/mixins/FlaggedElement.php',
     'OOUI\\FormLayout' => $vendorDir . 
'/oojs/oojs-ui/php/layouts/FormLayout.php',
     'OOUI\\GroupElement' => $vendorDir . 
'/oojs/oojs-ui/php/mixins/GroupElement.php',
+    'OOUI\\HiddenInputWidget' => $vendorDir . 
'/oojs/oojs-ui/php/widgets/HiddenInputWidget.php',
     'OOUI\\HorizontalLayout' => $vendorDir . 
'/oojs/oojs-ui/php/layouts/HorizontalLayout.php',
     'OOUI\\HtmlSnippet' => $vendorDir . '/oojs/oojs-ui/php/HtmlSnippet.php',
     'OOUI\\IconElement' => $vendorDir . 
'/oojs/oojs-ui/php/mixins/IconElement.php',
@@ -555,6 +556,7 @@
     'OOUI\\Theme' => $vendorDir . '/oojs/oojs-ui/php/Theme.php',
     'OOUI\\TitledElement' => $vendorDir . 
'/oojs/oojs-ui/php/mixins/TitledElement.php',
     'OOUI\\Widget' => $vendorDir . '/oojs/oojs-ui/php/Widget.php',
+    'OOUI\\WikimediaUITheme' => $vendorDir . 
'/oojs/oojs-ui/php/themes/WikimediaUITheme.php',
     'OS_Guess' => $vendorDir . '/pear/pear-core-minimal/src/OS/Guess.php',
     'PEAR' => $vendorDir . '/pear/pear-core-minimal/src/PEAR.php',
     'PEAR_Error' => $vendorDir . '/pear/pear-core-minimal/src/PEAR.php',
diff --git a/composer/autoload_static.php b/composer/autoload_static.php
index 6900e49..5e293f1 100644
--- a/composer/autoload_static.php
+++ b/composer/autoload_static.php
@@ -720,6 +720,7 @@
         'OOUI\\FlaggedElement' => __DIR__ . '/..' . 
'/oojs/oojs-ui/php/mixins/FlaggedElement.php',
         'OOUI\\FormLayout' => __DIR__ . '/..' . 
'/oojs/oojs-ui/php/layouts/FormLayout.php',
         'OOUI\\GroupElement' => __DIR__ . '/..' . 
'/oojs/oojs-ui/php/mixins/GroupElement.php',
+        'OOUI\\HiddenInputWidget' => __DIR__ . '/..' . 
'/oojs/oojs-ui/php/widgets/HiddenInputWidget.php',
         'OOUI\\HorizontalLayout' => __DIR__ . '/..' . 
'/oojs/oojs-ui/php/layouts/HorizontalLayout.php',
         'OOUI\\HtmlSnippet' => __DIR__ . '/..' . 
'/oojs/oojs-ui/php/HtmlSnippet.php',
         'OOUI\\IconElement' => __DIR__ . '/..' . 
'/oojs/oojs-ui/php/mixins/IconElement.php',
@@ -741,6 +742,7 @@
         'OOUI\\Theme' => __DIR__ . '/..' . '/oojs/oojs-ui/php/Theme.php',
         'OOUI\\TitledElement' => __DIR__ . '/..' . 
'/oojs/oojs-ui/php/mixins/TitledElement.php',
         'OOUI\\Widget' => __DIR__ . '/..' . '/oojs/oojs-ui/php/Widget.php',
+        'OOUI\\WikimediaUITheme' => __DIR__ . '/..' . 
'/oojs/oojs-ui/php/themes/WikimediaUITheme.php',
         'OS_Guess' => __DIR__ . '/..' . 
'/pear/pear-core-minimal/src/OS/Guess.php',
         'PEAR' => __DIR__ . '/..' . '/pear/pear-core-minimal/src/PEAR.php',
         'PEAR_Error' => __DIR__ . '/..' . 
'/pear/pear-core-minimal/src/PEAR.php',
diff --git a/composer/installed.json b/composer/installed.json
index ccb05f4..c221a6c 100644
--- a/composer/installed.json
+++ b/composer/installed.json
@@ -2163,18 +2163,70 @@
         "homepage": "https://www.mediawiki.org/wiki/Testing-access-wrapper";
     },
     {
-        "name": "oojs/oojs-ui",
-        "version": "v0.21.4",
-        "version_normalized": "0.21.4.0",
+        "name": "mustangostang/spyc",
+        "version": "0.6.2",
+        "version_normalized": "0.6.2.0",
         "source": {
             "type": "git",
-            "url": "https://github.com/wikimedia/oojs-ui.git";,
-            "reference": "ed5dd92664b765a160e68e46ec0337e75451b0ad"
+            "url": "https://github.com/mustangostang/spyc.git";,
+            "reference": "23c35ae854d835f2d7bcc3e3ad743d7e57a8c14d"
         },
         "dist": {
             "type": "zip",
-            "url": 
"https://api.github.com/repos/wikimedia/oojs-ui/zipball/ed5dd92664b765a160e68e46ec0337e75451b0ad";,
-            "reference": "ed5dd92664b765a160e68e46ec0337e75451b0ad",
+            "url": 
"https://api.github.com/repos/mustangostang/spyc/zipball/23c35ae854d835f2d7bcc3e3ad743d7e57a8c14d";,
+            "reference": "23c35ae854d835f2d7bcc3e3ad743d7e57a8c14d",
+            "shasum": ""
+        },
+        "require": {
+            "php": ">=5.3.1"
+        },
+        "require-dev": {
+            "phpunit/phpunit": "4.3.*@dev"
+        },
+        "time": "2017-02-24T16:06:33+00:00",
+        "type": "library",
+        "extra": {
+            "branch-alias": {
+                "dev-master": "0.5.x-dev"
+            }
+        },
+        "installation-source": "dist",
+        "autoload": {
+            "files": [
+                "Spyc.php"
+            ]
+        },
+        "notification-url": "https://packagist.org/downloads/";,
+        "license": [
+            "MIT"
+        ],
+        "authors": [
+            {
+                "name": "mustangostang",
+                "email": "[email protected]"
+            }
+        ],
+        "description": "A simple YAML loader/dumper class for PHP",
+        "homepage": "https://github.com/mustangostang/spyc/";,
+        "keywords": [
+            "spyc",
+            "yaml",
+            "yml"
+        ]
+    },
+    {
+        "name": "oojs/oojs-ui",
+        "version": "v0.22.0",
+        "version_normalized": "0.22.0.0",
+        "source": {
+            "type": "git",
+            "url": "https://github.com/wikimedia/oojs-ui.git";,
+            "reference": "7266f93803bafb52df22925fda743cbe35a84b98"
+        },
+        "dist": {
+            "type": "zip",
+            "url": 
"https://api.github.com/repos/wikimedia/oojs-ui/zipball/7266f93803bafb52df22925fda743cbe35a84b98";,
+            "reference": "7266f93803bafb52df22925fda743cbe35a84b98",
             "shasum": ""
         },
         "require": {
@@ -2186,7 +2238,7 @@
             "mediawiki/mediawiki-codesniffer": "0.6.0",
             "phpunit/phpunit": "4.8.21"
         },
-        "time": "2017-05-16T22:09:22+00:00",
+        "time": "2017-05-30T22:02:38+00:00",
         "type": "library",
         "installation-source": "dist",
         "autoload": {
@@ -2242,57 +2294,5 @@
         ],
         "description": "Provides library of common widgets, layouts, and 
windows.",
         "homepage": "https://www.mediawiki.org/wiki/OOjs_UI";
-    },
-    {
-        "name": "mustangostang/spyc",
-        "version": "0.6.2",
-        "version_normalized": "0.6.2.0",
-        "source": {
-            "type": "git",
-            "url": "https://github.com/mustangostang/spyc.git";,
-            "reference": "23c35ae854d835f2d7bcc3e3ad743d7e57a8c14d"
-        },
-        "dist": {
-            "type": "zip",
-            "url": 
"https://api.github.com/repos/mustangostang/spyc/zipball/23c35ae854d835f2d7bcc3e3ad743d7e57a8c14d";,
-            "reference": "23c35ae854d835f2d7bcc3e3ad743d7e57a8c14d",
-            "shasum": ""
-        },
-        "require": {
-            "php": ">=5.3.1"
-        },
-        "require-dev": {
-            "phpunit/phpunit": "4.3.*@dev"
-        },
-        "time": "2017-02-24T16:06:33+00:00",
-        "type": "library",
-        "extra": {
-            "branch-alias": {
-                "dev-master": "0.5.x-dev"
-            }
-        },
-        "installation-source": "dist",
-        "autoload": {
-            "files": [
-                "Spyc.php"
-            ]
-        },
-        "notification-url": "https://packagist.org/downloads/";,
-        "license": [
-            "MIT"
-        ],
-        "authors": [
-            {
-                "name": "mustangostang",
-                "email": "[email protected]"
-            }
-        ],
-        "description": "A simple YAML loader/dumper class for PHP",
-        "homepage": "https://github.com/mustangostang/spyc/";,
-        "keywords": [
-            "spyc",
-            "yaml",
-            "yml"
-        ]
     }
 ]
diff --git a/oojs/oojs-ui/.mailmap b/oojs/oojs-ui/.mailmap
index 3ec803b..b95bbc8 100644
--- a/oojs/oojs-ui/.mailmap
+++ b/oojs/oojs-ui/.mailmap
@@ -1,8 +1,8 @@
 Alex Monk <[email protected]>
 Alex Monk <[email protected]> <[email protected]>
 Bartosz Dziewoński <[email protected]>
-Bartosz Dziewoński <[email protected]> <[email protected]>
 Bartosz Dziewoński <[email protected]> <[email protected]>
+Bartosz Dziewoński <[email protected]> <[email protected]>
 Christian Williams <[email protected]>
 Christian Williams <[email protected]> <christian@localhost>
 Christian Williams <[email protected]> <[email protected]>
@@ -16,16 +16,27 @@
 Inez Korczyński <[email protected]>
 Inez Korczyński <[email protected]> <[email protected]>
 James D. Forrester <[email protected]>
+Jon Robson <[email protected]>
+Juliusz Gonera <[email protected]>
+Juliusz Gonera <[email protected]>
 Kirsten Menger-Anderson <[email protected]>
+Kunal Mehta <[email protected]>
+Kunal Mehta <[email protected]> <[email protected]>
 Marielle Volz <[email protected]>
+May Tee-Galloway <[email protected]>
+May Tee-Galloway <[email protected]> <[email protected]>
 Moriel Schottlender <[email protected]>
 Moriel Schottlender <[email protected]> <[email protected]>
+Prateek Saxena <[email protected]>
+Prateek Saxena <[email protected]> <[email protected]>
 Roan Kattouw <[email protected]>
 Roan Kattouw <[email protected]> <[email protected]>
 Roan Kattouw <[email protected]> <[email protected]>
 Rob Moen <[email protected]>
 Rob Moen <[email protected]> <[email protected]>
 Rob Moen <[email protected]> <[email protected]>
+Sam Reed <[email protected]>
+Sam Reed <[email protected]> <[email protected]>
 Sucheta Ghoshal <[email protected]>
 Thalia Chan <[email protected]>
 Thalia Chan <[email protected]> <[email protected]>
@@ -34,5 +45,7 @@
 Trevor Parscal <[email protected]>
 Trevor Parscal <[email protected]> <[email protected]>
 Trevor Parscal <[email protected]> <[email protected]>
+Volker E. <[email protected]>
+Volker E. <[email protected]> <[email protected]>
 Željko Filipin <[email protected]>
 Željko Filipin <[email protected]> <[email protected]>
diff --git a/oojs/oojs-ui/AUTHORS.txt b/oojs/oojs-ui/AUTHORS.txt
index a17f3a4..52b4888 100644
--- a/oojs/oojs-ui/AUTHORS.txt
+++ b/oojs/oojs-ui/AUTHORS.txt
@@ -5,35 +5,54 @@
 James D. Forrester <[email protected]>
 Kirsten Menger-Anderson <[email protected]>
 Kunal Mehta <[email protected]>
+Moriel Schottlender <[email protected]>
 Prateek Saxena <[email protected]>
 Roan Kattouw <[email protected]>
 Rob Moen <[email protected]>
 Timo Tijhof <[email protected]>
 Trevor Parscal <[email protected]>
+Volker E. <[email protected]>
 
 Patch Contributors (minor contributors, alphabetically)
 
+Alangi Derick <[email protected]>
 Alex Monk <[email protected]>
 Amir E. Aharoni <[email protected]>
+Amir Sarabadani <[email protected]>
+Andrew Garrett <[email protected]>
+Andrew Green <[email protected]>
 Antoine Musso <[email protected]>
 Brad Jorsch <[email protected]>
+Brion Vibber <[email protected]>
 C. Scott Ananian <[email protected]>
+Chad Horohoe <[email protected]>
+codynguyen1116 <[email protected]>
 David Lynch <[email protected]>
 Derk-Jan Hartman <[email protected]>
 eranroz <[email protected]>
 Erick Guan <[email protected]>
 Erik Moeller <[email protected]>
 Florian <[email protected]>
+Geoffrey Mon <[email protected]>
 Gilles Dubuc <[email protected]>
-Inez Korczyński <[email protected]>
+Huji Lee <[email protected]>
+Inez Korczyński <[email protected]>
+IvanFon <[email protected]>
+Jon Robson <[email protected]>
 Juliusz Gonera <[email protected]>
+Kartik Mistry <[email protected]>
 Kyle Florence <[email protected]>
+Leszek Manicki <[email protected]>
+Marc A. Pelletier <[email protected]>
+Mark Holmquist <[email protected]>
 Matthew Flaschen <[email protected]>
 May Tee-Galloway <[email protected]>
-Moriel Schottlender <[email protected]>
 Mr. Stradivarius <[email protected]>
 Niklas Laxström <[email protected]>
 Nirzar Pangarkar <[email protected]>
+Ori Livneh <[email protected]>
+Paladox <[email protected]>
+Pau Giner <[email protected]>
 Ricordisamoa <[email protected]>
 rillke <[email protected]>
 Ryan Kaldari <[email protected]>
@@ -41,6 +60,6 @@
 Stephane Bisson <[email protected]>
 Sucheta Ghoshal <[email protected]>
 Thalia Chan <[email protected]>
-Volker Eckl <[email protected]>
+Victor Barbu <[email protected]>
 Wei-Ko Kao <[email protected]>
 Željko Filipin <[email protected]>
diff --git a/oojs/oojs-ui/History.md b/oojs/oojs-ui/History.md
index 43652e2..8ea366a 100644
--- a/oojs/oojs-ui/History.md
+++ b/oojs/oojs-ui/History.md
@@ -1,4 +1,61 @@
 # OOjs UI Release History
+## v0.22.0 / 2017-05-30
+### Breaking changes
+* [BREAKING CHANGE] TextInputWidget: Remove search related methods (Prateek 
Saxena)
+* [BREAKING CHANGE] icons: Drop the core icon pack (James D. Forrester)
+* [BREAKING CHANGE] icons: Remove unused 'bookmark' icon (Volker E.)
+
+### Deprecations
+* [DEPRECATING CHANGE] Rename the 'MediaWiki' theme to 'WikimediaUI' (James D. 
Forrester)
+* [DEPRECATING CHANGE] WindowManager: Deprecate using 
`openWindow`/`closeWindow` returns as promises (Bartosz Dziewoński)
+
+### Features
+* Add HiddenInputWidget to generate hidden input (Victor Barbu)
+* InputWidget: Introduce `#setInputId` and `inputId` config option (Bartosz 
Dziewoński)
+* MenuTagMultiselectWidget: Clear text field after adding an item from it 
(Bartosz Dziewoński)
+* MenuTagMultiselectWidget: Handle the 'selected' config option (Bartosz 
Dziewoński)
+* NumberInputWidget: Use icons instead of labels (Volker E.)
+* PopupButtonWidget: Handle empty configuration (Bartosz Dziewoński)
+* PopupWidget: Position close button in head absolutely (David Lynch)
+* PopupWidget: Sensibly position anchor-less popups (Roan Kattouw)
+* WindowManager: Add `WindowInstance` - a Promise-based lifecycle object (Timo 
Tijhof)
+* WindowManager: Handle errors better in `#closeWindow` (Bartosz Dziewoński)
+
+* Allow *even more* widgets to be focussed programatically (Bartosz Dziewoński)
+* Only cancel mouse down event if tool in toolgroup clicked on (Ed Sanders)
+* Re-introduce `.simulateLabelClick()` as a separate method from .focus() 
(Bartosz Dziewoński)
+
+### Styles
+* themes: Field*Layout help position perfectly aligned (Volker E.)
+* themes: Improve frameless button in size and behaviour (Volker E.)
+* themes: Increase FieldsetLayout header's `font-size` (Volker E.)
+* Apex theme: Ensure vertical centering of ButtonElement's icon (Volker E.)
+* Apex theme: Make OptionWidget icon override more specific (Moriel 
Schottlender)
+* Apex theme: Start Apex's 'user' icon pack, with just 'userAvatar' for now 
(Ed Sanders)
+* WikimediaUI theme: Align `@background-color-destructive` to WikimediaUI Base 
(Volker E.)
+* WikimediaUI theme: Align ButtonInputWidget's `line-height` to ButtonWidget 
(Volker E.)
+* WikimediaUI theme: Align inline label's position (Volker E.)
+* WikimediaUI theme: Ensure icon aligns in dropdown menu (Volker E.)
+* WikimediaUI theme: Remove incorrect comments (Volker E.)
+
+### Code
+* MenuTagMultiselectWidget: Add test for 'selected' config option (Bartosz 
Dziewoński)
+* windows: Add tests for OO.ui.alert/confirm/prompt (Timo Tijhof)
+* AUTHORS: Update for the past two years' work (James D. Forrester)
+* build: Add the README/AUTHORS/LICENCE files to dist (James D. Forrester)
+* demos: Add TextInputWidget examples with inline labels but no indicators (Ed 
Sanders)
+* demos: Add viewport meta tag to PHP demo too (Volker E.)
+* demos: Avoid inline CSS for the overlay (Bartosz Dziewoński)
+* demos: Fix code generation for more complicated cases (Bartosz Dziewoński)
+* demos: Fix up a couple of minor things in demo widgets (Bartosz Dziewoński)
+* demos: Fix `z-index` with fixed demo header (Volker E.)
+* demos: Increase and strengthen responsive support (Volker E.)
+* demos: Indicate widgets clearer by sections (Volker E.)
+* demos: Make disabled progress bar in demo determinate (Ed Sanders)
+* demos: Show code that can be used to create the widget (Prateek Saxena)
+* testsuitegenerator: Handle classes with no constructor (Bartosz Dziewoński)
+
+
 ## v0.21.4 / 2017-05-16
 ### Features
 * Allow more widgets to be focussed programatically (Bartosz Dziewoński)
diff --git a/oojs/oojs-ui/README.md b/oojs/oojs-ui/README.md
index 0a2f0e2..6ee88c4 100644
--- a/oojs/oojs-ui/README.md
+++ b/oojs/oojs-ui/README.md
@@ -35,9 +35,9 @@
 
 While the distribution directory is chock-full of files, you will normally 
only need to load three:
 
-* `oojs-ui.js`, containing the full library
-* One of `oojs-ui-mediawiki.css` or `oojs-ui-apex.css`, containing 
theme-specific styles
-* One of `oojs-ui-mediawiki.js` or  `oojs-ui-apex.js`, containing 
theme-specific code
+* `oojs-ui.js`, containing the full library;
+* One of `oojs-ui-wikimediaui.css` or `oojs-ui-apex.css`, containing 
theme-specific styles; and
+* One of `oojs-ui-wikimediaui.js` or  `oojs-ui-apex.js`, containing 
theme-specific code
 
 You can load additional icon packs from files named 
`oojs-ui-mediawiki-icons-*.css` or  `oojs-ui-apex-icons-*.css`.
 
diff --git a/oojs/oojs-ui/bin/generate-JSPHP-for-karma.php 
b/oojs/oojs-ui/bin/generate-JSPHP-for-karma.php
index faadd70..c58e1d2 100644
--- a/oojs/oojs-ui/bin/generate-JSPHP-for-karma.php
+++ b/oojs/oojs-ui/bin/generate-JSPHP-for-karma.php
@@ -24,7 +24,7 @@
        }
 }
 // Keep synchronized with tests/index.php
-$themes = [ 'ApexTheme', 'MediaWikiTheme' ];
+$themes = [ 'ApexTheme', 'WikimediaUITheme' ];
 foreach ( $themes as $theme ) {
        OOUI\Theme::setSingleton( new_OOUI( $theme ) );
        foreach ( $testSuite as $className => $tests ) {
diff --git a/oojs/oojs-ui/bin/testsuitegenerator.rb 
b/oojs/oojs-ui/bin/testsuitegenerator.rb
index f0da93e..bada71b 100644
--- a/oojs/oojs-ui/bin/testsuitegenerator.rb
+++ b/oojs/oojs-ui/bin/testsuitegenerator.rb
@@ -21,6 +21,7 @@
        testable_classes = classes
                .reject{|c| c[:abstract] } # can't test abstract classes
                .reject{|c| !c[:parent] || c[:trait] || c[:parent] == 'Theme' } 
# can't test abstract
+               .reject{|c| c[:name] == 'MediaWikiTheme' } # can't test abstract
                .reject{|c| %w[Element Widget Layout Theme].include? c[:name] } 
# no toplevel
 
        make_class_instance_placeholder = lambda do |klass, config|
@@ -105,7 +106,8 @@
                                vals = expandos[t]
                        elsif testable_classes.find{|c| c[:name] == t }
                                # OOUI object. Test suite will instantiate one 
and run the test with it.
-                               params = 
find_class.call(t)[:methods][0][:params] || []
+                               constructor = 
find_class.call(t)[:methods].find{|m| m[:name] == '#constructor' }
+                               params = constructor ? (constructor[:params] || 
[]) : []
                                config = params.map{|config_option|
                                        types = config_option[:type].split '|'
                                        values = 
expand_types_to_values.call(types)
@@ -145,9 +147,10 @@
                }
 
                config_sources = find_config_sources.call(class_name)
-                       .map{|c| find_class.call(c)[:methods][0] }
-               config = config_sources.map{|c| c[:config] }.compact.inject(:+)
-               required_config = klass[:methods][0][:params] || []
+                       .map{|c| find_class.call(c)[:methods].find{|m| m[:name] 
== '#constructor' } }
+               config = config_sources.compact.map{|c| c[:config] 
}.compact.inject([], :+)
+               constructor = klass[:methods].find{|m| m[:name] == 
'#constructor' }
+               required_config = constructor ? (constructor[:params] || []) : 
[]
 
                # generate every possible configuration of configuration option 
sets
                maxlength = [config.length, 2].min
diff --git a/oojs/oojs-ui/demos/classes/CapsuleNumberPopupMultiselectWidget.js 
b/oojs/oojs-ui/demos/classes/CapsuleNumberPopupMultiselectWidget.js
index ca8a533..5cf3826 100644
--- a/oojs/oojs-ui/demos/classes/CapsuleNumberPopupMultiselectWidget.js
+++ b/oojs/oojs-ui/demos/classes/CapsuleNumberPopupMultiselectWidget.js
@@ -7,11 +7,14 @@
        // Parent constructor
        Demo.CapsuleNumberPopupMultiselectWidget.parent.call( this, $.extend( 
{}, config, {
                allowArbitrary: true,
-               popup: { $content: this.capsulePopupWidget.$element }
+               popup: {}
        } ) );
 
        // Events
        this.capsulePopupWidget.connect( this, { enter: 'onPopupEnter' } );
+
+       // Initialization
+       this.popup.$body.append( this.capsulePopupWidget.$element );
 };
 
 OO.inheritClass( Demo.CapsuleNumberPopupMultiselectWidget, 
OO.ui.CapsuleMultiselectWidget );
diff --git a/oojs/oojs-ui/demos/classes/NumberLookupTextInputWidget.js 
b/oojs/oojs-ui/demos/classes/NumberLookupTextInputWidget.js
index 97d0753..7ad5d16 100644
--- a/oojs/oojs-ui/demos/classes/NumberLookupTextInputWidget.js
+++ b/oojs/oojs-ui/demos/classes/NumberLookupTextInputWidget.js
@@ -10,7 +10,7 @@
  */
 Demo.NumberLookupTextInputWidget = function DemoNumberLookupTextInputWidget( 
config ) {
        // Parent constructor
-       OO.ui.TextInputWidget.call( this, { validate: 'integer' } );
+       OO.ui.TextInputWidget.call( this, $.extend( { validate: 'integer' }, 
config ) );
        // Mixin constructors
        OO.ui.mixin.LookupElement.call( this, config );
 };
diff --git a/oojs/oojs-ui/demos/demo.js b/oojs/oojs-ui/demos/demo.js
index c1d682c..3c8dc00 100644
--- a/oojs/oojs-ui/demos/demo.js
+++ b/oojs/oojs-ui/demos/demo.js
@@ -1,4 +1,5 @@
 /* eslint-disable no-console */
+/* globals Prism */
 /**
  * @class
  * @extends {OO.ui.Element}
@@ -63,6 +64,7 @@
 
        this.documentationLink = new OO.ui.ButtonWidget( {
                label: 'Docs',
+               classes: [ 'demo-button-docs' ],
                icon: 'journal',
                href: '../js/',
                flags: [ 'progressive' ]
@@ -130,7 +132,7 @@
  * @property {Object.<string,string>}
  */
 Demo.static.themes = {
-       mediawiki: 'MediaWiki', // Do not change this line or you'll break 
`grunt add-theme`
+       wikimediaui: 'WikimediaUI', // Do not change this line or you'll break 
`grunt add-theme`
        apex: 'Apex'
 };
 
@@ -141,7 +143,7 @@
  * @property {Object.<string,string[]>
  */
 Demo.static.additionalThemeImagesSuffixes = {
-       mediawiki: [
+       wikimediaui: [
                '-icons-movement',
                '-icons-content',
                '-icons-alerts',
@@ -169,6 +171,7 @@
                '-icons-editing-list',
                '-icons-editing-advanced',
                '-icons-media',
+               '-icons-user',
                '-icons-layout'
        ]
 };
@@ -211,7 +214,7 @@
  * @static
  * @property {string}
  */
-Demo.static.defaultTheme = 'mediawiki';
+Demo.static.defaultTheme = 'wikimediaui';
 
 /**
  * Default page.
@@ -435,8 +438,8 @@
  * @param {string} widget Variable name for layout's field widget
  * @return {jQuery} Console interface element
  */
-Demo.prototype.buildConsole = function ( item, layout, widget ) {
-       var $toggle, $log, $label, $input, $submit, $console, $form,
+Demo.prototype.buildConsole = function ( item, layout, widget, showLayoutCode 
) {
+       var $toggle, $log, $label, $input, $submit, $console, $form, $pre, 
$code,
                console = window.console;
 
        function exec( str ) {
@@ -498,10 +501,107 @@
                $log.prop( 'scrollTop', $log.prop( 'scrollHeight' ) );
        }
 
+       function getCode( item ) {
+               var config, isDemoWidget, constructorName, defaultConfig, url, 
params, out,
+                       replaceKeyword = 'replace-',
+                       replaceLater = [];
+
+               // If no item was passed we shouldn't show a code block
+               if ( item === undefined ) {
+                       return false;
+               }
+
+               isDemoWidget = item.constructor.name.indexOf( 'Demo' ) === 0;
+               config = item.initialConfig;
+               constructorName = ( isDemoWidget ? 'Demo.' : 'OO.ui.' ) + 
item.constructor.name.slice( 4 );
+
+               // Prevent the default config from being part of the code
+               if ( item instanceof OO.ui.ActionFieldLayout ) {
+                       defaultConfig = ( new item.constructor( new 
OO.ui.TextInputWidget(), new OO.ui.ButtonWidget() ) ).initialConfig;
+               } else if ( item instanceof OO.ui.FieldLayout ) {
+                       defaultConfig = ( new item.constructor( new 
OO.ui.ButtonWidget() ) ).initialConfig;
+               } else {
+                       defaultConfig = ( new item.constructor() 
).initialConfig;
+               }
+               Object.keys( defaultConfig ).forEach( function ( key ) {
+                       if ( config[ key ] === defaultConfig[ key ] ) {
+                               delete config[ key ];
+                       } else if (
+                               typeof config[ key ] === 'object' && typeof 
defaultConfig[ key ] === 'object' &&
+                               OO.compare( config[ key ], defaultConfig[ key ] 
)
+                       ) {
+                               delete config[ key ];
+                       }
+               } );
+
+               config = JSON.stringify( config, function ( k, v ) {
+                       if ( v instanceof OO.ui.Element || v instanceof 
OO.ui.HtmlSnippet || v instanceof jQuery || v instanceof Function ) {
+                               replaceLater.push( v );
+                               return replaceKeyword + ( replaceLater.length - 
1 ).toString();
+                       }
+                       return v;
+               }, '\t' );
+
+               // We replace later, because running getCode in place will 
treat the new code
+               // as a string and won't do proper indentation either
+               replaceLater.forEach( function ( obj, i ) {
+                       config = config.replace(
+                               // Match any number of tabs (for indentation) 
and optional object key, followed by our placeholder
+                               new RegExp( '(\t*)("[^"]+?": |)"' + 
replaceKeyword + i + '"' ),
+                               function ( all, indent, objectKey ) {
+                                       var code;
+                                       if ( obj instanceof Function ) {
+                                               // Get function's source code, 
with extraneous indentation removed
+                                               code = obj.toString().replace( 
/^\t\t\t\t\t\t/gm, '' );
+                                       } else if ( obj instanceof jQuery ) {
+                                               if ( $.contains( item.$element[ 
0 ], obj[ 0 ] ) ) {
+                                                       // If this element 
appears inside the generated widget,
+                                                       // assume this was 
something like `$label: $( '<p>Text</p>' )`
+                                                       code = '$( \"' + 
obj.prop( 'outerHTML' ).replace( /'/g, '\\\'' ) + '\" )';
+                                               } else {
+                                                       // Otherwise assume 
this was something like `$overlay: $( '#overlay' )`
+                                                       code = '$( \"#' + 
obj.attr( 'id' ) + '\" )';
+                                               }
+                                       } else if ( obj instanceof 
OO.ui.HtmlSnippet ) {
+                                               code = 'new OO.ui.HtmlSnippet( 
"' + obj.toString() + '" )';
+                                       } else {
+                                               code = getCode( obj );
+                                       }
+                                       // Re-add the indent at the beginning, 
and after every newline
+                                       return indent + objectKey + 
code.replace( /\n/g, '\n' + indent );
+                               }
+                       );
+               } );
+
+               // The generated code needs to include different arguments, 
based on the object type
+               if ( item instanceof OO.ui.ActionFieldLayout ) {
+                       params = getCode( item.fieldWidget ) + ', ' + getCode( 
item.buttonWidget );
+               } else if ( item instanceof OO.ui.FieldLayout ) {
+                       params = getCode( item.fieldWidget );
+               } else {
+                       params = '';
+               }
+               if ( config !== '{}' ) {
+                       params += ( params ? ', ' : '' ) + config;
+               }
+               out = 'new ' + constructorName + '(' + ( params ? ' ' : '' ) + 
params + ( params ? ' ' : '' ) + ')';
+
+               // The code generated for Demo widgets cannot be copied and used
+               if ( item.constructor.name.indexOf( 'Demo' ) === 0 ) {
+                       url =
+                               
'https://phabricator.wikimedia.org/diffusion/GOJU/browse/master/demos/classes/' 
+
+                               item.constructor.name.slice( 4 ) + '.js';
+                       out = '// See source code:\n// ' + url + '\n' + out;
+               }
+
+               return out;
+       }
+
        $toggle = $( '<span>' )
                .addClass( 'demo-console-toggle' )
                .attr( 'title', 'Toggle console' )
                .on( 'click', function ( e ) {
+                       var code;
                        e.preventDefault();
                        $console.toggleClass( 'demo-console-collapsed 
demo-console-expanded' );
                        if ( $input.is( ':visible' ) ) {
@@ -511,6 +611,19 @@
                                        window[ widget ] = item.fieldWidget;
                                        console.log( '[demo]', 'Globals ' + 
layout + ', ' + widget + ' have been set' );
                                        console.log( '[demo]', item );
+
+                                       if ( showLayoutCode === true ) {
+                                               code = getCode( item );
+                                       } else {
+                                               code = getCode( 
item.fieldWidget );
+                                       }
+
+                                       if ( code ) {
+                                               $code.text( code );
+                                               Prism.highlightElement( $code[ 
0 ] );
+                                       } else {
+                                               $code.remove();
+                                       }
                                }
                        }
                } );
@@ -535,6 +648,12 @@
                submit();
        } );
 
+       $code = $( '<code>' ).addClass( 'language-javascript' );
+
+       $pre = $( '<pre>' )
+               .addClass( 'demo-sample-code' )
+               .append( $code );
+
        $console = $( '<div>' )
                .addClass( 'demo-console demo-console-collapsed' )
                .append(
@@ -545,7 +664,8 @@
                                        $input
                                ),
                                $submit
-                       )
+                       ),
+                       $pre
                );
 
        return $console;
diff --git a/oojs/oojs-ui/demos/demos.php b/oojs/oojs-ui/demos/demos.php
index bd22c06..ac95d30 100644
--- a/oojs/oojs-ui/demos/demos.php
+++ b/oojs/oojs-ui/demos/demos.php
@@ -10,11 +10,11 @@
        require_once 'classes/ButtonStyleShowcaseWidget.php';
 
        $themes = [
-               'mediawiki' => 'MediaWiki', // Do not change this line or 
you'll break `grunt add-theme`
+               'wikimediaui' => 'WikimediaUI', // Do not change this line or 
you'll break `grunt add-theme`
                'apex' => 'Apex',
        ];
        $theme = ( isset( $_GET['theme'] ) && isset( $themes[ $_GET['theme'] ] 
) )
-               ? $_GET['theme'] : 'mediawiki';
+               ? $_GET['theme'] : 'wikimediaui';
        $themeClass = 'OOUI\\' . $themes[ $theme ] . 'Theme';
        OOUI\Theme::setSingleton( new $themeClass() );
 
@@ -44,6 +44,7 @@
 <head>
        <meta charset="UTF-8">
        <title>OOjs UI Widget Demo</title>
+       <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="dist/<?php echo $styleFileName; ?>">
        <link rel="stylesheet" href="dist/<?php echo $styleFileNameImages; ?>">
        <link rel="stylesheet" href="dist/<?php echo $styleFileNameExtraIcons; 
?>">
diff --git a/oojs/oojs-ui/demos/index.html b/oojs/oojs-ui/demos/index.html
index 89c721f..cabe444 100644
--- a/oojs/oojs-ui/demos/index.html
+++ b/oojs/oojs-ui/demos/index.html
@@ -7,12 +7,15 @@
        <link rel="stylesheet" href="classes/ButtonStyleShowcaseWidget.css">
        <link rel="stylesheet" href="classes/FloatableTest.css">
        <link rel="stylesheet" href="classes/PositionSelectWidget.css">
+       <link rel="stylesheet" href="node_modules/prismjs/themes/prism.css">
 </head>
 <body>
        <script src="node_modules/jquery/dist/jquery.js"></script>
        <script src="node_modules/oojs/dist/oojs.jquery.js"></script>
+       <script src="node_modules/prismjs/prism.js"></script>
+       <script 
src="node_modules/prismjs/plugins/autolinker/prism-autolinker.js"></script>
        <script src="dist/oojs-ui.js"></script>
-       <script src="dist/oojs-ui-mediawiki.js"></script> <!-- Do not change 
this line or you'll break `grunt add-theme` -->
+       <script src="dist/oojs-ui-wikimediaui.js"></script> <!-- Do not change 
this line or you'll break `grunt add-theme` -->
        <script src="dist/oojs-ui-apex.js"></script>
        <script src="demo.js"></script>
        <script src="classes/ButtonStyleShowcaseWidget.js"></script>
diff --git a/oojs/oojs-ui/demos/pages/widgets.js 
b/oojs/oojs-ui/demos/pages/widgets.js
index 0c951a5..6f30c6b 100644
--- a/oojs/oojs-ui/demos/pages/widgets.js
+++ b/oojs/oojs-ui/demos/pages/widgets.js
@@ -6,6 +6,7 @@
                horizontalDragItems = [],
                verticalDragItems = [],
                verticalHandledDragItems = [],
+               $overlay = $( '<div>' ).addClass( 'demo-overlay' ).attr( 'id', 
'demo-overlay' ),
                $demo = demo.$element;
 
        for ( i = 0; i <= 12; i++ ) {
@@ -59,7 +60,8 @@
 
        fieldsets = [
                new OO.ui.FieldsetLayout( {
-                       label: 'Simple buttons',
+                       id: 'demo-section-buttons',
+                       label: 'Buttons',
                        items: [
                                new OO.ui.FieldLayout(
                                        new OO.ui.ButtonWidget( { label: 
'Normal' } ),
@@ -84,7 +86,7 @@
                                                flags: [ 'constructive' ]
                                        } ),
                                        {
-                                               label: 'ButtonWidget 
(constructive, deprecated in MediaWiki theme)\u200E',
+                                               label: 'ButtonWidget 
(constructive, deprecated in WikimediaUI theme)\u200E',
                                                align: 'top'
                                        }
                                ),
@@ -114,7 +116,7 @@
                                                flags: [ 'primary', 
'constructive' ]
                                        } ),
                                        {
-                                               label: 'ButtonWidget (primary, 
constructive, deprecated in MediaWiki theme)\u200E',
+                                               label: 'ButtonWidget (primary, 
constructive, deprecated in WikimediaUI theme)\u200E',
                                                align: 'top'
                                        }
                                ),
@@ -205,6 +207,17 @@
                                ),
                                new OO.ui.FieldLayout(
                                        new OO.ui.ButtonWidget( {
+                                               label: 'Accesskey: H',
+                                               accessKey: 'h'
+                                       } ),
+                                       {
+                                               label: 'ButtonWidget (with 
accesskey)\u200E',
+                                               align: 'top',
+                                               help: new OO.ui.HtmlSnippet( 
'Notice: Using `accesskey` might <a 
href="http://webaim.org/techniques/keyboard/accesskey"; 
target="_blank">negatively impact screen readers</a>!' )
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.ButtonWidget( {
                                                icon: 'help',
                                                title: 'Icon only, framed'
                                        } ),
@@ -284,7 +297,7 @@
                                        new OO.ui.ButtonWidget( {
                                                framed: false,
                                                flags: [ 'destructive' ],
-                                               icon: 'remove',
+                                               icon: 'trash',
                                                label: 'Destructive'
                                        } ),
                                        {
@@ -351,10 +364,95 @@
                                                label: 'ButtonWidget 
(frameless, indicator)\u200E',
                                                align: 'top'
                                        }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.ButtonInputWidget( {
+                                               label: 'Submit the form',
+                                               type: 'submit',
+                                               flags: [ 'primary', 
'progressive' ],
+                                               useInputTag: true
+                                       } ),
+                                       {
+                                               align: 'top',
+                                               label: 'ButtonInputWidget 
(using <input>)\u200E'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.ButtonInputWidget( {
+                                               label: 'Another button',
+                                               type: 'button'
+                                       } ),
+                                       {
+                                               align: 'top',
+                                               label: 'ButtonInputWidget 
(using <button>)\u200E'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.ButtonInputWidget( {
+                                               label: 'Accesskey: I',
+                                               accessKey: 'i'
+                                       } ),
+                                       {
+                                               label: 'ButtonInputWidget (with 
accesskey)\u200E',
+                                               align: 'top',
+                                               help: new OO.ui.HtmlSnippet( 
'Notice: Using `accesskey` might <a 
href="http://webaim.org/techniques/keyboard/accesskey"; 
target="_blank">negatively impact screen readers</a>!' )
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.ButtonInputWidget( {
+                                               framed: false,
+                                               label: 'Another button',
+                                               type: 'button'
+                                       } ),
+                                       {
+                                               align: 'top',
+                                               label: 'ButtonInputWidget 
(frameless)\u200E'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.ButtonInputWidget( {
+                                               framed: false,
+                                               label: 'Another button',
+                                               type: 'button',
+                                               useInputTag: true
+                                       } ),
+                                       {
+                                               align: 'top',
+                                               label: 'ButtonInputWidget 
(frameless, using <input>)\u200E'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.ToggleButtonWidget( { label: 
'Toggle' } ),
+                                       {
+                                               label: 'ToggleButtonWidget',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.ToggleButtonWidget( { label: 
'Toggle', value: true } ),
+                                       {
+                                               label: 'ToggleButtonWidget 
(initially active)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.ToggleButtonWidget( { icon: 
'next' } ),
+                                       {
+                                               label: 'ToggleButtonWidget 
(icon only)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.ToggleButtonWidget( { icon: 
'next', value: true } ),
+                                       {
+                                               label: 'ToggleButtonWidget 
(icon only, initially active)\u200E',
+                                               align: 'top'
+                                       }
                                )
                        ]
                } ),
                new OO.ui.FieldsetLayout( {
+                       id: 'demo-section-button-sets',
                        label: 'Button sets',
                        items: [
                                new OO.ui.FieldLayout(
@@ -508,10 +606,36 @@
                                                label: 'ButtonSelectWidget 
(disabled items)\u200E',
                                                align: 'top'
                                        }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.ButtonSelectWidget( {
+                                               items: [
+                                                       new 
OO.ui.ButtonOptionWidget( {
+                                                               data: 'a',
+                                                               label: 
'Accesskey: J',
+                                                               accessKey: 'j'
+                                                       } ),
+                                                       new 
OO.ui.ButtonOptionWidget( {
+                                                               data: 'b',
+                                                               label: 
'Accesskey: K',
+                                                               accessKey: 'k'
+                                                       } ),
+                                                       new 
OO.ui.ButtonOptionWidget( {
+                                                               data: 'c',
+                                                               label: 
'Accesskey: L',
+                                                               accessKey: 'l'
+                                                       } )
+                                               ]
+                                       } ),
+                                       {
+                                               label: 'ButtonSelectWidget 
(with accesskeys)\u200E',
+                                               align: 'top'
+                                       }
                                )
                        ]
                } ),
                new OO.ui.FieldsetLayout( {
+                       id: 'demo-section-button-showcase',
                        label: 'Button style showcase',
                        items: [
                                new OO.ui.FieldLayout(
@@ -523,7 +647,270 @@
                        ]
                } ),
                new OO.ui.FieldsetLayout( {
-                       label: 'Form widgets',
+                       id: 'demo-section-inputs',
+                       label: 'Inputs: TextInput, TextInput (multiline), 
SearchInput, NumberInput',
+                       items: [
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( { value: 
'Text input' } ),
+                                       {
+                                               label: 'TextInputWidget\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( { icon: 
'help' } ),
+                                       {
+                                               label: 'TextInputWidget 
(icon)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( {
+                                               required: true,
+                                               validate: 'non-empty'
+                                       } ),
+                                       {
+                                               label: 'TextInputWidget 
(required)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( {
+                                               validate: function ( value ) {
+                                                       return value.length % 2 
=== 0;
+                                               }
+                                       } ),
+                                       {
+                                               label: 'TextInputWidget (only 
allows even number of characters)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( { 
placeholder: 'Placeholder' } ),
+                                       {
+                                               label: 'TextInputWidget 
(placeholder)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( {
+                                               value: 'Title attribute',
+                                               title: 'Title attribute with 
more information about me.'
+                                       } ),
+                                       {
+                                               label: 'TextInputWidget (with 
title)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( {
+                                               value: 'Readonly',
+                                               readOnly: true
+                                       } ),
+                                       {
+                                               label: 'TextInputWidget 
(readonly)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( {
+                                               value: 'Disabled',
+                                               disabled: true
+                                       } ),
+                                       {
+                                               label: 'TextInputWidget 
(disabled)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( {
+                                               multiline: true,
+                                               value: 'Multiline\nMultiline'
+                                       } ),
+                                       {
+                                               label: 'TextInputWidget 
(multiline)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( {
+                                               multiline: true,
+                                               rows: 15,
+                                               value: 'Multiline\nMultiline'
+                                       } ),
+                                       {
+                                               label: 'TextInputWidget 
(multiline, rows=15)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( {
+                                               multiline: true,
+                                               autosize: true,
+                                               value: 
'Autosize\nAutosize\nAutosize\nAutosize'
+                                       } ),
+                                       {
+                                               label: 'TextInputWidget 
(autosize)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( {
+                                               multiline: true,
+                                               rows: 10,
+                                               autosize: true,
+                                               value: 
'Autosize\nAutosize\nAutosize\nAutosize'
+                                       } ),
+                                       {
+                                               label: 'TextInputWidget 
(autosize, rows=10)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( {
+                                               multiline: true,
+                                               autosize: true,
+                                               icon: 'tag',
+                                               indicator: 'alert',
+                                               label: 'Inline label',
+                                               value: 
'Autosize\nAutosize\nAutosize\nAutosize'
+                                       } ),
+                                       {
+                                               label: 'TextInputWidget 
(autosize, icon, indicator, label)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( {
+                                               value: 'Text input with label',
+                                               label: 'Inline label'
+                                       } ),
+                                       {
+                                               label: 'TextInputWidget 
(label)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( {
+                                               value: 'Text input with label',
+                                               label: 'Inline label',
+                                               labelPosition: 'before'
+                                       } ),
+                                       {
+                                               label: 'TextInputWidget 
(label[position=before])\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( {
+                                               icon: 'tag',
+                                               indicator: 'alert',
+                                               value: 'Text input with label',
+                                               label: 'Inline label'
+                                       } ),
+                                       {
+                                               label: 'TextInputWidget (icon, 
indicator, label)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( {
+                                               icon: 'tag',
+                                               indicator: 'alert',
+                                               value: 'Text input with label',
+                                               label: 'Inline label',
+                                               labelPosition: 'before'
+                                       } ),
+                                       {
+                                               label: 'TextInputWidget (icon, 
indicator, label[position=before])\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( {
+                                               value: 'Disabled',
+                                               icon: 'tag',
+                                               indicator: 'alert',
+                                               label: 'Inline label',
+                                               disabled: true
+                                       } ),
+                                       {
+                                               label: 'TextInputWidget (icon, 
indicator, label, disabled)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.TextInputWidget( {
+                                               value: 'Accesskey: S',
+                                               accessKey: 's'
+                                       } ),
+                                       {
+                                               label: 'TextInputWidget (with 
accesskey)\u200E',
+                                               align: 'top',
+                                               help: new OO.ui.HtmlSnippet( 
'Notice: Using `accesskey` might <a 
href="http://webaim.org/techniques/keyboard/accesskey"; 
target="_blank">negatively impact screen readers</a>!' )
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.SearchInputWidget(),
+                                       {
+                                               label: 'SearchInputWidget 
(type=search)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.SearchInputWidget( { 
disabled: true } ),
+                                       {
+                                               label: 'SearchInputWidget 
(disabled)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.SearchInputWidget( { 
disabled: true, value: 'test' } ),
+                                       {
+                                               label: 'SearchInputWidget 
(disabled, filled)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.NumberInputWidget(),
+                                       {
+                                               label: 'NumberInputWidget',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.NumberInputWidget( { 
disabled: true } ),
+                                       {
+                                               label: 'NumberInputWidget 
(disabled)',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.NumberInputWidget( { min: 1, 
max: 5, isInteger: true } ),
+                                       {
+                                               label: 'NumberInputWidget (1–5, 
ints only)',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.NumberInputWidget( { min: 0, 
max: 1, step: 0.1, pageStep: 0.25 } ),
+                                       {
+                                               label: 'NumberInputWidget (0–1, 
step by .1, page by .25)',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.NumberInputWidget( { 
showButtons: false } ),
+                                       {
+                                               label: 'NumberInputWidget (no 
buttons)',
+                                               align: 'top'
+                                       }
+                               )
+                       ]
+               } ),
+               new OO.ui.FieldsetLayout( {
+                       id: 'demo-section-inputs-binary',
+                       label: 'Checkbox, Radio & ToggleSwitch',
                        items: [
                                new OO.ui.FieldLayout(
                                        new OO.ui.CheckboxInputWidget( {
@@ -667,38 +1054,28 @@
                                        }
                                ),
                                new OO.ui.FieldLayout(
-                                       new OO.ui.NumberInputWidget(),
+                                       new OO.ui.RadioSelectWidget( {
+                                               items: [
+                                                       new 
OO.ui.RadioOptionWidget( {
+                                                               data: 'a',
+                                                               label: 
'Accesskey: M',
+                                                               accessKey: 'm'
+                                                       } ),
+                                                       new 
OO.ui.RadioOptionWidget( {
+                                                               data: 'b',
+                                                               label: 
'Accesskey: N',
+                                                               accessKey: 'n'
+                                                       } ),
+                                                       new 
OO.ui.RadioOptionWidget( {
+                                                               data: 'c',
+                                                               label: 
'Accesskey: O',
+                                                               accessKey: 'o'
+                                                       } )
+                                               ]
+                                       } ),
                                        {
-                                               label: 'NumberInputWidget',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.NumberInputWidget( { 
disabled: true } ),
-                                       {
-                                               label: 'NumberInputWidget 
(disabled)',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.NumberInputWidget( { min: 1, 
max: 5, isInteger: true } ),
-                                       {
-                                               label: 'NumberInputWidget (1–5, 
ints only)',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.NumberInputWidget( { min: 0, 
max: 1, step: 0.1, pageStep: 0.25 } ),
-                                       {
-                                               label: 'NumberInputWidget (0–1, 
step by .1, page by .25)',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.NumberInputWidget( { 
showButtons: false } ),
-                                       {
-                                               label: 'NumberInputWidget (no 
buttons)',
-                                               align: 'top'
+                                               align: 'top',
+                                               label: 'RadioSelectWidget (with 
accesskeys)\u200E'
                                        }
                                ),
                                new OO.ui.FieldLayout(
@@ -721,286 +1098,13 @@
                                                label: 'ToggleSwitchWidget 
(disabled, checked)\u200E',
                                                align: 'top'
                                        }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.ToggleButtonWidget( { label: 
'Toggle' } ),
-                                       {
-                                               label: 'ToggleButtonWidget',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.ToggleButtonWidget( { label: 
'Toggle', value: true } ),
-                                       {
-                                               label: 'ToggleButtonWidget 
(initially active)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.ToggleButtonWidget( { icon: 
'next' } ),
-                                       {
-                                               label: 'ToggleButtonWidget 
(icon only)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.ToggleButtonWidget( { icon: 
'next', value: true } ),
-                                       {
-                                               label: 'ToggleButtonWidget 
(icon only, initially active)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( { value: 
'Text input' } ),
-                                       {
-                                               label: 'TextInputWidget\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( { icon: 
'help' } ),
-                                       {
-                                               label: 'TextInputWidget 
(icon)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( {
-                                               required: true,
-                                               validate: 'non-empty'
-                                       } ),
-                                       {
-                                               label: 'TextInputWidget 
(required)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( {
-                                               validate: function ( value ) {
-                                                       return value.length % 2 
=== 0;
-                                               }
-                                       } ),
-                                       {
-                                               label: 'TextInputWidget (only 
allows even number of characters)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( { 
placeholder: 'Placeholder' } ),
-                                       {
-                                               label: 'TextInputWidget 
(placeholder)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( { type: 
'number' } ),
-                                       {
-                                               label: 'TextInputWidget 
(type=number)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( {
-                                               value: 'Readonly',
-                                               readOnly: true
-                                       } ),
-                                       {
-                                               label: 'TextInputWidget 
(readonly)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( {
-                                               value: 'Disabled',
-                                               disabled: true
-                                       } ),
-                                       {
-                                               label: 'TextInputWidget 
(disabled)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.SearchInputWidget(),
-                                       {
-                                               label: 'SearchInputWidget 
(type=search)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.SearchInputWidget( { 
disabled: true } ),
-                                       {
-                                               label: 'SearchInputWidget 
(disabled)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.SearchInputWidget( { 
disabled: true, value: 'test' } ),
-                                       {
-                                               label: 'SearchInputWidget 
(disabled, filled)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( {
-                                               multiline: true,
-                                               value: 'Multiline\nMultiline'
-                                       } ),
-                                       {
-                                               label: 'TextInputWidget 
(multiline)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( {
-                                               multiline: true,
-                                               rows: 15,
-                                               value: 'Multiline\nMultiline'
-                                       } ),
-                                       {
-                                               label: 'TextInputWidget 
(multiline, rows=15)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( {
-                                               multiline: true,
-                                               autosize: true,
-                                               value: 
'Autosize\nAutosize\nAutosize\nAutosize'
-                                       } ),
-                                       {
-                                               label: 'TextInputWidget 
(autosize)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( {
-                                               multiline: true,
-                                               rows: 10,
-                                               autosize: true,
-                                               value: 
'Autosize\nAutosize\nAutosize\nAutosize'
-                                       } ),
-                                       {
-                                               label: 'TextInputWidget 
(autosize, rows=10)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( {
-                                               multiline: true,
-                                               autosize: true,
-                                               icon: 'tag',
-                                               indicator: 'alert',
-                                               label: 'Inline label',
-                                               value: 
'Autosize\nAutosize\nAutosize\nAutosize'
-                                       } ),
-                                       {
-                                               label: 'TextInputWidget 
(autosize, icon, indicator, label)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( {
-                                               icon: 'tag',
-                                               indicator: 'alert',
-                                               value: 'Text input with label',
-                                               label: 'Inline label'
-                                       } ),
-                                       {
-                                               label: 'TextInputWidget (icon, 
indicator, label)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( {
-                                               value: 'Disabled',
-                                               icon: 'tag',
-                                               indicator: 'alert',
-                                               label: 'Inline label',
-                                               disabled: true
-                                       } ),
-                                       {
-                                               label: 'TextInputWidget (icon, 
indicator, label, disabled)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( {
-                                               value: 'Title attribute',
-                                               title: 'Title attribute with 
more information about me.'
-                                       } ),
-                                       {
-                                               label: 'TextInputWidget (with 
title)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.SelectFileWidget( {} ),
-                                       {
-                                               label: 'SelectFileWidget\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.SelectFileWidget( { accept: [ 
'image/png', 'image/jpeg' ] } ),
-                                       {
-                                               label: 'SelectFileWidget 
(accept PNG and JPEG)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.SelectFileWidget( {
-                                               icon: 'tag',
-                                               indicator: 'alert'
-                                       } ),
-                                       {
-                                               label: 'SelectFileWidget (icon, 
indicator)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.SelectFileWidget( {
-                                               icon: 'tag',
-                                               indicator: 'alert',
-                                               disabled: true
-                                       } ),
-                                       {
-                                               label: 'SelectFileWidget 
(disabled)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new Demo.UnsupportedSelectFileWidget(),
-                                       {
-                                               label: 'SelectFileWidget (no 
browser support)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.SelectFileWidget( { 
showDropTarget: true } ),
-                                       {
-                                               label: 'SelectFileWidget (with 
drop target)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.SelectFileWidget( {
-                                               showDropTarget: true,
-                                               disabled: true
-                                       } ),
-                                       {
-                                               label: 'SelectFileWidget (with 
drop target, disabled)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new Demo.UnsupportedSelectFileWidget( {
-                                               showDropTarget: true
-                                       } ),
-                                       {
-                                               label: 'SelectFileWidget (with 
drop target, no browser support)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
+                               )
+                       ]
+               } ),
+               new OO.ui.FieldsetLayout( {
+                       id: 'demo-section-dropdown',
+                       label: 'Dropdown',
+                       items: [
                                new OO.ui.FieldLayout(
                                        new OO.ui.DropdownWidget( {
                                                label: 'Select one',
@@ -1138,7 +1242,7 @@
                                new OO.ui.FieldLayout(
                                        new OO.ui.DropdownWidget( {
                                                label: 'Select one',
-                                               $overlay: $( '<div>' 
).appendTo( 'body' ).css( { position: 'absolute', top: 0, left: 0 } ),
+                                               $overlay: $overlay,
                                                menu: {
                                                        items: [
                                                                new 
OO.ui.MenuOptionWidget( {
@@ -1193,6 +1297,33 @@
                                        {
                                                label: 'DropdownWidget (does 
not close on choose)\u200E',
                                                align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.DropdownWidget( {
+                                               menu: {
+                                                       items: [
+                                                               new 
OO.ui.MenuOptionWidget( {
+                                                                       data: 
'a',
+                                                                       label: 
'Accesskey: P',
+                                                                       
accessKey: 'p'
+                                                               } ),
+                                                               new 
OO.ui.MenuOptionWidget( {
+                                                                       data: 
'b',
+                                                                       label: 
'Accesskey: Q',
+                                                                       
accessKey: 'q'
+                                                               } ),
+                                                               new 
OO.ui.MenuOptionWidget( {
+                                                                       data: 
'c',
+                                                                       label: 
'Accesskey: R',
+                                                                       
accessKey: 'r'
+                                                               } )
+                                                       ]
+                                               }
+                                       } ),
+                                       {
+                                               align: 'top',
+                                               label: 'DropdownWidget (with 
accesskeys)\u200E'
                                        }
                                ),
                                new OO.ui.FieldLayout(
@@ -1304,7 +1435,13 @@
                                                label: 'DropdownInputWidget 
(long)\u200E',
                                                align: 'top'
                                        }
-                               ),
+                               )
+                       ]
+               } ),
+               new OO.ui.FieldsetLayout( {
+                       id: 'demo-section-comboBox',
+                       label: 'ComboBox',
+                       items: [
                                new OO.ui.FieldLayout(
                                        new OO.ui.ComboBoxInputWidget( {
                                                options: [
@@ -1395,7 +1532,87 @@
                                                label: 'ComboBoxInputWidget 
(empty)\u200E',
                                                align: 'top'
                                        }
+                               )
+                       ]
+               } ),
+               new OO.ui.FieldsetLayout( {
+                       id: 'demo-section-selectFile',
+                       label: 'SelectFile',
+                       items: [
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.SelectFileWidget( {} ),
+                                       {
+                                               label: 'SelectFileWidget\u200E',
+                                               align: 'top'
+                                       }
                                ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.SelectFileWidget( { accept: [ 
'image/png', 'image/jpeg' ] } ),
+                                       {
+                                               label: 'SelectFileWidget 
(accept PNG and JPEG)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.SelectFileWidget( {
+                                               icon: 'tag',
+                                               indicator: 'alert'
+                                       } ),
+                                       {
+                                               label: 'SelectFileWidget (icon, 
indicator)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.SelectFileWidget( {
+                                               icon: 'tag',
+                                               indicator: 'alert',
+                                               disabled: true
+                                       } ),
+                                       {
+                                               label: 'SelectFileWidget 
(disabled)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new Demo.UnsupportedSelectFileWidget(),
+                                       {
+                                               label: 'SelectFileWidget (no 
browser support)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.SelectFileWidget( { 
showDropTarget: true } ),
+                                       {
+                                               label: 'SelectFileWidget (with 
drop target)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.SelectFileWidget( {
+                                               showDropTarget: true,
+                                               disabled: true
+                                       } ),
+                                       {
+                                               label: 'SelectFileWidget (with 
drop target, disabled)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new Demo.UnsupportedSelectFileWidget( {
+                                               showDropTarget: true
+                                       } ),
+                                       {
+                                               label: 'SelectFileWidget (with 
drop target, no browser support)\u200E',
+                                               align: 'top'
+                                       }
+                               )
+                       ]
+               } ),
+               new OO.ui.FieldsetLayout( {
+                       id: 'demo-section-tagMultiselect',
+                       label: 'TagMultiselect, MenuTagMultiselect, 
CapsuleMultiselect',
+                       items: [
                                new OO.ui.FieldLayout(
                                        new OO.ui.TagMultiselectWidget( {
                                                placeholder: 'Add tags',
@@ -1463,6 +1680,33 @@
                                ),
                                new OO.ui.FieldLayout(
                                        new OO.ui.MenuTagMultiselectWidget( {
+                                               selected: [
+                                                       { data: 'foo', label: 
'Label for foo' },
+                                                       { data: 'bar', label: 
'Label for bar' }
+                                               ],
+                                               options: [
+                                                       { data: 'foo', label: 
'Label for foo' },
+                                                       { data: 'bar', label: 
'Label for bar' },
+                                                       { data: 'baz', label: 
'Label for baz' }
+                                               ]
+                                       } ),
+                                       {
+                                               label: 
'MenuTagMultiselectWidget (initially selected, preset options)',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.MenuTagMultiselectWidget( {
+                                               selected: [ 'foo', 'bar' ],
+                                               allowArbitrary: true
+                                       } ),
+                                       {
+                                               label: 
'MenuTagMultiselectWidget (initially selected, allowArbitrary)',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.MenuTagMultiselectWidget( {
                                                allowArbitrary: false,
                                                options: [
                                                        { data: 'abc', label: 
'Label for abc' },
@@ -1510,7 +1754,7 @@
                                ),
                                new OO.ui.FieldLayout(
                                        new OO.ui.CapsuleMultiselectWidget( {
-                                               placeholder: 'Type like a 
cat...',
+                                               placeholder: 'Type like a cat…',
                                                menu: {
                                                        items: [
                                                                new 
OO.ui.MenuOptionWidget( { data: 'abc', label: 'Label for abc' } ),
@@ -1627,340 +1871,35 @@
                                                label: 
'CapsuleMultiselectWidget with NumberInputWidget popup\u200E',
                                                align: 'top'
                                        }
-                               ),
+                               )
+                       ]
+               } ),
+               new OO.ui.FieldsetLayout( {
+                       id: 'demo-section-lookupElement',
+                       label: 'LookupElement',
+                       items: [
                                new OO.ui.FieldLayout(
-                                       new OO.ui.ButtonInputWidget( {
-                                               label: 'Submit the form',
-                                               type: 'submit',
-                                               flags: [ 'primary', 
'progressive' ],
-                                               useInputTag: true
-                                       } ),
+                                       new Demo.NumberLookupTextInputWidget(),
                                        {
-                                               align: 'top',
-                                               label: 'ButtonInputWidget 
(using <input>)\u200E'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.ButtonInputWidget( {
-                                               label: 'Another button',
-                                               type: 'button'
-                                       } ),
-                                       {
-                                               align: 'top',
-                                               label: 'ButtonInputWidget 
(using <button>)\u200E'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.ButtonInputWidget( {
-                                               framed: false,
-                                               label: 'Another button',
-                                               type: 'button'
-                                       } ),
-                                       {
-                                               align: 'top',
-                                               label: 'ButtonInputWidget 
(frameless)\u200E'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.ButtonInputWidget( {
-                                               framed: false,
-                                               label: 'Another button',
-                                               type: 'button',
-                                               useInputTag: true
-                                       } ),
-                                       {
-                                               align: 'top',
-                                               label: 'ButtonInputWidget 
(frameless, using <input>)\u200E'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.ButtonWidget( {
-                                               label: 'Accesskey: H',
-                                               accessKey: 'h'
-                                       } ),
-                                       {
-                                               label: 'ButtonWidget (with 
accesskey)\u200E',
+                                               label: 'LookupElement (try 
inputting an integer)\u200E',
                                                align: 'top'
                                        }
                                ),
                                new OO.ui.FieldLayout(
-                                       new OO.ui.ButtonInputWidget( {
-                                               label: 'Accesskey: I',
-                                               accessKey: 'i'
+                                       new Demo.NumberLookupTextInputWidget( {
+                                               highlightFirst: false
                                        } ),
                                        {
-                                               label: 'ButtonInputWidget (with 
accesskey)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.ButtonSelectWidget( {
-                                               items: [
-                                                       new 
OO.ui.ButtonOptionWidget( {
-                                                               data: 'a',
-                                                               label: 
'Accesskey: J',
-                                                               accessKey: 'j'
-                                                       } ),
-                                                       new 
OO.ui.ButtonOptionWidget( {
-                                                               data: 'b',
-                                                               label: 
'Accesskey: K',
-                                                               accessKey: 'k'
-                                                       } ),
-                                                       new 
OO.ui.ButtonOptionWidget( {
-                                                               data: 'c',
-                                                               label: 
'Accesskey: L',
-                                                               accessKey: 'l'
-                                                       } )
-                                               ]
-                                       } ),
-                                       {
-                                               label: 'ButtonSelectWidget 
(with accesskeys)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.RadioSelectWidget( {
-                                               items: [
-                                                       new 
OO.ui.RadioOptionWidget( {
-                                                               data: 'a',
-                                                               label: 
'Accesskey: M',
-                                                               accessKey: 'm'
-                                                       } ),
-                                                       new 
OO.ui.RadioOptionWidget( {
-                                                               data: 'b',
-                                                               label: 
'Accesskey: N',
-                                                               accessKey: 'n'
-                                                       } ),
-                                                       new 
OO.ui.RadioOptionWidget( {
-                                                               data: 'c',
-                                                               label: 
'Accesskey: O',
-                                                               accessKey: 'o'
-                                                       } )
-                                               ]
-                                       } ),
-                                       {
-                                               align: 'top',
-                                               label: 'RadioSelectWidget (with 
accesskeys)\u200E'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.DropdownWidget( {
-                                               menu: {
-                                                       items: [
-                                                               new 
OO.ui.MenuOptionWidget( {
-                                                                       data: 
'a',
-                                                                       label: 
'Accesskey: P',
-                                                                       
accessKey: 'p'
-                                                               } ),
-                                                               new 
OO.ui.MenuOptionWidget( {
-                                                                       data: 
'b',
-                                                                       label: 
'Accesskey: Q',
-                                                                       
accessKey: 'q'
-                                                               } ),
-                                                               new 
OO.ui.MenuOptionWidget( {
-                                                                       data: 
'c',
-                                                                       label: 
'Accesskey: R',
-                                                                       
accessKey: 'r'
-                                                               } )
-                                                       ]
-                                               }
-                                       } ),
-                                       {
-                                               align: 'top',
-                                               label: 'DropdownWidget (with 
accesskeys)\u200E'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.TextInputWidget( {
-                                               value: 'Accesskey: S',
-                                               accessKey: 's'
-                                       } ),
-                                       {
-                                               label: 'TextInputWidget (with 
accesskey)\u200E',
+                                               label: 'LookupElement without 
highlighting 1st term (try inputting an integer)\u200E',
                                                align: 'top'
                                        }
                                )
                        ]
                } ),
                new OO.ui.FieldsetLayout( {
-                       label: 'HorizontalLayout',
+                       id: 'demo-section-popupButton',
+                       label: 'PopupButton',
                        items: [
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.Widget( {
-                                               content: [ new 
OO.ui.HorizontalLayout( {
-                                                       items: [
-                                                               new 
OO.ui.ButtonWidget( { label: 'Button' } ),
-                                                               new 
OO.ui.ButtonGroupWidget( { items: [
-                                                                       new 
OO.ui.ToggleButtonWidget( { label: 'A' } ),
-                                                                       new 
OO.ui.ToggleButtonWidget( { label: 'B' } )
-                                                               ] } ),
-                                                               new 
OO.ui.ButtonInputWidget( { label: 'ButtonInput' } ),
-                                                               new 
OO.ui.TextInputWidget( { value: 'TextInput' } ),
-                                                               new 
OO.ui.DropdownInputWidget( { options: [
-                                                                       {
-                                                                               
label: 'DropdownInput',
-                                                                               
data: null
-                                                                       }
-                                                               ] } ),
-                                                               new 
OO.ui.CheckboxInputWidget( { selected: true } ),
-                                                               new 
OO.ui.RadioInputWidget( { selected: true } ),
-                                                               new 
OO.ui.LabelWidget( { label: 'Label' } )
-                                                       ]
-                                               } ) ]
-                                       } ),
-                                       {
-                                               label: 'Multiple widgets shown 
as a single line, ' +
-                                                       'as used in compact 
forms or in parts of a bigger widget.',
-                                               align: 'top'
-                                       }
-                               )
-                       ]
-               } ),
-               new OO.ui.FieldsetLayout( {
-                       label: 'Draggable',
-                       items: [
-                               new OO.ui.FieldLayout(
-                                       new Demo.DraggableGroupWidget( {
-                                               orientation: 'horizontal',
-                                               items: horizontalDragItems
-                                       } ),
-                                       {
-                                               label: 'DraggableGroupWidget 
(horizontal)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new Demo.DraggableGroupWidget( {
-                                               items: verticalDragItems
-                                       } ),
-                                       {
-                                               label: 'DraggableGroupWidget 
(vertical)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new Demo.DraggableGroupWidget( {
-                                               items: verticalHandledDragItems
-                                       } ),
-                                       {
-                                               label: 'DraggableGroupWidget 
with handles (vertical)\u200E',
-                                               align: 'top'
-                                       }
-                               )
-                       ]
-               } ),
-               new OO.ui.FieldsetLayout( {
-                       label: 'Other widgets',
-                       items: [
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.IconWidget( {
-                                               icon: 'search',
-                                               title: 'Search icon'
-                                       } ),
-                                       {
-                                               label: 'IconWidget 
(normal)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.IconWidget( {
-                                               icon: 'remove',
-                                               flags: 'destructive',
-                                               title: 'Remove icon'
-                                       } ),
-                                       {
-                                               label: 'IconWidget 
(flagged)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.IconWidget( {
-                                               icon: 'search',
-                                               title: 'Search icon',
-                                               disabled: true
-                                       } ),
-                                       {
-                                               label: 'IconWidget 
(disabled)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.IndicatorWidget( {
-                                               indicator: 'alert',
-                                               title: 'Required indicator'
-                                       } ),
-                                       {
-                                               label: 'IndicatorWidget 
(normal)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.IndicatorWidget( {
-                                               indicator: 'alert',
-                                               title: 'Required indicator',
-                                               disabled: true
-                                       } ),
-                                       {
-                                               label: 'IndicatorWidget 
(disabled)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.LabelWidget( {
-                                               label: 'Label'
-                                       } ),
-                                       {
-                                               label: 'LabelWidget 
(normal)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.LabelWidget( {
-                                               label: 'Label',
-                                               disabled: true
-                                       } ),
-                                       {
-                                               label: 'LabelWidget 
(disabled)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new OO.ui.LabelWidget( {
-                                               label: new OO.ui.HtmlSnippet( 
'<b>Fancy</b> <i>text</i> <u>formatting</u>!' )
-                                       } ),
-                                       {
-                                               label: 'LabelWidget (with 
HTML)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       labelForTextInput,
-                                       {
-                                               label: 'LabelWidget (with an 
associated TextInputWidget)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       textInputForLabel,
-                                       {
-                                               label: 'TextInputWidget (with 
an associated label)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       labelForRadioSelectInput,
-                                       {
-                                               label: 'LabelWidget (with an 
associated RadioSelectInputWidget)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       radioSelectInputForLabel,
-                                       {
-                                               label: 'RadioSelectInputWidget 
(with an associated label)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
                                new OO.ui.FieldLayout(
                                        new OO.ui.PopupButtonWidget( {
                                                icon: 'info',
@@ -2164,30 +2103,87 @@
                                                popup: {
                                                        $content: $( '<p>' 
).text( loremIpsum ),
                                                        padded: true,
-                                                       anchor: false
+                                                       anchor: false,
+                                                       align: 'center'
                                                }
                                        } ),
                                        {
-                                               label: 'PopupButtonWidget (no 
anchor)\u200E',
+                                               label: 'PopupButtonWidget (no 
anchor, align: center)\u200E',
                                                align: 'top'
                                        }
                                ),
                                new OO.ui.FieldLayout(
-                                       new Demo.NumberLookupTextInputWidget(),
-                                       {
-                                               label: 'LookupElement (try 
inputting an integer)\u200E',
-                                               align: 'top'
-                                       }
-                               ),
-                               new OO.ui.FieldLayout(
-                                       new Demo.NumberLookupTextInputWidget( {
-                                               highlightFirst: false
+                                       new OO.ui.PopupButtonWidget( {
+                                               icon: 'menu',
+                                               label: 'Options',
+                                               popup: {
+                                                       $content: $( '<p>' 
).text( loremIpsum ),
+                                                       padded: true,
+                                                       anchor: false,
+                                                       align: 'forwards'
+                                               }
                                        } ),
                                        {
-                                               label: 'LookupElement without 
highlighting 1st term (try inputting an integer)\u200E',
+                                               label: 'PopupButtonWidget (no 
anchor, align: forwards)\u200E',
                                                align: 'top'
                                        }
                                ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.PopupButtonWidget( {
+                                               icon: 'menu',
+                                               label: 'Options',
+                                               popup: {
+                                                       $content: $( '<p>' 
).text( loremIpsum ),
+                                                       padded: true,
+                                                       anchor: false,
+                                                       align: 'backwards'
+                                               }
+                                       } ),
+                                       {
+                                               label: 'PopupButtonWidget (no 
anchor, align: backwards)\u200E',
+                                               align: 'top'
+                                       }
+                               )
+                       ]
+               } ),
+               new OO.ui.FieldsetLayout( {
+                       id: 'demo-section-draggable',
+                       label: 'Draggable',
+                       items: [
+                               new OO.ui.FieldLayout(
+                                       new Demo.DraggableGroupWidget( {
+                                               orientation: 'horizontal',
+                                               items: horizontalDragItems
+                                       } ),
+                                       {
+                                               label: 'DraggableGroupWidget 
(horizontal)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new Demo.DraggableGroupWidget( {
+                                               items: verticalDragItems
+                                       } ),
+                                       {
+                                               label: 'DraggableGroupWidget 
(vertical)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new Demo.DraggableGroupWidget( {
+                                               items: verticalHandledDragItems
+                                       } ),
+                                       {
+                                               label: 'DraggableGroupWidget 
with handles (vertical)\u200E',
+                                               align: 'top'
+                                       }
+                               )
+                       ]
+               } ),
+               new OO.ui.FieldsetLayout( {
+                       id: 'demo-section-progressBar',
+                       label: 'Progress bar',
+                       items: [
                                new OO.ui.FieldLayout(
                                        new OO.ui.ProgressBarWidget( {
                                                progress: 33
@@ -2199,6 +2195,7 @@
                                ),
                                new OO.ui.FieldLayout(
                                        new OO.ui.ProgressBarWidget( {
+                                               progress: 50,
                                                disabled: true
                                        } ),
                                        {
@@ -2218,6 +2215,122 @@
                        ]
                } ),
                new OO.ui.FieldsetLayout( {
+                       id: 'demo-section-others',
+                       label: 'Other widgets',
+                       items: [
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.IconWidget( {
+                                               icon: 'search',
+                                               title: 'Search icon'
+                                       } ),
+                                       {
+                                               label: 'IconWidget 
(normal)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.IconWidget( {
+                                               icon: 'trash',
+                                               flags: 'destructive',
+                                               title: 'Remove icon'
+                                       } ),
+                                       {
+                                               label: 'IconWidget 
(flagged)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.IconWidget( {
+                                               icon: 'search',
+                                               title: 'Search icon',
+                                               disabled: true
+                                       } ),
+                                       {
+                                               label: 'IconWidget 
(disabled)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.IndicatorWidget( {
+                                               indicator: 'alert',
+                                               title: 'Required indicator'
+                                       } ),
+                                       {
+                                               label: 'IndicatorWidget 
(normal)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.IndicatorWidget( {
+                                               indicator: 'alert',
+                                               title: 'Required indicator',
+                                               disabled: true
+                                       } ),
+                                       {
+                                               label: 'IndicatorWidget 
(disabled)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.LabelWidget( {
+                                               label: 'Label'
+                                       } ),
+                                       {
+                                               label: 'LabelWidget 
(normal)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.LabelWidget( {
+                                               label: 'Label',
+                                               disabled: true
+                                       } ),
+                                       {
+                                               label: 'LabelWidget 
(disabled)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.LabelWidget( {
+                                               label: new OO.ui.HtmlSnippet( 
'<b>Fancy</b> <i>text</i> <u>formatting</u>!' )
+                                       } ),
+                                       {
+                                               label: 'LabelWidget (with 
HTML)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       labelForTextInput,
+                                       {
+                                               label: 'LabelWidget (with an 
associated TextInputWidget)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       textInputForLabel,
+                                       {
+                                               label: 'TextInputWidget (with 
an associated label)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       labelForRadioSelectInput,
+                                       {
+                                               label: 'LabelWidget (with an 
associated RadioSelectInputWidget)\u200E',
+                                               align: 'top'
+                                       }
+                               ),
+                               new OO.ui.FieldLayout(
+                                       radioSelectInputForLabel,
+                                       {
+                                               label: 'RadioSelectInputWidget 
(with an associated label)\u200E',
+                                               align: 'top'
+                                       }
+                               )
+                       ]
+               } ),
+               new OO.ui.FieldsetLayout( {
+                       id: 'demo-section-fieldLayouts',
                        label: 'Field layouts',
                        icon: 'tag',
                        help: loremIpsum,
@@ -2410,11 +2523,47 @@
                                )
                        ]
                } ),
+               new OO.ui.FieldsetLayout( {
+                       id: 'demo-section-horizontalLayout',
+                       label: 'HorizontalLayout',
+                       items: [
+                               new OO.ui.FieldLayout(
+                                       new OO.ui.Widget( {
+                                               content: [ new 
OO.ui.HorizontalLayout( {
+                                                       items: [
+                                                               new 
OO.ui.ButtonWidget( { label: 'Button' } ),
+                                                               new 
OO.ui.ButtonGroupWidget( { items: [
+                                                                       new 
OO.ui.ToggleButtonWidget( { label: 'A' } ),
+                                                                       new 
OO.ui.ToggleButtonWidget( { label: 'B' } )
+                                                               ] } ),
+                                                               new 
OO.ui.ButtonInputWidget( { label: 'ButtonInput' } ),
+                                                               new 
OO.ui.TextInputWidget( { value: 'TextInput' } ),
+                                                               new 
OO.ui.DropdownInputWidget( { options: [
+                                                                       {
+                                                                               
label: 'DropdownInput',
+                                                                               
data: null
+                                                                       }
+                                                               ] } ),
+                                                               new 
OO.ui.CheckboxInputWidget( { selected: true } ),
+                                                               new 
OO.ui.RadioInputWidget( { selected: true } ),
+                                                               new 
OO.ui.LabelWidget( { label: 'Label' } )
+                                                       ]
+                                               } ) ]
+                                       } ),
+                                       {
+                                               label: 'Multiple widgets shown 
as a single line, ' +
+                                                       'as used in compact 
forms or in parts of a bigger widget.',
+                                               align: 'top'
+                                       }
+                               )
+                       ]
+               } ),
                new OO.ui.FormLayout( {
                        method: 'GET',
                        action: 'demos.php',
                        items: [
                                new OO.ui.FieldsetLayout( {
+                                       id: 'demo-section-formLayout',
                                        label: 'Form layout (compounded 
example)',
                                        items: [
                                                new OO.ui.FieldLayout(
@@ -2512,6 +2661,18 @@
                                                                label: 
'Remember me',
                                                                align: 'inline'
                                                        }
+                                               ),
+                                               new OO.ui.FieldLayout(
+                                                       new 
OO.ui.HiddenInputWidget( {
+                                                               name: 'hidden',
+                                                               value: 'hidden 
value'
+                                                       } )
+                                               ),
+                                               new OO.ui.FieldLayout(
+                                                       new 
OO.ui.ButtonInputWidget( {
+                                                               type: 'submit',
+                                                               label: 'Submit 
form'
+                                                       } )
                                                )
                                        ]
                                } ),
@@ -2545,6 +2706,11 @@
                                                                                
        framed: false,
                                                                                
        icon: 'tag',
                                                                                
        label: 'Random icon button'
+                                                                               
} ),
+                                                                               
new OO.ui.ButtonWidget( {
+                                                                               
        framed: false,
+                                                                               
        icon: 'help',
+                                                                               
        title: 'Icon only'
                                                                                
} )
                                                                        ]
                                                                } ) ]
@@ -2568,9 +2734,18 @@
        ];
 
        $.each( fieldsets, function ( i, fieldsetLayout ) {
+               var showLayoutCode = false;
+
+               if (
+                       fieldsetLayout instanceof OO.ui.FormLayout ||
+                       fieldsetLayout.getLabel() === 'Field layouts'
+               ) {
+                       showLayoutCode = true;
+               }
+
                $.each( fieldsetLayout.getItems(), function ( j, fieldLayout ) {
                        fieldLayout.$element.append(
-                               demo.buildConsole( fieldLayout, 'layout', 
'widget' )
+                               demo.buildConsole( fieldLayout, 'layout', 
'widget', showLayoutCode )
                        );
                } );
        } );
@@ -2586,4 +2761,10 @@
                                $( fieldsets.map( function ( fieldset ) { 
return fieldset.$element[ 0 ]; } ) )
                        )
        );
+
+       $overlay.appendTo( 'body' );
+
+       demo.once( 'destroy', function () {
+               $overlay.remove();
+       } );
 };
diff --git a/oojs/oojs-ui/demos/pages/widgets.php 
b/oojs/oojs-ui/demos/pages/widgets.php
index 44b6b48..d6b13db 100644
--- a/oojs/oojs-ui/demos/pages/widgets.php
+++ b/oojs/oojs-ui/demos/pages/widgets.php
@@ -12,11 +12,13 @@
        'padded' => true,
        'framed' => true,
 ] );
+
 $demoContainer->addClasses( [ 'demo-container' ] );
 
 $demoContainer->appendContent( new OOUI\FieldsetLayout( [
+       'id' => 'demo-section-buttons',
        'infusable' => true,
-       'label' => 'Simple buttons',
+       'label' => 'Buttons',
        'items' => [
                new OOUI\FieldLayout(
                        new OOUI\ButtonWidget( [ 'label' => 'Normal' ] ),
@@ -254,9 +256,79 @@
                                'align' => 'top'
                        ]
                ),
+               new OOUI\FieldLayout(
+                       new OOUI\ButtonInputWidget( [
+                               'label' => 'Submit the form',
+                               'type' => 'submit',
+                               'flags' => [ 'primary', 'progressive' ],
+                               'useInputTag' => true
+                       ] ),
+                       [
+                               'align' => 'top',
+                               'label' => "ButtonInputWidget (using 
<input>)\xE2\x80\x8E"
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\ButtonInputWidget( [
+                               'label' => 'Another button',
+                               'type' => 'button'
+                       ] ),
+                       [
+                               'align' => 'top',
+                               'label' => "ButtonInputWidget (using 
<button>)\xE2\x80\x8E"
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\ButtonInputWidget( [
+                               'framed' => false,
+                               'label' => 'Another button',
+                               'type' => 'button'
+                       ] ),
+                       [
+                               'align' => 'top',
+                               'label' => "ButtonInputWidget 
(frameless)\xE2\x80\x8E"
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\ButtonInputWidget( [
+                               'framed' => false,
+                               'label' => 'Another button',
+                               'type' => 'button',
+                               'useInputTag' => true
+                       ] ),
+                       [
+                               'align' => 'top',
+                               'label' => "ButtonInputWidget (frameless, using 
<input>)\xE2\x80\x8E"
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\ButtonWidget( [
+                               'label' => 'Accesskey: H',
+                               'accessKey' => 'h'
+                       ] ),
+                       [
+                               'label' => "ButtonWidget (with 
accesskey)\xE2\x80\x8E",
+                               'align' => 'top',
+                               'help' => new OOUI\HtmlSnippet( 'Notice: Using 
`accesskey` might '  .
+                                       '<a 
href="http://webaim.org/techniques/keyboard/accesskey"; target="_blank">' .
+                                       'negatively impact screen readers</a>!' 
)
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\ButtonInputWidget( [
+                               'label' => 'Accesskey: I',
+                               'accessKey' => 'i'
+                       ] ),
+                       [
+                               'label' => "ButtonInputWidget (with 
accesskey)\xE2\x80\x8E",
+                               'align' => 'top'
+                       ]
+               )
        ]
 ] ) );
+
 $demoContainer->appendContent( new OOUI\FieldsetLayout( [
+       'id' => 'demo-section-button-sets',
        'infusable' => true,
        'label' => 'Button sets',
        'items' => [
@@ -283,7 +355,9 @@
                )
        ]
 ] ) );
+
 $demoContainer->appendContent( new OOUI\FieldsetLayout( [
+       'id' => 'demo-section-button-showcase',
        'infusable' => true,
        'label' => 'Button style showcase',
        'items' => [
@@ -293,11 +367,134 @@
                                'align' => 'top',
                        ]
                )
-       ],
+       ]
 ] ) );
+
 $demoContainer->appendContent( new OOUI\FieldsetLayout( [
+       'id' => 'demo-section-inputs',
        'infusable' => true,
-       'label' => 'Form widgets',
+       'label' => 'TextInput',
+       'items' => [
+               new OOUI\FieldLayout(
+                       new OOUI\TextInputWidget( [ 'value' => 'Text input' ] ),
+                       [
+                               'label' => "TextInputWidget\xE2\x80\x8E",
+                               'align' => 'top'
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\TextInputWidget( [ 'icon' => 'help' ] ),
+                       [
+                               'label' => "TextInputWidget (icon)\xE2\x80\x8E",
+                               'align' => 'top'
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\TextInputWidget( [
+                               'required' => true
+                       ] ),
+                       [
+                               'label' => "TextInputWidget 
(required)\xE2\x80\x8E",
+                               'align' => 'top'
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\TextInputWidget( [ 'placeholder' => 
'Placeholder' ] ),
+                       [
+                               'label' => "TextInputWidget 
(placeholder)\xE2\x80\x8E",
+                               'align' => 'top'
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\TextInputWidget( [
+                               'value' => 'Title attribute',
+                               'title' => 'Title attribute with more 
information about me.'
+                       ] ),
+                       [
+                               'label' => "TextInputWidget (with 
title)\xE2\x80\x8E",
+                               'align' => 'top'
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\TextInputWidget( [ 'type' => 'search' ] ),
+                       [
+                               'label' => "TextInputWidget 
(type=search)\xE2\x80\x8E",
+                               'align' => 'top'
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\TextInputWidget( [
+                               'value' => 'Accesskey: S',
+                               'accessKey' => 's'
+                       ] ),
+                       [
+                               'label' => "TextInputWidget (with 
accesskey)\xE2\x80\x8E",
+                               'align' => 'top',
+                               'help' => new OOUI\HtmlSnippet( 'Notice: Using 
`accesskey` might '  .
+                                       '<a 
href="http://webaim.org/techniques/keyboard/accesskey"; target="_blank">' .
+                                       'negatively impact screen readers</a>!' 
)
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\TextInputWidget( [
+                               'value' => 'Readonly',
+                               'readOnly' => true
+                       ] ),
+                       [
+                               'label' => "TextInputWidget 
(readonly)\xE2\x80\x8E",
+                               'align' => 'top'
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\TextInputWidget( [
+                               'value' => 'Disabled',
+                               'disabled' => true
+                       ] ),
+                       [
+                               'label' => "TextInputWidget 
(disabled)\xE2\x80\x8E",
+                               'align' => 'top'
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\TextInputWidget( [
+                               'multiline' => true,
+                               'value' => "Multiline\nMultiline"
+                       ] ),
+                       [
+                               'label' => "TextInputWidget 
(multiline)\xE2\x80\x8E",
+                               'align' => 'top'
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\TextInputWidget( [
+                               'multiline' => true,
+                               'rows' => 15,
+                               'value' => "Multiline\nMultiline"
+                       ] ),
+                       [
+                               'label' => "TextInputWidget (multiline, 
rows=15)\xE2\x80\x8E",
+                               'align' => 'top'
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\TextInputWidget( [
+                               'multiline' => true,
+                               'value' => "Multiline\nMultiline",
+                               'icon' => 'tag',
+                               'indicator' => 'required'
+                       ] ),
+                       [
+                               'label' => "TextInputWidget (multiline, icon, 
indicator)\xE2\x80\x8E",
+                               'align' => 'top'
+                       ]
+               )
+       ]
+] ) );
+
+$demoContainer->appendContent( new OOUI\FieldsetLayout( [
+       'id' => 'demo-section-inputs-binary',
+       'infusable' => true,
+       'label' => 'Checkbox & Radio',
        'items' => [
                new OOUI\FieldLayout(
                        new OOUI\CheckboxInputWidget( [
@@ -393,114 +590,15 @@
                                'align' => 'top',
                                'label' => 'CheckboxMultiselectInputWidget',
                        ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\TextInputWidget( [ 'value' => 'Text input' ] ),
-                       [
-                               'label' => "TextInputWidget\xE2\x80\x8E",
-                               'align' => 'top'
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\TextInputWidget( [ 'icon' => 'help' ] ),
-                       [
-                               'label' => "TextInputWidget (icon)\xE2\x80\x8E",
-                               'align' => 'top'
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\TextInputWidget( [
-                               'required' => true
-                       ] ),
-                       [
-                               'label' => "TextInputWidget 
(required)\xE2\x80\x8E",
-                               'align' => 'top'
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\TextInputWidget( [ 'placeholder' => 
'Placeholder' ] ),
-                       [
-                               'label' => "TextInputWidget 
(placeholder)\xE2\x80\x8E",
-                               'align' => 'top'
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\TextInputWidget( [ 'type' => 'search' ] ),
-                       [
-                               'label' => "TextInputWidget 
(type=search)\xE2\x80\x8E",
-                               'align' => 'top'
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\TextInputWidget( [ 'type' => 'number' ] ),
-                       [
-                               'label' => "TextInputWidget 
(type=number)\xE2\x80\x8E",
-                               'align' => 'top'
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\TextInputWidget( [
-                               'value' => 'Readonly',
-                               'readOnly' => true
-                       ] ),
-                       [
-                               'label' => "TextInputWidget 
(readonly)\xE2\x80\x8E",
-                               'align' => 'top'
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\TextInputWidget( [
-                               'value' => 'Disabled',
-                               'disabled' => true
-                       ] ),
-                       [
-                               'label' => "TextInputWidget 
(disabled)\xE2\x80\x8E",
-                               'align' => 'top'
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\TextInputWidget( [
-                               'value' => 'Title attribute',
-                               'title' => 'Title attribute with more 
information about me.'
-                       ] ),
-                       [
-                               'label' => "TextInputWidget (with 
title)\xE2\x80\x8E",
-                               'align' => 'top'
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\TextInputWidget( [
-                               'multiline' => true,
-                               'value' => "Multiline\nMultiline"
-                       ] ),
-                       [
-                               'label' => "TextInputWidget 
(multiline)\xE2\x80\x8E",
-                               'align' => 'top'
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\TextInputWidget( [
-                               'multiline' => true,
-                               'rows' => 15,
-                               'value' => "Multiline\nMultiline"
-                       ] ),
-                       [
-                               'label' => "TextInputWidget (multiline, 
rows=15)\xE2\x80\x8E",
-                               'align' => 'top'
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\TextInputWidget( [
-                               'multiline' => true,
-                               'value' => "Multiline\nMultiline",
-                               'icon' => 'tag',
-                               'indicator' => 'required'
-                       ] ),
-                       [
-                               'label' => "TextInputWidget (multiline, icon, 
indicator)\xE2\x80\x8E",
-                               'align' => 'top'
-                       ]
-               ),
+               )
+       ]
+] ) );
+
+$demoContainer->appendContent( new OOUI\FieldsetLayout( [
+       'id' => 'demo-section-dropdown',
+       'infusable' => true,
+       'label' => 'Dropdown',
+       'items' => [
                new OOUI\FieldLayout(
                        new OOUI\DropdownInputWidget( [
                                'options' => [
@@ -610,7 +708,15 @@
                                'label' => "DropdownInputWidget 
(long)\xE2\x80\x8E",
                                'align' => 'top'
                        ]
-               ),
+               )
+       ]
+] ) );
+
+$demoContainer->appendContent( new OOUI\FieldsetLayout( [
+       'id' => 'demo-section-comboBox',
+       'infusable' => true,
+       'label' => 'ComboBox',
+       'items' => [
                new OOUI\FieldLayout(
                        new OOUI\ComboBoxInputWidget( [
                                'options' => [
@@ -648,124 +754,48 @@
                                'label' => "ComboBoxInputWidget 
(empty)\xE2\x80\x8E",
                                'align' => 'top'
                        ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\ButtonInputWidget( [
-                               'label' => 'Submit the form',
-                               'type' => 'submit',
-                               'flags' => [ 'primary', 'progressive' ],
-                               'useInputTag' => true
-                       ] ),
-                       [
-                               'align' => 'top',
-                               'label' => "ButtonInputWidget (using 
<input>)\xE2\x80\x8E"
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\ButtonInputWidget( [
-                               'label' => 'Another button',
-                               'type' => 'button'
-                       ] ),
-                       [
-                               'align' => 'top',
-                               'label' => "ButtonInputWidget (using 
<button>)\xE2\x80\x8E"
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\ButtonInputWidget( [
-                               'framed' => false,
-                               'label' => 'Another button',
-                               'type' => 'button'
-                       ] ),
-                       [
-                               'align' => 'top',
-                               'label' => "ButtonInputWidget 
(frameless)\xE2\x80\x8E"
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\ButtonInputWidget( [
-                               'framed' => false,
-                               'label' => 'Another button',
-                               'type' => 'button',
-                               'useInputTag' => true
-                       ] ),
-                       [
-                               'align' => 'top',
-                               'label' => "ButtonInputWidget (frameless, using 
<input>)\xE2\x80\x8E"
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\ButtonWidget( [
-                               'label' => 'Accesskey: H',
-                               'accessKey' => 'h'
-                       ] ),
-                       [
-                               'label' => "ButtonWidget (with 
accesskey)\xE2\x80\x8E",
-                               'align' => 'top'
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\ButtonInputWidget( [
-                               'label' => 'Accesskey: I',
-                               'accessKey' => 'i'
-                       ] ),
-                       [
-                               'label' => "ButtonInputWidget (with 
accesskey)\xE2\x80\x8E",
-                               'align' => 'top'
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\TextInputWidget( [
-                               'value' => 'Accesskey: S',
-                               'accessKey' => 's'
-                       ] ),
-                       [
-                               'label' => "TextInputWidget (with 
accesskey)\xE2\x80\x8E",
-                               'align' => 'top'
-                       ]
                )
        ]
 ] ) );
-// We can't make the outer FieldsetLayout infusable, because the Widget in its 
FieldLayout
-// is added with 'content', which is not preserved after infusion. But we need 
the Widget
-// to wrap the HorizontalLayout. Need to think about this at some point.
+
 $demoContainer->appendContent( new OOUI\FieldsetLayout( [
-       'infusable' => false,
-       'label' => 'HorizontalLayout',
+       'id' => 'demo-section-progressBar',
+       'infusable' => true,
+       'label' => 'Progress bar',
        'items' => [
                new OOUI\FieldLayout(
-                       new OOUI\Widget( [
-                               'content' => new OOUI\HorizontalLayout( [
-                                       'infusable' => true,
-                                       'items' => [
-                                               new OOUI\ButtonWidget( [ 
'label' => 'Button' ] ),
-                                               new OOUI\ButtonGroupWidget( [ 
'items' => [
-                                                       new OOUI\ButtonWidget( 
[ 'label' => 'A' ] ),
-                                                       new OOUI\ButtonWidget( 
[ 'label' => 'B' ] )
-                                               ] ] ),
-                                               new OOUI\ButtonInputWidget( [ 
'label' => 'ButtonInput' ] ),
-                                               new OOUI\TextInputWidget( [ 
'value' => 'TextInput' ] ),
-                                               new OOUI\DropdownInputWidget( [ 
'options' => [
-                                                       [
-                                                               'label' => 
'DropdownInput',
-                                                               'data' => null
-                                                       ]
-                                               ] ] ),
-                                               new OOUI\CheckboxInputWidget( [ 
'selected' => true ] ),
-                                               new OOUI\RadioInputWidget( [ 
'selected' => true ] ),
-                                               new OOUI\LabelWidget( [ 'label' 
=> 'Label' ] )
-                                       ],
-                               ] ),
+                       new OOUI\ProgressBarWidget( [
+                               'progress' => 33
                        ] ),
                        [
-                               'label' => 'Multiple widgets shown as a single 
line, ' .
-                                       'as used in compact forms or in parts 
of a bigger widget.',
+                               'label' => 'Progress bar',
                                'align' => 'top'
                        ]
                ),
-       ],
+               new OOUI\FieldLayout(
+                       new OOUI\ProgressBarWidget( [
+                               'disabled' => true,
+                               'progress' => 50
+                       ] ),
+                       [
+                               'label' => 'Progress bar (disabled)',
+                               'align' => 'top'
+                       ]
+               ),
+               new OOUI\FieldLayout(
+                       new OOUI\ProgressBarWidget( [
+                               'progress' => false
+                       ] ),
+                       [
+                               'label' => 'Progress bar (indeterminate)',
+                               'align' => 'top'
+                       ]
+               ),
+       ]
 ] ) );
+
 $demoContainer->appendContent( new OOUI\FieldsetLayout( [
+       'id' => 'demo-section-others',
        'infusable' => true,
        'label' => 'Other widgets',
        'items' => [
@@ -852,7 +882,9 @@
                )
        ]
 ] ) );
+
 $demoContainer->appendContent( new OOUI\FieldsetLayout( [
+       'id' => 'demo-section-fieldLayouts',
        'infusable' => true,
        'label' => 'Field layouts',
        'icon' => 'tag',
@@ -1042,26 +1074,49 @@
                                'errors' => [ 'The value must be a number.' ],
                                'align' => 'top'
                        ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\ProgressBarWidget( [
-                               'progress' => 33
-                       ] ),
-                       [
-                               'label' => 'Progress bar',
-                               'align' => 'top'
-                       ]
-               ),
-               new OOUI\FieldLayout(
-                       new OOUI\ProgressBarWidget( [
-                               'progress' => false
-                       ] ),
-                       [
-                               'label' => 'Progress bar (indeterminate)',
-                               'align' => 'top'
-                       ]
-               ),
+               )
        ]
+] ) );
+
+// We can't make the outer FieldsetLayout infusable, because the Widget in its 
FieldLayout
+// is added with 'content', which is not preserved after infusion. But we need 
the Widget
+// to wrap the HorizontalLayout. Need to think about this at some point.
+$demoContainer->appendContent( new OOUI\FieldsetLayout( [
+       'id' => 'demo-section-horizontalLayout',
+       'infusable' => false,
+       'label' => 'HorizontalLayout',
+       'items' => [
+               new OOUI\FieldLayout(
+                       new OOUI\Widget( [
+                               'content' => new OOUI\HorizontalLayout( [
+                                       'infusable' => true,
+                                       'items' => [
+                                               new OOUI\ButtonWidget( [ 
'label' => 'Button' ] ),
+                                               new OOUI\ButtonGroupWidget( [ 
'items' => [
+                                                       new OOUI\ButtonWidget( 
[ 'label' => 'A' ] ),
+                                                       new OOUI\ButtonWidget( 
[ 'label' => 'B' ] )
+                                               ] ] ),
+                                               new OOUI\ButtonInputWidget( [ 
'label' => 'ButtonInput' ] ),
+                                               new OOUI\TextInputWidget( [ 
'value' => 'TextInput' ] ),
+                                               new OOUI\DropdownInputWidget( [ 
'options' => [
+                                                       [
+                                                               'label' => 
'DropdownInput',
+                                                               'data' => null
+                                                       ]
+                                               ] ] ),
+                                               new OOUI\CheckboxInputWidget( [ 
'selected' => true ] ),
+                                               new OOUI\RadioInputWidget( [ 
'selected' => true ] ),
+                                               new OOUI\LabelWidget( [ 'label' 
=> 'Label' ] )
+                                       ],
+                               ] ),
+                       ] ),
+                       [
+                               'label' => 'Multiple widgets shown as a single 
line, ' .
+                                       'as used in compact forms or in parts 
of a bigger widget.',
+                               'align' => 'top'
+                       ]
+               ),
+       ],
 ] ) );
 
 $demoContainer->appendContent( new OOUI\FormLayout( [
@@ -1070,6 +1125,7 @@
        'action' => 'demos.php',
        'items' => [
                new OOUI\FieldsetLayout( [
+                       'id' => 'demo-section-formLayout',
                        'label' => 'Form layout',
                        'items' => [
                                new OOUI\FieldLayout(
@@ -1101,6 +1157,18 @@
                                                'align' => 'inline',
                                        ]
                                ),
+                               new OOUI\FieldLayout(
+                                       new OOUI\HiddenInputWidget( [
+                                               'name' => 'hidden',
+                                               'value' => 'hidden value',
+                                       ] )
+                               ),
+                               new OOUI\FieldLayout(
+                                       new OOUI\ButtonInputWidget( [
+                                               'type' => 'submit',
+                                               'label' => 'Submit form',
+                                       ] )
+                               ),
                        ]
                ] ),
                new OOUI\FieldsetLayout( [
diff --git a/oojs/oojs-ui/demos/styles/demo.css 
b/oojs/oojs-ui/demos/styles/demo.css
index 45c890f..73ae333 100644
--- a/oojs/oojs-ui/demos/styles/demo.css
+++ b/oojs/oojs-ui/demos/styles/demo.css
@@ -1,6 +1,7 @@
 body {
        color: #222;
-       margin: 1em;
+       margin: 0 1em;
+       padding: 0;
        font-family: sans-serif;
        font-size: 0.8em;
 }
@@ -16,18 +17,10 @@
 }
 
 .demo-menu {
-       background-color: #fff;
-       position: fixed;
-       top: 0;
-       z-index: 1;
-       width: 62.5em;
-       padding-top: 1em;
-       /* To better hide Apex's large drop shadows */
-       margin-left: -1em;
-       padding-left: 1em;
-       padding-right: 1em;
-       /* Support: Android < 5, iOS < 8 to tame their buggy behaviour */
-       -webkit-backface-visibility: hidden;
+       min-width: 320px; /* Let's not pretend it works on anything lower than 
that */
+       -webkit-box-sizing: border-box;
+       -moz-box-sizing: border-box;
+       box-sizing: border-box;
 }
 
 .demo-menu > .oo-ui-widget {
@@ -46,11 +39,6 @@
        -webkit-box-sizing: border-box;
        -moz-box-sizing: border-box;
        box-sizing: border-box;
-}
-
-/* This needs extra specificity to beat PanelLayout styles */
-.oo-ui-panelLayout.demo-container {
-       margin-top: 5em;
 }
 
 /* Console */
@@ -116,6 +104,7 @@
        transform: rotate( -90deg );
 }
 
+.demo-console-collapsed .demo-sample-code,
 .demo-console-collapsed .demo-console-log,
 .demo-console-collapsed .demo-console-label,
 .demo-console-collapsed .demo-console-submit {
@@ -218,6 +207,12 @@
        color: #444;
 }
 
+.demo-sample-code {
+       /* Need to override Prism (syntax highlighter) styles */
+       background-color: #eaecf0;
+       margin: 0 !important; /* stylelint-disable-line 
declaration-no-important */
+}
+
 /* Toolbars demo */
 
 .demo-container.demo-toolbars {
@@ -268,6 +263,12 @@
        max-width: 10em;
 }
 
+.demo-overlay {
+       position: absolute;
+       top: 0;
+       left: 0;
+}
+
 /* Special cases: ActionFieldLayout top aligned,
 FieldLayout left & right aligned */
 .oo-ui-fieldLayout-align-left,
@@ -294,8 +295,37 @@
        padding: 1em 1em 1.5em 1em;
 }
 
+/*
+ * Support: iOS 9.2, Android 4.4.4, Op Mobile 37, Chrome/Android 57, 
Fx/Android 52, UC Browser 11.4, Baidu 7.12
+ * Workaround for weak ancient mobile browser support of `fixed` positioning
+ */
+@supports ( position: fixed ) {
+       .demo-menu {
+               background-color: #fff;
+               position: fixed;
+               top: 0;
+               border-bottom: 1px solid #a2a9b1;
+               padding-top: 1em;
+               box-shadow: 0 4px 4px -4px rgba( 0, 0, 0, 0.25 );
+               z-index: 5;
+       }
+
+       /* This needs extra specificity to beat PanelLayout styles */
+       .demo-container.oo-ui-panelLayout {
+               /* Apex overrides. WikimediaUI wins for now in the demo framing 
in this browser subset */
+               border-color: #a2a9b1;
+               border-radius: 2px;
+               box-shadow: none;
+       }
+
+       .oo-ui-windowManager-modal > .oo-ui-dialog,
+       .oo-ui-processDialog-errors {
+               z-index: 6;
+       }
+}
+
 /* Media Queries */
-@media ( max-width: 750px ) {
+@media ( min-width: 320px ) {
        body {
                font-size: 1em;
        }
@@ -317,12 +347,74 @@
        .demo-console-toggle {
                margin-right: -2em;
        }
-}
 
-@media ( min-width: 751px ) {
-       .demo-container {
-               padding: 2em;
+       @supports ( position: fixed ) {
+               .demo-menu {
+                       min-height: 11.4em;
+                       left: 1em;
+                       right: 1em;
+               }
+
+               /* Hide “Docs“ Button on very small screens */
+               .demo-menu > .demo-button-docs {
+                       display: none;
+               }
+
+               /* This needs extra specificity to beat PanelLayout styles */
+               .demo-container.oo-ui-panelLayout {
+                       margin-top: 11.4em;
+               }
        }
 }
 
+@media ( min-width: 568px ) {
+       @supports ( position: fixed ) {
+               .demo-menu {
+                       min-height: 7.5em;
+               }
+
+               .demo-menu > .demo-button-docs {
+                       display: inline-block;
+               }
+
+               .demo-container.oo-ui-panelLayout {
+                       margin-top: 7.5em;
+               }
+       }
+}
+
+@media ( min-width: 768px ) {
+       .demo-console-toggle {
+               margin-right: 0;
+       }
+}
+
+@media ( min-width: 960px ) {
+       body {
+               font-size: 0.8em;
+       }
+
+       .demo-container {
+               border-radius: 2px;
+               border-width: 1px;
+               padding: 2em;
+       }
+
+       .demo-menu {
+               width: 62.5em;
+               white-space: nowrap;
+       }
+
+       @supports ( position: fixed ) {
+               .demo-menu {
+                       min-height: 4.5em;
+                       left: auto;
+                       right: auto;
+               }
+
+               .demo-container.oo-ui-panelLayout {
+                       margin-top: 4.5em;
+               }
+       }
+}
 /* stylelint-enable selector-pseudo-element-colon-notation */
diff --git a/oojs/oojs-ui/i18n/id.json b/oojs/oojs-ui/i18n/id.json
index ac7f6c6..c53e058 100644
--- a/oojs/oojs-ui/i18n/id.json
+++ b/oojs/oojs-ui/i18n/id.json
@@ -9,7 +9,8 @@
                        "McDutchie",
                        "Rv77ax",
                        "William Surya Permana",
-                       "Rachmat.Wahidi"
+                       "Rachmat.Wahidi",
+                       "Rachmat04"
                ]
        },
        "ooui-outline-control-move-down": "Pindahkan butir ke bawah",
diff --git a/oojs/oojs-ui/package.json b/oojs/oojs-ui/package.json
index 88a79a7..15eed0d 100644
--- a/oojs/oojs-ui/package.json
+++ b/oojs/oojs-ui/package.json
@@ -1,6 +1,6 @@
 {
   "name": "oojs-ui",
-  "version": "0.21.4",
+  "version": "0.22.0",
   "description": "User interface classes built on the OOjs framework.",
   "keywords": [
     "oojs-plugin",
@@ -17,6 +17,7 @@
     "predoc": "grunt build",
     "doc": "jsduck",
     "postdoc": "grunt copy:jsduck",
+    "quickdoc": "grunt quick-build && jsduck && grunt copy:jsduck",
     "publish-build": "grunt publish-build",
     "demos": "grunt publish-build && grunt demos",
     "jenkins": "npm test && jsduck && npm run postdoc"
@@ -54,6 +55,7 @@
     "karma-firefox-launcher": "1.0.0",
     "karma-qunit": "1.1.0",
     "karma-remap-istanbul": "0.6.0",
+    "prismjs": "1.6.0",
     "q": "1.4.1",
     "qunitjs": "1.22.0",
     "stylelint": "7.8.0",
diff --git a/oojs/oojs-ui/php/themes/MediaWikiTheme.php 
b/oojs/oojs-ui/php/themes/MediaWikiTheme.php
index c3a1745..1c37218 100644
--- a/oojs/oojs-ui/php/themes/MediaWikiTheme.php
+++ b/oojs/oojs-ui/php/themes/MediaWikiTheme.php
@@ -2,44 +2,5 @@
 
 namespace OOUI;
 
-class MediaWikiTheme extends Theme {
-
-       /* Methods */
-
-       public function getElementClasses( Element $element ) {
-               $variants = [
-                       'warning' => false,
-                       'invert' => false,
-                       'progressive' => false,
-                       'constructive' => false,
-                       'destructive' => false
-               ];
-
-               // Parent method
-               $classes = parent::getElementClasses( $element );
-
-               if ( $element->supports( [ 'hasFlag' ] ) ) {
-                       $isFramed = $element->supports( [ 'isFramed' ] ) && 
$element->isFramed();
-                       $isActive = $element->supports( [ 'isActive' ] ) && 
$element->isActive();
-                       if ( $isFramed && ( $isActive || $element->isDisabled() 
|| $element->hasFlag( 'primary' ) ) ) {
-                               // Button with a dark background, use white icon
-                               $variants['invert'] = true;
-                       } elseif ( !$isFramed && $element->isDisabled() ) {
-                               // Frameless disabled button, always use black 
icon regardless of flags
-                               $variants['invert'] = false;
-                       } elseif ( !$element->isDisabled() ) {
-                               // Any other kind of button, use the right 
colored icon if available
-                               $variants['progressive'] = $element->hasFlag( 
'progressive' );
-                               $variants['constructive'] = $element->hasFlag( 
'constructive' );
-                               $variants['destructive'] = $element->hasFlag( 
'destructive' );
-                               $variants['warning'] = $element->hasFlag( 
'warning' );
-                       }
-               }
-
-               foreach ( $variants as $variant => $toggle ) {
-                       $classes[$toggle ? 'on' : 'off'][] = 'oo-ui-image-' . 
$variant;
-               }
-
-               return $classes;
-       }
+class MediaWikiTheme extends WikimediaUITheme {
 }
diff --git a/oojs/oojs-ui/php/themes/WikimediaUITheme.php 
b/oojs/oojs-ui/php/themes/WikimediaUITheme.php
new file mode 100644
index 0000000..8c3f911
--- /dev/null
+++ b/oojs/oojs-ui/php/themes/WikimediaUITheme.php
@@ -0,0 +1,45 @@
+<?php
+
+namespace OOUI;
+
+class WikimediaUITheme extends Theme {
+
+       /* Methods */
+
+       public function getElementClasses( Element $element ) {
+               $variants = [
+                       'warning' => false,
+                       'invert' => false,
+                       'progressive' => false,
+                       'constructive' => false,
+                       'destructive' => false
+               ];
+
+               // Parent method
+               $classes = parent::getElementClasses( $element );
+
+               if ( $element->supports( [ 'hasFlag' ] ) ) {
+                       $isFramed = $element->supports( [ 'isFramed' ] ) && 
$element->isFramed();
+                       $isActive = $element->supports( [ 'isActive' ] ) && 
$element->isActive();
+                       if ( $isFramed && ( $isActive || $element->isDisabled() 
|| $element->hasFlag( 'primary' ) ) ) {
+                               // Button with a dark background, use white icon
+                               $variants['invert'] = true;
+                       } elseif ( !$isFramed && $element->isDisabled() ) {
+                               // Frameless disabled button, always use black 
icon regardless of flags
+                               $variants['invert'] = false;
+                       } elseif ( !$element->isDisabled() ) {
+                               // Any other kind of button, use the right 
colored icon if available
+                               $variants['progressive'] = $element->hasFlag( 
'progressive' );
+                               $variants['constructive'] = $element->hasFlag( 
'constructive' );
+                               $variants['destructive'] = $element->hasFlag( 
'destructive' );
+                               $variants['warning'] = $element->hasFlag( 
'warning' );
+                       }
+               }
+
+               foreach ( $variants as $variant => $toggle ) {
+                       $classes[$toggle ? 'on' : 'off'][] = 'oo-ui-image-' . 
$variant;
+               }
+
+               return $classes;
+       }
+}
diff --git a/oojs/oojs-ui/php/widgets/CheckboxInputWidget.php 
b/oojs/oojs-ui/php/widgets/CheckboxInputWidget.php
index 9e6e0d0..4b0beb9 100644
--- a/oojs/oojs-ui/php/widgets/CheckboxInputWidget.php
+++ b/oojs/oojs-ui/php/widgets/CheckboxInputWidget.php
@@ -31,7 +31,7 @@
 
                // Initialization
                $this->addClasses( [ 'oo-ui-checkboxInputWidget' ] );
-               // Required for pretty styling in MediaWiki theme
+               // Required for pretty styling in WikimediaUI theme
                $this->appendContent( new Tag( 'span' ) );
                $this->setSelected( isset( $config['selected'] ) ? 
$config['selected'] : false );
        }
diff --git a/oojs/oojs-ui/php/widgets/HiddenInputWidget.php 
b/oojs/oojs-ui/php/widgets/HiddenInputWidget.php
new file mode 100644
index 0000000..af1b234
--- /dev/null
+++ b/oojs/oojs-ui/php/widgets/HiddenInputWidget.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace OOUI;
+
+/**
+ * Data widget intended for creating 'hidden'-type inputs.
+ */
+class HiddenInputWidget extends Widget {
+
+       /**
+        * @var string
+        */
+       public static $tagName = 'input';
+
+       /**
+        * DataWidget constructor.
+        *
+        * @param array $config
+        * @param string $config['value'] The data the input contains. 
(default: '')
+        * @param string $config['name'] The name of the hidden input. 
(default: '')
+        */
+       public function __construct( array $config ) {
+               // Configuration initialization
+               $config = array_merge( [ 'value' => '', 'name' => '' ], $config 
);
+
+               // Parent constructor
+               parent::__construct( $config );
+
+               // Initialization
+               $this->setAttributes( [
+                       'type' => 'hidden',
+                       'value' => $config['value'],
+                       'name' => $config['name'],
+               ] );
+               $this->removeAttributes( [ 'aria-disabled' ] );
+       }
+
+       public function getConfig( &$config ) {
+               $config['value'] = $this->getAttribute( 'value' );
+               $config['name'] = $this->getAttribute( 'name' );
+               return parent::getConfig( $config );
+       }
+}
diff --git a/oojs/oojs-ui/php/widgets/InputWidget.php 
b/oojs/oojs-ui/php/widgets/InputWidget.php
index 8be7930..dfe918b 100644
--- a/oojs/oojs-ui/php/widgets/InputWidget.php
+++ b/oojs/oojs-ui/php/widgets/InputWidget.php
@@ -34,6 +34,7 @@
         * @param string $config['name'] HTML input name (default: '')
         * @param string $config['value'] Input value (default: '')
         * @param string $config['dir'] The directionality of the input 
(ltr/rtl)
+        * @param string $config['inputId'] The value of the input’s HTML `id` 
attribute.
         */
        public function __construct( array $config = [] ) {
                // Parent constructor
@@ -65,6 +66,9 @@
                $this->setValue( isset( $config['value'] ) ? $config['value'] : 
null );
                if ( isset( $config['dir'] ) ) {
                        $this->setDir( $config['dir'] );
+               }
+               if ( isset( $config['inputId'] ) ) {
+                       $this->setInputId( $config['inputId'] );
                }
        }
 
@@ -138,6 +142,17 @@
                return $this;
        }
 
+       /**
+        * Set the 'id' attribute of the `<input>` element.
+        *
+        * @param string $id
+        * @return $this
+        */
+       public function setInputId( $id ) {
+               $this->input->setAttributes( [ 'id' => $id ] );
+               return $this;
+       }
+
        public function getConfig( &$config ) {
                $name = $this->input->getAttribute( 'name' );
                if ( $name !== null ) {
@@ -146,6 +161,10 @@
                if ( $this->value !== '' ) {
                        $config['value'] = $this->value;
                }
+               $id = $this->input->getAttribute( 'id' );
+               if ( $id !== null ) {
+                       $config['inputId'] = $id;
+               }
                return parent::getConfig( $config );
        }
 }
diff --git a/oojs/oojs-ui/php/widgets/RadioInputWidget.php 
b/oojs/oojs-ui/php/widgets/RadioInputWidget.php
index 4a0f359..72943d8 100644
--- a/oojs/oojs-ui/php/widgets/RadioInputWidget.php
+++ b/oojs/oojs-ui/php/widgets/RadioInputWidget.php
@@ -22,7 +22,7 @@
 
                // Initialization
                $this->addClasses( [ 'oo-ui-radioInputWidget' ] );
-               // Required for pretty styling in MediaWiki theme
+               // Required for pretty styling in WikimediaUI theme
                $this->appendContent( new Tag( 'span' ) );
                $this->setSelected( isset( $config['selected'] ) ? 
$config['selected'] : false );
        }
diff --git a/oojs/oojs-ui/php/widgets/TextInputWidget.php 
b/oojs/oojs-ui/php/widgets/TextInputWidget.php
index 20cf035..885c155 100644
--- a/oojs/oojs-ui/php/widgets/TextInputWidget.php
+++ b/oojs/oojs-ui/php/widgets/TextInputWidget.php
@@ -186,7 +186,6 @@
                $allowedTypes = [
                        'text',
                        'password',
-                       'search',
                        'email',
                        'url',
                        'number'

-- 
To view, visit https://gerrit.wikimedia.org/r/356313
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I93b66d5339e6766f46dfcc5b22abaeadd74d8da0
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/vendor
Gerrit-Branch: master
Gerrit-Owner: Jforrester <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to