Codex is the design system for Wikimedia. It includes design tokens to store stylistic values, user interface components built in both JavaScript (Vue.js) and only with CSS, and a suite of icons. All of these are designed and built with wide-ranging support for internationalisation, global usage and web accessibility by default.

This page documents how to use Codex in MediaWiki. To see the code itself, see the Codex software package. For general documentation on how to use Vue.js in MediaWiki, see Vue.js .

Codex packages in MediaWiki edit

Current version edit

MediaWiki currently uses version 1.3.4 of Codex. New versions are released every 2 weeks (see the Release Timeline for release cadence and all versions).

Packages edit

The following Codex packages are available in MediaWiki:

  1. @wikimedia/codex-design-tokens — This package contains design tokens in various formats, including Less variables and JSON.
  2. @wikimedia/codex — This package contains user-interface (UI) components built with Vue 3 or as CSS-only components.
  3. @wikimedia/codex-icons — This package contains a set of icons.

Note that there currently also exists a fourth package — @wikimedia/codex-search. It is a subset of the @wikimedia/codex package, containing only the TypeaheadSearch component and its styles. With v0.20.0 it was deprecated and its code moved into codex package. It was invented to serve Vector 2022 only this component for performance considerations, should only be used there and is aimed to cease to exist with code splitting becoming available.

General use of Codex in MediaWiki edit

Check out the CodexExample extension (MW 1.41+) for sample use of its components, design tokens, and icons in a MediaWiki extension.

The code examples on the Codex documentation web site all have two versions, labeled "NPM" and "MediaWiki". In MediaWiki core, skins and extensions, you have to use the "MediaWiki" versions of these examples; the "NPM" examples won't work, because some things work slightly differently in MediaWiki. Also read the sections on this page that go into more detail about how to use Codex design tokens, components, and icons in MediaWiki.

Using your local version of Codex in your local MediaWiki instance edit

Sometimes it can be helpful to use your version of Codex in your local MediaWiki instance, in order to test new features or changes in Codex that have not yet been released and included in MediaWiki core. We hope to eventually automate this, but until we have that capability, you can do this manually by copying the 'dist' files from the Codex packages into 'resources/lib' in core.

  1. Build your local Codex library by running npm run build-all in the root directory of your Codex repository.
  2. Copy the parts of Codex that you need into your MediaWiki core repository. All of the examples below assume that you use a Unix-like system (e.g. Linux or macOS), your Codex repo and your core repo live in the same directory, and that you are working from the core directory. To copy:
    • @wikimedia/codex package, which contains Codex components: cp -r ../codex/packages/codex/dist/{codex*,mixins,modules} resources/lib/codex/
    • @wikimedia/codex-design-tokens package: cp ../codex/packages/codex-design-tokens/dist/*.less resources/lib/codex-design-tokens/
    • @wikimedia/codex-icons package: cp ../codex/packages/codex-icons/dist/{codex-icons.json,codex-icon-paths.less} resources/lib/codex-icons/

Using Codex design tokens edit

Design tokens are the smallest stylistic pieces of our design system. Learn about Codex design tokens in the official documentation and see demos of available tokens (for example the color tokens demo).

Benefits of design tokens edit

All visual aspects of the design system, such as colors, typography, spacing, and sizes are defined with tokens. They provide a central source of truth for these design elements, which can then be used across multiple platforms and applications, and here in MediaWiki core, skins, and extensions. By using design tokens, designers and developers can ensure consistency in the look and feel of their digital products. For example, instead of hard-coding a specific color value in multiple places within a website or app, a design token for that color can be created and used throughout the system. In the final stage of tokens architecture, all Codex tokens should be used exclusively for style properties in MediaWiki core, skins and extensions. A change like a color replacement will be easily reflected everywhere.

Design tokens help streamline the design and development process, increase efficiency, and maintain visual consistency throughout a project.

Using Codex design tokens in MediaWiki and extensions edit

You can use the design tokens in a .less file (or in a <style lang="less"> block in a .vue file) by importing mediawiki.skin.variables.less. MediaWiki uses the skin variables system to distribute Codex tokens.

The values of these token variables differ by skin. The default Codex theme is currently used in MinervaNeue, and a modified version of the default theme for a smaller base font size (see also the section about relative values below) is used in Vector 2022 and Vector legacy. All other skins currently use fallback values defined in mediawiki.skin.defaults.less; these values are still under development. See How to make a MediaWiki skin for detailed information.

 

Example of a Less file using the Codex design tokens:

/* In 'extensions/MyExtension/resources/extension.stylesheet.less': */
@import 'mediawiki.skin.variables.less';

.my-extension-class {
    /* `@background-color-base` is one of the design tokens provided by Codex. */
    background-color: @background-color-base;
}

Note that the examples on the Codex documentation site import the tokens from '@wikimedia/codex-design-tokens/..., but this does not work in MediaWiki. Instead, you should import 'mediawiki.skin.variables.less' as shown in the example above.

Tokens with relative values edit

