Skip to content
On this page
You're viewing the docs for the main branch of Codex, which may contain features that have not been released yet. Codex users should visit the official docs.

Adding new icons

This guide assumes you've already read through and designed your new icon according to the Design Style Guide's icon principles, the visual style guidelines and perhaps even followed the template for creating the new one before arriving on this page.

When adding a new icon, you should:

  • Add the .svg file(s) for the icon to the packages/codex-icons/src/images/ directory
  • Add the icon definition to packages/codex-icons/src/icons.ts

Naming the icon files

Icon names in icons.ts have the form cdxIconFooBar, e.g. cdxIconFullScreen. The corresponding icon files have the same name but in lowerCamelCase, e.g. fooBar.svg or fullScreen.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. The icon name should describe the icon, not its application, e.g. bell instead of notification.

SVG conventions

Follow these conventions when crafting .svg files for icons:

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

Icons are also optimized using SVGO during the build process. Codex follows MediaWiki's SVG coding convention, compare configuration in '.svgo.config.js' file in 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.

Internationalization and localization

In general the Design System's aim is to provide universal rather than culturally-specific icons. Nonetheless, in order for the system to put the user into the center, Codex allows specific overrides in its icon system to accustom directionality or language specific overrides to achieve great usability in many languages.

Simple unidirectional icons

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

ts
import svgAdd from './images/add.svg';
export const cdxIconAdd = svgAdd;

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, use a single .svg file named in lowerCamelCase, e.g. listBullet.svg. 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, use two SVG files 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, use a separate SVG file for each version of the icon, 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
};