Skip to content

Contributing icons

This page outlines the steps that collaborators should follow to contribute a new icon in Codex.

INFO

If you need support or have questions during the contribution process, reach out through one of the following channels:

  • Telegram: If you are an external contributor, join the Codex Telegram channel.
  • Slack: If you're an internal contributor at the Wikimedia Foundation, join the Codex Slack channel for support and collaboration.

Reporting and validating

File a task

In order to validate the need of this new icon, a new Phabricator task needs to be created. Use this icon creation task template to file the task, and provide as much information as possible.

WARNING

Create a new icon only if none of the existing icons meet your need.

Create an inventory

Collect and compare use cases to detect requirements. You can check the following relevant links in order to collect relevant information that can support the icon design process:

Validate the task

Make sure the task has been reviewed, validated, and approved before starting any work. This includes confirming that the new icon is truly needed.

Once the task is validated and the need is clearly established, you can move forward with the next steps in the contribution process.

Designing the icon

Follow Wikimedia’s guidelines

While designing the icon, follow the principles and visual styles described in our style guide. Wikimedia icons should be simple, neutral, monochromatic and front-facing.

Icons will be designed on a 20px canvas, and be either solid or use a 2px stroke if they’re outlined.

Designing icons in Figma

INFO

Duplicate this icon exploration template to work on the icon's design if needed.

Create an RTL version (if needed)

Design an RTL (or mirrored) version of the icon in case it represents horizontal directionality, lists or text. Refer to the Bidirectionality guidelines to read more about how to mirror icons.

  • Mirror icons with horizontal orientation, like the cdxIconArrowNext and cdxIconArrowPrevious

  • Mirror icons that represent lists or text.

  • Do not mirror Icons lacking clear directionality, as well as icons representing time, containing check symbols, or designed for right hand use

  • Do not mirror question mark icons or media icons such as play, pause, or rewind.

INFO

Share the icon proposal in the Phabricator task to gather feedback and iterate as needed.

Prepare for implementation

Optimize the icon

Make sure the icon meets the following requirements before exporting it:

  1. Icon strokes are outlined and converted to vector paths (learn how to do it)

Export icons vector paths

  1. All the shapes in the icon have been merged using union selection.

Shapes union selection Figma screenshot

  1. The icon is pixel perfect. You can use the pixel preview (Ctrl + P/Command + Shift + P) to verify that the icon’s strokes fit within the pixel edges. This will help you verify that the icon is recognizable in low DPI resolutions.

Pixel perfect preview Figma screenshot

  1. Once the icon’s strokes have been converted to vector paths, merged with union selection and checked using pixel preview, the icon can be flattened to group all shapes into a single vector.

Flatten the icon Figma screenshot

  1. In order to ensure that the exported icon displays the right filling and empty spaces, you’ll have to use the plugin Fill-Rule-Editor to define the fill rules of the icon’s vector objects.

Fill rule plugin Figma screenshot

Export the icon as SVG

Once the icon has been optimized, export the icon uisng this SVG Export Figma plugin. This will make sure that the icon code is as small as possible without quality loss.

  1. Find the SVG Export plugin using the “Plugins” section in Figma’s main menu and run it. Before exporting the icon, import the preset “WikimediaUI” (download link for JSON file). The import option is available from a menu in the “Presets” panel.
  2. Apply the WikimediaUI SVGO presets to the icon to be exported, then proceed to export the icon using the “Export all” button

Share the SVG icon in the Phabricator task

Include the exported SVG in the “SVG icon” section of the task so developers can easily access it for Codex. To support implementation and future updates:

  • Add a description in the “Proposal” section in the task's description to explain the icon’s design.
  • Link the Figma exploration file in the “Design spec” section for easy reference.

Implementing the icon

When adding a new icon, you should:

  1. Add the SVG file(s) for the icon to the packages/codex-icons/src/images/ directory
  2. Optimize the SVG file(s)
  3. Add the icon definition to packages/codex-icons/src/icons.ts

Naming

The icon's name should describe the icon, not its application, e.g. "bell" instead of "notification".

Icon files should be named with the icon name in lowerCamelCase, e.g. fooBar.svg or articleAdd.svg. If there are multiple SVG files for the same icon, those are named iconName-suffix.svg, e.g. imageAdd-rtl.svg or italic-i.svg (more on this below).

The variable name of the icon definition in packages/codex-icons/src/icons.ts should be in lowerCamelCase and consist of the prefix cdxIcon followed by the icon name, e.g. cdxIconArticleAdd for the "articleAdd" icon. Icon definitions in this file are in alphabetical order.

SVG conventions

Follow these conventions when crafting SVG files for icons:

  • Icons must be 20x20 pixels canvas. Set width="20" height="20" viewbox="0 0 20 20" on the <svg> element.
  • Icons should include a <title> element with the name of the icon.
  • Icons must be monochrome (only default black color), and should not hard-code this color. This means the fill attribute should not be used.

SVG optimization

Icons are also optimized using SVGO during the build process. Codex follows MediaWiki's SVG coding conventions, which are captured in the .svgo.config.js configuration file in the @wikimedia/codex-icons package root folder. Note that this optimization step overwrites the icon files in the src/images directory, and removes any <!-- comments --> in the SVG files.