Tokens that express distances generally use absolute values in px, while tokens that express sizes generally use relative values in em. Tokens with relative values are designed to be used in a context where the font size is the default font size for the skin. In MinervaNeue the default font size is 16px; in Vector 2022 and Vector legacy it's 14px. Tokens with relative values are set such that they come out to the same pixel value in all skins. For example, in MinervaNeue @size-icon-medium is set to 1.25em (which is 20px at a font size of 16px), while in Vector 2022 and Vector legacy it's set to 1.42857em (which is 20px at a font size of 14px).

In most cases, the skin will set the right font size for you, but if you encounter issues with relative values producing the wrong size (typically a fractional number of pixels rather than a round number, e.g. 22.857px instead of 20px), check if the parent element's font size is different from the skin's base font size.

Using Codex Vue 3 components edit

Note that this section also includes using Codex composables.

Getting started edit

See the official docs to learn more about the available Vue 3 components, including demos and usage information (for example, see the Button component demo). Make sure to use the MediaWiki-specific code samples, since usage differs slightly in and outside of MediaWiki.

Requiring Codex components in MediaWiki and extensions edit

Codex is included in MediaWiki. There are two ways you can access Codex Vue components in your ResourceLoader module: by including only the components you need, or by requiring the entire library of components.

Subset of components edit

It is recommended only to require the components you need to improve performance. To see a working example of this system, reference the CodexExample extension.

First, make the following changes to your ResourceLoader module definition in extension.json or skin.json:

  1. Set the class to MediaWiki\\ResourceLoader\\CodexModule.
  2. Add a list of codexComponents, including all components and composables that you will be using.
"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' );

Note that if you only need the JavaScript files and not styles, you can add "codexScriptOnly": "true" to your module definition. You should only do this if you're putting the styles in another, style-only module using "codexStyleOnly": true.

Entire library edit

You can access all Codex components by adding the @wikimedia/codex ResourceLoader module to your module's dependencies.

Example of the module definition (in extension.json format):

"ext.myExtension.blockform": {
	"dependencies": [
		"@wikimedia/codex"
	]
	"packageFiles": [
		"init.js",
		"BlockForm.vue"
	],
	"messages": [
		"block-target",
		"ipb-submit"
	]
}

Then you can import components and composables as follows:

// In resources/ext.myExtension/BlockForm.vue
const { CdxButton, CdxTextInput } = require( '@wikimedia/codex' );

Using Codex components in MediaWiki and extensions edit

Once you have included Codex components as a dependency of your ResourceLoader module and required them in your Vue file, you can then pass these components to the components option of your component, and use them in your component's template. Remember that kebab-case is required in templates , so you have to use <cdx-button> for CdxButton, <cdx-text-input> for CdxTextInput, etc.

Example edit

Example of a simple block form using the CdxButton and CdxTextInput components from Codex:

<template>
    <div class="mw-block-form">
        {{ $i18n( 'block-target' ) }}
        <cdx-text-input v-model="username"></cdx-text-input>
        <cdx-button
            type="primary"
            action="destructive"
            :disabled="!isUsernameSet"
            @click="blockUser"
        >
            {{ $i18n( 'ipb-submit' ) }}
        </cdx-button>
    </div>
</template>

<script>
// This assumes you're using a subset of Codex components as described above.
const { CdxButton, CdxTextInput } = require( '../codex.js' );

// @vue/component
module.exports = exports = {
    components: {
        CdxButton,
        CdxTextInput
    },
    data: {
        username: ''
    },
    computed: {
        isUsernameSet() {
            return this.username !== '';
        }
    },
    methods: {
        blockUser() {
            // ...
        }
    }
};
</script>

Using Codex icons edit

Getting started edit

Visit the official docs site for information about the icon system and a list of all icons.

Using Codex icons in MediaWiki and extensions 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, by defining a package file as follows:

{
    "name": "icons.json",
    "callback": "MediaWiki\\ResourceLoader\\CodexModule::getIcons",
    "callbackParam": [
        // List the icons your module needs here, e.g.:
        "cdxIconArrowNext",
        "cdxIconBold",
        "cdxIconTrash"
    ]
}

These icons can then be imported in .vue files as follows:

const { cdxIconArrowNext, cdxIconBold, cdxIconTrash } = require( './icons.json' );

For more information about how to use these icons once you've imported them, see the Codex documentation on icons.

Example edit

Example of the same block form as above, but with an icon added:

<template>
    <div class="mw-block-form">
        {{ $i18n( 'block-target' ) }}
        <cdx-text-input v-model="username"></cdx-text-input>
        <cdx-button
            type="primary"
            action="destructive"
            @click="blockUser"
        >
            <cdx-icon :icon="cdxIconBlock"></cdx-icon>
            {{ $i18n( 'ipb-submit' ) }}
        </cdx-button>
    </div>
</template>
<script>
    const { CdxButton, CdxTextInput } = require( '@wikimedia/codex' );
    const { cdxIconBlock } = require( './icons.json' );
</script>

