Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Published by Scroll Versions from space TDDM and version 1

Overview

We use Tui uses SVG icons wrapped in Vue components in Tui. The icons are defined as SVG files named according to appearance (e.g. chevron-left), which are then wrapped in a Vue component with a semantic name (e.g. BackArrow).

Implementation

The SVG files are automatically optimised with SVGO as part of the build process, and pass through a webpack Webpack loader that converts them to a form that can be understood by JavaScript.

...

We then have a simple function to generate a Vue component for that icon.

Examples

Icons can be imported and used like so:

...

For icons defined in Tui, you can see a list of them all on the Tui samples page under icons/Common.

Defining a new icon in a plugin

First you'll need an SVG file. It needs to be placed under icons/internal/obj in  in order to work. If adding a custom SVG file make sure fill and stroke are set to 'currentColor' so  so it gets the right colour when using it.

Icon wrappers should go in client/component/my_plugin/src/components/icons/ and  and be named according to their semantic meaning, not appearance (e.g. Delete.js, not TrashBin.js).

Create a file like so:

Code Block
languagejs
titleAdd.js
// import an svg from bootstrap-icons in tui
import icon from '../../../tui/src/icons/internal/obj/bootstrap-icons/plus.svg';
// or one in your plugin
import icon from './internal/obj/bootstrap-icons/plus.svg';
import { createIconComponent } from 'tui/lib/svg_icon';

export default createIconComponent(icon);

Defining a new icon in Tui core

First you'll need an SVG file. It needs to be placed under icons/internal/obj in  in order to work. There are a lot under bootstrap-icons, and Totara original icons should be placed in the totara folder folder. If adding a custom SVG file make sure fill and stroke are set to 'currentColor' so  so it gets the right colour when using it.

Icon wrappers should go in client/component/tui/src/components/icons/ and  and be named according to their semantic meaning, not appearance appearance (e.g. Delete.js, not TrashBin.js).

Create a file like so:

Code Block
languagejs
titleAdd.js
import icon from './internal/obj/bootstrap-icons/plus.svg';
import { createIconComponent } from 'tui/lib/svg_icon';

export default createIconComponent(icon);

Including icons in the font library

We have used a web application called icomoon to create our fonts from SVG icons. The sources can can be found in server/theme/base/fonts/roots_font.json.zip (for the deprecated Roots/Basis theme stack) and server/theme/base/fonts/tfont.json.zip (for the newer Legacy/Ventura) theme stack. Once icons have been added and the font is regenerated, add the outputted font files into the server/theme/base/fonts directory (renaming as necessary) and the resulting SCSS files in the appropriate server/theme/base/scss/icons directory (additional naming changes may need to be done in style.scss).

Custom theme updates

Any custom themes using the following line of code will need to remove it, otherwise icons will not load. This potentially includes any custom theme that was based on Roots or Basis:

Code Block
languagephp
$THEME->parents_exclude_sheets = array(
    'base' => array('flexible-icons'), // Delete this line
);

You can find instructions on how to use the font icons in the Flexible Icons API documentation.

Tips and known limitations

  • Try to avoid any explicitly set colours as these will not update with the theme. Fill and stroke should be currentColor rather than a hex value.
  • If you need another colour, the best option is probably to add a class to the element in question and style it through CSS. The best place to put the CSS would probably be to make the wrapper file a Vue file instead of a JS file (leave out the template) and add a style block.
  • For consistency when injecting into a font library avoid using strokes (use fills instead) and masks (draw multiple objects instead).