To optimize the new icon file(s), run npm run minify:svg -w @wikimedia/codex-icons in the root of the codex repository. Be sure to commit the optimized file(s).

How to add each type of icon

Simple unidirectional icons

For a simple icon that doesn't vary by directionality (LTR/RTL) or language, add a single SVG file named in lowerCamelCase, e.g. articleAdd.svg, to the images/ directory. Add an icon definition to icons.ts that looks like this:

ts
import svgArticleAdd from './images/articleAdd.svg';
export const cdxIconArticleAdd = svgArticleAdd;

Automatically flipped icons

Automatically flipped icons are icons whose RTL version is a perfect mirror image of the LTR version. For these icons, we only put the LTR version in the repository, and then tell the browser to flip the icon horizontally in RTL contexts.

For example, listBullet.svg contains the LTR version of the listBullet icon: . In RTL contexts, the LTR version is displayed, but is mirrored horizontally: .

For these icons, add a single SVG file named in lowerCamelCase, e.g. listBullet.svg, to the images/ directory. This file contains the LTR version of the icon (but despite that, it doesn't have a -ltr suffix). Add an icon definition to icons.ts that looks like this:

ts
import svgListBullet from './images/listBullet.svg';
export const cdxIconListBullet: IconFlipForRtl = {
	ltr: svgListBullet,
	shouldFlip: true
};
Per-language exceptions to automatic flipping

For some icons, certain RTL languages need to use the LTR version of an icon. For example, question marks are flipped in most RTL languages, but not in Hebrew and Yiddish, so icons like help () that depict a question mark should not be flipped in those languages. To indicate this, list the RTL languages in which the icon shouldn't be flipped in the shouldFlipExceptions property, like this:

ts
import svgHelp from './images/help.svg';
export const cdxIconHelp: IconFlipForRtl = {
	ltr: svgHelp,
	shouldFlip: true,
	shouldFlipExceptions: [ 'he', 'yi' ]
};

Icons with different LTR and RTL versions

For some icons, the RTL version isn't a simple mirror image of the LTR version. For example, the listNumbered icon looks like in LTR. Flipping it automatically would look wrong, because the numbers would be mirrored too: . Instead, we need a separate SVG file for the RTL version of the icon: .

For these icons, add two SVG files to the images/ directory named with -ltr and -rtl suffixes, e.g. listNumbered-ltr.svg and listNumbered-rtl.svg. Add an icon definition to icons.ts that looks like this:

ts
import svgListNumberedLtr from './images/listNumbered-ltr.svg';
import svgListNumberedRtl from './images/listNumbered-rtl.svg';
export const cdxIconListNumbered: IconVariedByDir = {
	ltr: svgListNumberedLtr,
	rtl: svgListNumberedRtl
};

Icons with different versions per language

Some icons look different in different languages, especially those based on letters. In many cases, several languages share the same version of the icon. For example, the "bold" icon looks like in Czech, English, Hebrew, Malayalam, Polish and Scottish, but like in Kirghiz, Russian and Ukrainian, etc.

For these icons, add a separate SVG file for each version of the icon to images/, each with a suffix that describes the variant of the icon. For example, bold-b.svg, bold-f.svg, bold-cyrl-zhe.svg, etc. There may be many variants; the "bold" icon has 16.

In the icon definition in icons.ts, first import all the variant files in alphabetical order, then define which variant to use for which language, and the default variant to use for all other languages.

ts
import svgBoldA from './images/bold-a.svg';
import svgBoldB from './images/bold-b.svg';
import svgBoldCyrlZhe from './images/bold-cyrl-zhe.svg';
// … many more …

export const cdxIconBold: IconVariedByLang = {
	langCodeMap: {
		cs: svgBoldB,
		en: svgBoldB,
		he: svgBoldB,
		ml: svgBoldB,
		pl: svgBoldB,
		sco: svgBoldB,
		ky: svgBoldCyrlZhe,
		ru: svgBoldCyrlZhe,
		uk: svgBoldCyrlZhe,
		// … many more …
	},
	// 'bold-a.svg' will be used for all other languages not listed above.
	default: svgBoldA
};

Testing the new icon

Lint

After optimizing the SVG file(s), run npm run lint -w @wikimedia/codex-icons in the root of the codex repository. This will run svglint and will check your additions to icons.ts.

Testing locally

To check the new icon on the Codex docs site, run these commands from the root of the codex repository:

bash
# Build the icons package.
npm run build -w @wikimedia/codex-icons

# Serve the docs site.
npm run doc:dev

Then you can visit http://localhost:5173/icons/all-icons.html to check the list of all icons, including your new one.

Reviewing and documenting

Once the icon implementation has been completed, the contributor will need to:

  • Design sign-off: Confirm the new icon was implemented correctly.
  • Publish in Figma: Add the approved icon to the Codex Figma library for reuse in design projects. Due to team permissions in Figma, only designers in the Wikimedia Foundation Figma team can edit the library. If you are part of the team, create a Figma branch adding the new icon before publishing; if you are not, someone from the team will handle the publishing for you.