Example of the ResourceLoader module definition:

"ext.myExtension.blockform": {
	"packageFiles": [
		"init.js",
		"BlockForm.vue",
		{
			"name": "icons.json",
			"callback": "MediaWiki\\ResourceLoader\\CodexModule::getIcons",
			"callbackParam": [
				"cdxIconBlock"
			]
		}
	],
	"messages": [
		"block-target",
		"ipb-submit"
	],
	"dependencies": [
		"@wikimedia/codex"
	]
}

In this example, init.js is an init file that mounts the component with Vue.createMwApp(), as documented here.

Using 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.

Example of a Less file using a mixin:

/* In 'extensions/MyExtension/resources/extension.stylesheet.less': */
@import 'mediawiki.skin.variables.less';

.my-extension-class {
    a {
        .cdx-mixin-link-base();
    }
}

Note that the examples on the Codex documentation site import the tokens from '@wikimedia/codex-design-tokens/...' and then the relevant mixin from '@wikimedia/codex/mixins/...'but this does not work in MediaWiki. Instead, you should import 'mediawiki.skin.variables.less' as shown in the example above.

Using CSS-only Codex components edit

Some Codex components have CSS-only versions that work without JavaScript. You can check if a component has a CSS-only version by looking up the component in the Codex documentation, and seeing if there is a section named "CSS-only version". For example, the Button component has such a section. This documentation section contains examples of what the HTML for that component looks like.

To use a CSS-only component, do the following:

  1. Output the HTML for the component as shown in the component's documentation
  2. Load the appropriate ResourceLoader module containing the component styles, using addModuleStyles(). This will either be the codex-styles module, which contains the styles for all Codex components, or your own ResourceLoader module with styles for a subset of Codex components (and, if needed, your own styles).

Requiring Codex component styles edit

Subset of components edit

It is recommend only to require the components you need to improve performance. To see a working example of this system, reference the CodexExample extension.

Add a new style-only ResourceLoader module, or add to an existing one in extension.json or skin.json:

  1. Set the class to MediaWiki\\ResourceLoader\\CodexModule.
  2. Add a list of codexComponents, including all components that you will be using.
  3. Add "codexStyleOnly": "true"
"ext.myExtension.styles": {
    "class": "MediaWiki\\ResourceLoader\\CodexModule",
    "codexComponents": [
        "CdxButton",
        "CdxTextInput"
    ],
    "codexStyleOnly": "true"
}

Then, in your PHP code, load the module using addModuleStyles().

$out->addModuleStyles( 'ext.myExtension.styles' );

Entire library edit

You can access the styles for all Codex components by loading the codex-styles module in your PHP code:

$out->addModuleStyles( 'codex-styles' );

Using Codex CSS-only components edit

Simple example edit

Note that this example loads the entire codex-styles module for the sake of simplicity. In real cases where only one component is used, you should load a subset of Codex as explained above.

// Get an OutputPage object.
$out = $this->getOutput();
// Output the HTML
$out->addHTML(
    '<button class="cdx-button cdx-button--action-progressive cdx-button--weight-primary">' .
    $this->msg( 'message-for-button-label' )->escaped() .
    '</button>'
);
// Load the codex-styles module.
$out->addModuleStyles( 'codex-styles' );

Complex example edit

In SpecialFoo.php:

// Get an OutputPage object.
$out = $this->getOutput();
// Output the HTML.
$out->addHTML( <<<HTML
    <div
        class="cdx-text-input cdx-text-input--has-start-icon"
    >
        <input class="cdx-text-input__input" type="text">
        <span
            class="cdx-text-input__icon cdx-text-input__start-icon mw-special-foo-input-icon"
        ></span>
    </div>
HTML
);
// Load the codex-styles module and our own styles module.
$out->addModuleStyles( [ 'codex-styles', 'ext.specialfoo.styles' ] );

In extension.json:

{
    "ResourceModules": {
        "ext.specialfoo.styles": {
            "class": "MediaWiki\\ResourceLoader\\CodexModule",
            "codexComponents": [
                "CdxTextInput"
            ],
            "codexStyleOnly": "true",
            "styles": [
                "SpecialFoo.less"
            ]
        }
    }
}

In SpecialFoo.less:

/* Import all Codex design tokens and mixins by help of 'mediawiki.skin.variables.less'. */
@import 'mediawiki.skin.variables.less';

.mw-special-foo {
    /* ... other styles ... */

    &-input-icon {
        .cdx-mixin-css-icon( @cdx-icon-search );
    }
}

Migrating from MediaWiki UI to Codex edit

When replacing deprecated MediaWiki UI with Codex, it is recommended to use @wikimedia/codex package's CSS-only components or in some cases @wikimedia/codex-design-tokens tokens and Less mixins as replacement.

Please see the Migrating from MediaWiki UI article for detailed information.

Codex release cadence 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).

You can view all Codex tags on Gerrit or a tag timeline on GitHub. For more information about what is contained in each release, see the changelog.

See also: Design System Team/Release Timeline