Codex
Visit the official documentation site for comprehensive details on Codex, including how to use it outside of MediaWiki. |
Codex
Design system for Wikimedia featuring guidelines and a set of tools (design tokens, components, and icons) for creating user-interfaces
|
Codex is the design system for Wikimedia. As a system, Codex is made up of several distinct elements which may be used separately or together. These elements include: design tokens, icons, and UI components. Codex is bundled within MediaWiki, and is also available as a series of NPM packages.
The current version of Codex is 1.16.0
Codex's source code is hosted on Gerrit, and its development is tracked in Phabricator. Read the full changelog.
Basic usage
[edit]Codex provides a variety of components which skin, extension, and userscript authors can embed in their own user interfaces: buttons, checkboxes, toggle switches, dialogs, etc. Many of these components can be extensively customized.
A full list of current Codex components (along with documentation and interactive demos) can be found here.
CodexExample MediaWiki extension
[edit]The Design System Team maintains the CodexExample MediaWiki extension for demonstration purposes. This extension can be installed (it sets up a dedicated special page called `Special:CodexExample` with live demos) or you can study its source code for inspiration. See the project README page for more information.
Usage with JavaScript
[edit]Codex components are built using the Vue.js JavaScript framework.
If you are developing a Vue application in MediaWiki, then it's easy to load Codex components from ResourceLoader using require()
.
You can load all of Codex at once, or just a limited subset of components.
Loading the entire library (recommended for use in userscripts)
[edit]"ext.myExtension.foo": {
"dependencies": [ "@wikimedia/codex" ]
"packageFiles": [
"init.js",
"MyComponent.vue"
]
}
<!-- MyComponent.vue -->
<template>
<cdx-button @click="doSomething">Click me!</cdx-button>
</template>
<script>
const { CdxButton } = require( '@wikimedia/codex' );
module.exports = exports = {
name: "MyComponent",
components: {
CdxButton
},
methods: {
doSomething() {
//...
}
}
}
</script>
Loading a subset of Codex components (recommended for skins and extensions)
[edit]To only load a limited set of components, you can declare your dependencies in the following way below:
"ext.myExtension.foo": {
"class": "MediaWiki\\ResourceLoader\\CodexModule",
"packageFiles": [
"init.js",
"MyComponent.vue"
],
"codexComponents": [
"CdxButton",
"CdxCard",
"CdxDialog"
]
}
This will generate a virtual file, codex.js
, in your resources directory with the exports you need.
You can then require the components you requested from that virtual file:
// In resources/ext.myExtension.foo/MyComponent.vue
const { CdxButton, CdxTextInput } = require( '../codex.js' );
See the CodexExample repository for more in-depth example of how to use Codex in a MediaWiki extension.
Usage without JavaScript (CSS-only Codex components)
[edit]MediaWiki version: | ≥ 1.42 |
Many Codex components also support "css-only" usage. These components should appear visually identical to their JS-enabled counterparts, but they will offer more limited behavior.
Loading component styles
[edit]You can load the styles of a limited subset of Codex CSS components in the same way as you would for JS components, above.
If you only need the styles, you can add the "codexStyleOnly": "true"
option when you define your module.
"ext.myExtension.foo": {
"class": "MediaWiki\\ResourceLoader\\CodexModule",
"styles": "ext.myExtension.foo/styles.less",
"codexStyleOnly": "true",
"codexComponents": [
"CdxButton",
"CdxCard",
"CdxCheckbox",
"CdxProgressBar"
]
}
Providing component markup
[edit]To use CSS-only Codex components, just ensure that the appropriate styles are loaded and then add the necessary markup to your page. For now, you'll have to do this by hand. You can find example markup in the "CSS-only usage" section on a component's documentation page (here is the markup for the Button component).
<div>
<button class="cdx-button cdx-button--action-default">Default button</button>
</div>
<div>
<button class="cdx-button cdx-button--action-progressive">
Progressive button
</button>
</div>
<div>
<button class="cdx-button cdx-button--action-destructive">
Destructive button
</button>
</div>
Using Codex in PHP
[edit]Codex PHP is a library for building CSS-only UI components using Codex, the Wikimedia design system, please see the Codex PHP documentation.
Installation
[edit]Install the Codex PHP library via Composer:
composer require wikimedia/codex
Example Usage
[edit]Here’s an example of creating an Accordion component in PHP:
$accordion = $codex
->accordion()
->setTitle( "Accordion Example" )
->setDescription( "This is an example of an accordion." )
->setContentHtml(
$codex
->htmlSnippet()
->setContent( "<p>This is the content of the accordion.</p>" )
->build()
)
->setOpen( false )
->setAttributes( [
"class" => "foo",
"bar" => "baz",
] )
->build()
->getHtml();
echo $accordion;
Usage in MediaWiki
[edit]Below is an example of using Codex components in MediaWiki:
<?php
use MediaWiki\SpecialPage\SpecialPage;
use Wikimedia\Codex\Adapter\WebRequestAdapter;
use Wikimedia\Codex\Utility\Codex;
use Wikimedia\Codex\Utility\WebRequestCallbacks;
class SomeSpecial extends SpecialPage {
public function __construct() {
parent::__construct( "SomeSpecial" );
}
public function execute( $subPage ) {
$codex = new Codex();
$requestAdapter = new WebRequestAdapter( $this->getRequest() );
$callbacks = new WebRequestCallbacks( $requestAdapter );
$tab1 = $codex
->Tab()
->setName( "tab1" )
->setLabel( "Tab 1" )
->setContentHtml(
$codex
->htmlSnippet()
->setContent( "<p>Content 1.</p>" )
->build()
)
->setSelected( true )
->build();
$tabs = $codex
->Tabs()
->setCallbacks( $callbacks )
->setTab( [ $tab1 ] )
->build()
->getHtml();
$this->getOutput()->addHTML( $tabs );
}
}
Advanced usage
[edit]Using a limited subset of components
[edit]The @wikimedia/codex
ResourceLoader module provides the entire Codex library – all components, styles, etc.
If you are developing a skin or an extension and you care about performance, you should consider using Codex's code-splitting feature.
ResourceLoader allows you to specify a list of Codex components and load only the JS/CSS for those components plus their dependencies.
To use this feature, define a custom ResourceLoader module (this is typically done in skin.json
or extension.json
) and specify a list of codexComponents
:
"ext.myExtension.blockform": {
"class": "MediaWiki\\ResourceLoader\\CodexModule",
"codexComponents": [
"CdxButton",
"CdxCard",
"CdxDialog",
"CdxIcon",
"CdxRadio",
"CdxTextInput",
"useModelWrapper"
],
"packageFiles": [
"init.js",
"BlockForm.vue"
],
"messages": [
"block-target",
"ipb-submit"
]
}
This will generate a virtual file, codex.js
, in your resources
directory with the exports you need.
You can then require the components and composables you requested from that virtual file:
// In resources/ext.myExtension/BlockForm.vue
const { CdxButton, CdxTextInput } = require( '../codex.js' );
If you only need CSS-only components and don't wish to load the component JavaScript, you can add "codexStyleOnly": true
to the module definition.
Similarly, if you only need the JavaScript files and not styles, you can add "codexScriptOnly": "true"
.
You should only do this if you're putting the styles in another, style-only module as described above.
Using Codex icons
[edit]For performance reasons, there is no codex-icons
ResourceLoader module containing all the icons from Codex.
Such a module would be large and wasteful, since most users of Codex only need a handful of the 200+ icons.
Instead, ResourceLoader provides a way for modules to embed the icons they need, similar to the code-splitting approach described above.
{
"name": "icons.json",
"callback": "MediaWiki\\ResourceLoader\\CodexModule::getIcons",
"callbackParam": [
// List the icons your module needs here, e.g.:
"cdxIconArrowNext",
"cdxIconBold",
"cdxIconTrash"
]
}
Using design tokens directly
[edit]Design tokens can be imported into LESS stylesheets as variables. This may be useful if you are developing your own components or styles and want them to integrate with Codex.
Codex design tokens should be imported from the mediawiki.skin.variables.less
file.
@import 'mediawiki.skin.variables.less';
.my-feature {
color: @color-base;
background-color: @background-color-base;
}
For a full list of Codex's design tokens, broken down by category, see here.
Codex LESS mixins
[edit]Some Codex functionality is implemented using Less mixins. For example, the Link component is a Less mixin rather than a Vue component, and using icons in CSS-only components requires using a Less mixin (see also the documentation for using CSS-only components below).
Using Codex Less mixins in MediaWiki and extensions works very similarly to using design tokens: simply import 'mediawiki.skin.variables.less'
, which makes all Codex mixins available, as well as the design tokens.
@import 'mediawiki.skin.variables.less';
.my-feature {
a {
.cdx-mixin-link-base();
}
}
Using Codex in userscripts
[edit]It is possible to use Codex in userscripts. However, there are some limitations that will require certain workarounds. Here are a few considerations to keep in mind when using Vue and Codex in userscripts:
- No
.vue
single-file component support; you must define components in plain JS files - Everything needs to live in one file; userscripts don't provide a good way to load custom modules
- Define component templates using ES6 template literals
- Prefer global component registration for Codex components
Loading Vue/Codex
[edit]You'll need to load Vue and Codex from ResourceLoader.
The best way to do this is via mw.loader.using
; the rest of your userscript code should live in a callback or promise chain.
mw.loader.using( '@wikimedia/codex' ).then( function( require ) {
const Vue = require( 'vue' );
const Codex = require( '@wikimedia/codex' );
} );
Use Vue.createMwApp
[edit]Once you've loaded Vue and Codex, you must define a Vue app and mount it somewhere on the page.
The exact location will vary depending on what you are trying to do.
You can use MediaWiki's custom createMwApp
method for this.
mw.loader.using( '@wikimedia/codex' ).then( function( require ) {
//... require Vue and Codex as above
// create an element to mount the Vue app
const mountPoint = document.body.appendChild( document.createElement( 'div' ) );
// create a Vue app and mount it to the target element
Vue.createMwApp( {
// data, computed props, methods, etc. go here
} ).mount( mountPoint );
} );
Real examples
[edit]The link below shows a complete example of a userscript which adds a portlet link to all Wiki pages that triggers a custom Codex Dialog component to launch when clicked. Feel free to copy this script to your own user page to use as a starting point.
https://en.wikipedia.org/wiki/User:EGardner_(WMF)/codex-hello-world.js
Here is another script using Codex :
https://en.wikipedia.org/wiki/User:JSherman_(WMF)/revertrisk.js
Release cycle
[edit]A new version of Codex is released every other Tuesday. When a new release is created, a patch is also submitted to MediaWiki core to use that new release. Since this is done on Tuesdays, the update to core will be deployed the following week (the next time the deployment train runs).
Using a custom version of Codex for development or testing
[edit]MediaWiki uses the latest release of Codex. If you need to use a different version for development or testing purposes, for example to test how an unmerged patch in Codex interacts with MediaWiki, you can point MediaWiki to your own version of Codex as follows:
- Clone the Codex repository (if you haven't already), and check out the change you want to test.
- Run
npm install
andnpm run build-all
in the root directory of the Codex repository. - Point
$wgCodexDevelopmentDir
to the root directory of the Codex repository. For example, if you cloned the Codex repository in the parent directory of the MediaWiki directory, add$wgCodexDevelopmentDir = MW_INSTALL_PATH . '../codex';
toLocalSettings.php
- Test that it works by running
mw.loader.load( '@wikimedia/codex' )
in the browser console. This should trigger a warning saying "You are using a local development version of Codex", and should not trigger any errors.
Once you have this set up, you can make additional changes to your Codex clone, but you have to run npm run build-all
each time to make those changes take effect in MediaWiki.
To disable development mode and go back to using the latest release of Codex, comment out the line in LocalSettings.php
that sets $wgCodexDevelopmentDir
.