fms (Flutter-Material-Symbols)
An simple CLI tool that brings Google’s Material Symbols to your Flutter projects. It generates an icon font and its wrapper class from a single configuration file.
Motivation
In the latest version of MaterialDesign, Material3, Material Symbols was introduced in place of Material Icons. However, Flutter does not yet support Material Symbols officially. Although they are being supported, it will be some time before being bundled in the stable version.
Fortunately, Material Symbols is OSS and all the resources are available on Github. You can also see a list of available symbols on their official website. You can incorporate Material Symbols into your Flutter project right away by downloading the SVG files of the symbols you need from the website.
On the other hand, Material Icons are provided by the Flutter Framework as Icons
class and can be used as easily and type-safty as Icons.home
. How can we achieve the same thing with Material Symbols? First download the SVGs, convert them to a font file, then create a corresponding Dart wrapper class, and…. Yes, this is a very tedious process.
With fms (flutter-material-symbols) you can automatically generate these files from a single configuration file. There is no need to download and manage resources manually.
Why “generate”?
Why does fms take the trouble to generate font files instead of providing a class like Icons
? Material symbols has 2400+ icons and they are all customizable with 5 parameters. In addition, each parameter has at least 2 possible values. Therefore It is obvious that the number of possible combinations of the symbols and the parameters is enormous. If we create a class wchich provides all the variants of symbols as static member variables, a huge font file that contains all variant data must be included in the package. That’s inpractical. Instead, fms generates a font file that contians only as much data as you needed.
Index
Preface
One of the main functions of this package is heavily based on the following packages:
- fantasticon A node.js package that converts multiple SVG files into a single icon font. It is used to generate an icon fonts from SVGs of symbols. Therefore, node.js of version 11 or later must be enabled.
- icon_font_generator Wrapper library for fantasticon’s Dart. It is used to generate icon font wrapper classes.
Install
You can install fms from Pub.dev using pub
command.
$ flutter pub add --dev fms
Make sure that node.js of version 11 or later is installed.
$ node --version
v18.12.1
Getting started
-
Write a configuration file
# project_root/my_symbols.yaml family: MySymbols output: flutter: lib/src/my_symbols.dart font: assets/my_symbols.ttf symbols: home: Home home_selected: name: Home fill: true
-
Generate an Icon font and its wrapper class
The following command generates an icon font in
assets/my_symbols.ttf
and its wrapper class inlib/src/my_symbols.dart
.$ flutter pub run fms build my_symbols.yaml
-
Add generated icon font to your Flutter project
Add the information of the generated font to
pubspec.yaml
so that Flutter can use it. Don’t forget to also add the font file to your assets in theassets:
section if you put them somewhere other thanlib/
(e.g.assets/
).... flutter: assets: - assets/ fonts: - family: MySymbols fonts: - asset: assets/my_symbols.ttf
-
Use generated icons
You can use the icons in Dart code via
MySymbols
class which is defined in generatedmy_symbols.dart
.import 'package:your_package/src/my_symbols.dart'; import 'package:flutter/material.dart'; Widget homeNaviDest() { return NavigationDestination({ icon: const Icon(MySymbols.home), selectedIcon: const Icon(MySymbols.home_selected), }); }
How to use
Syntax of configuration file
A configuration file is written in YAML. One configuration file corresponds to one icon font and its wrapper class, respectively.
A configuration file consists of the following four sections:
family: ... # Family name
output: ... # Output destinations
symbols: ... # Define symbol instances
default: ... # Overrides default parameters(optional)
Family Name
In family:
section, specify the family name of an icon font to be generated.
family: MySymbols
This is also used as the name of the wrapper class, so it must be an appropriate identifier in Dart (usually UpperCamelCase). Therefore names that begin with a number, or contain special characters, or spaces cannot be used, as shown below:
10Symbols
MySymbols#1
My Symbols
Output destinations
The output destinations for a generated icon font and its wrapper class is specified in output:
section.
output:
flutter: lib/src/my_symbols.dart # Wrapper class
font: assets/my_symbols.ttf # Icon font
Define symbol instances
In symbols:
section, you can define symbol instances: the instances of the symbols you want to use. A symbol instance is a set of the name of a symbol and its parameters. Every instance also has a unique identifier within the family.
-
Symbol Name
Every symbol has a unique name (e.g.
Home
,Calendar Month
). Available symbol names can be found in the official gallery site. Be careful about case, whitespaces, etc. (e.g.calendarMonth
is wrong,Calendar Month
is correct). -
Parameters
Material Symbols are variable fonts. Each symbol can be customized by adjusting five parameters. See the offcial site to see how each parameter works.
-
Identifier
Each instance also has an identifier which is unique in thier family. This will be the variable name of the generated wrapper class, so it must be an appropriate identifier for Dart. fms supports both snake_case and lowerCamelCase, but the two styles cannot be mixed in a family.
Let’s start with a simple example. The following snippet defines an instance of Home
symbol and name it as home
. The symbol name is specified in the name:
section.
symbols:
home: # Identifier
name: Home # Symbol name
Next, customize symbols with parameters. Material Symbols supports five parameters: style, weight axis, fill axis, grade axis, and optical-size axis.
symbols:
home:
name: Home
style: outlined # style
weight: 400 # weight axis
fill: false # fill axis
grade: 0 # grade axis
size: 48px # optical-size axis
The possible values for each parameter section are as follows:
PARAMETER | SECTION | VALUE |
---|---|---|
Style | style: |
outlined , rounded , sharp |
Weight axis | weight: |
100 , 200 , … , 700 |
Fill axis | fill: |
true , false |
Grade Axis | grade: |
-25 , 0 , 200 |
Optical-size axis | size: |
20px , 24px , 40px , 48px |
All of the parameters are optional and may be omitted. Parameters whose value is not specified will have the default values. The default values are style: outlined
、weight: 400
、fill: false
、grade: 0
、size: 48px
, respectively. The following is an example of creating two different Home
symbols (home
and home_selected
) to be used for tabs of NavigationBar.
symbols:
home: # Equivalent to "fill: false"
name: Home
home_selected:
name: Home
fill: true
The name:
section can also be omitted if none of the parameters are specified. In such a case, the identifier and symbol name should be written in key-value format. The above example can be rewritten in abbreviated form as follows:
symbols:
home: Home # "name:" section is ommited
home_selected:
name: Home
fill: true
Overrides default parameters
Use default:
section to overrides the default value of each parameter. The values specified here will be used as the new default parameters. For example, to change the default value of style from outlined
to rounded
and the default value of weight axis
from 400
to 500
, write the following.
default:
style: rounded
weight: 500
The default:
section is optional and can be omitted.
Commands
fms has 2 subcommands: build
and clean
.
build
Use build
to generate an icon font and its wrapper class from a configuration file. Node.js is required for the command to work. If you do not have it, please install it first.
$ flutter pub run fms build your_config_file.yaml
Available options are:
-
--prefer-camel-case
.Use lowerCamelCase for identifiers of symbol instances instead of snake_case.
-
-f
,--force
.Download resource files even if the cache is available.
-
--use-yarn
.Use
yarn
as a node.js package manager instead ofnpm
.
Generate multiple icon fonts
One configuration file corresponds to one icon font and its wrapper class respectively. If you want to generate multiple icon fonts, write multiple configuration files too. Make sure that the family names must be unique within your project.
You can pass multiple configuration files to build` command, so there is no need to call the command multiple times.
$ flutter pub run fms first_symbols.yaml second_symbols.yaml
clean
Downloaded SVG files are cached in <project_root>/.dart_tool/
. Use the clean
to delete them.
$ flutter pub run fms clean
Contribution
Any kind of contribution is welcome. Suggestions for my english are also helpful to improve the quality of the document.