figmage 0.1.0-dev.11 figmage: ^0.1.0-dev.11 copied to clipboard
A CLI tool for generating Figma styles for Flutter
🧙♂️ Figmage 🧙 #
A CLI tool for generating Figma styles for Flutter
What's in the box 🎁 #
Figmage is a magical CLI tool that helps you generate a flutter package from your Figma Design System. It uses the Figma APIs to fetch your design tokens from published styles, as well as variables, with full modes support.
So a variables section like this:
Is only a short figmage forge
run away from becoming code like this:
// colors.dart
import 'package:flutter/material.dart';
@immutable
class ColorsMyCollection extends ThemeExtension<ColorsMyCollection> {
const ColorsMyCollection({
required this.background,
required this.primary,
});
const ColorsMyCollection.dark()
: background = const Color(0xff665555),
primary = const Color(0xffef86a6);
const ColorsMyCollection.light()
: background = const Color(0xfffff4f4),
primary = const Color(0xff7d4052);
final Color background;
final Color primary;
@override
ColorsMyCollection copyWith([
Color? background,
Color? primary,
]) {
/// ...
}
@override
ColorsMyCollection lerp(
ColorsMyCollection other,
double t,
) {
/// ...
}
}
extension ColorsMyCollectionBuildContextX on BuildContext {
ColorsMyCollection get colorsMyCollection =>
Theme.of(this).extension<ColorsMyCollection>()!;
}
Features #
- ✨ Generate a Flutter package from your Figma Design System
- 🎨 Supports many types of tokens:
- 🌈 Color styles and variables
- 🖋️ Typography styles (with optional
google_fonts
support!) - 🔢 Number variables, which can be generated as Paddings, and Spacers as well
- 🌓 Modes support for variables: Generate different tokens for different themes (e.g. dark/light)
- 📦 Package generation: All your tokens end up in one convenient package. Depend on it from your app, and update it whenever neccessary!
- 🤝 Seamless integration with
Theme
s frommaterial.dart
: Generated classes areThemeExtension
s, so they can be integrated into your app's theme easily! - 🎯 Quick access using
BuildContext
extensions. - 🔮 Portable: figmage is a pure dart package, so it can easily be integrated into your CI/CD pipelines, to automatically fetch the latest tokens of your project for you!
Installation 💻 #
❗ In order to start using Figmage you must have the Dart SDK installed on your machine.
For the easiest usage, install figmage via dart pub global activate
:
dart pub global activate figmage
How to generate 🏭 #
🚀 Quick start #
Create a folder in which you want your generated package to live. For example:
mkdir packages/my_design_system
cd packages/my_design_system
This command will generate a new package at the specified output path using the provided Figma API token and file ID:
figmage forge --token <token> --fileId <fileId>
Note
🤔 Wait, what's a token? And what's this file ID? Where do I get them?
To interact with the Figma API, you'll need an access token. Check out the Figma Docs to learn how to create yours.
The fileId is part of the URL when you open a Figma file. Just look in your browser's address bar when you have your design system file open, it's usually structured like this: ➡ figma.com/design/your-file-id-is-here/more-not-so-interesting-stuff
🎨 Details #
If you require more control over the generated code, create a figmage.yaml
file in the directory in which you want the package to be generated. This file will then always live next to the pubspec.yaml
of the generated package.
Below is an example, along with descriptions of what each flag accomplishes:
# The Figma file ID from which to generate tokens. If you set this here, you won't need to pass it as a flag.
fileId: "YOUR_FIGMA_FILE_ID"
# The name of the generated Dart package. Will use the current directory name if not provided.
packageName: "my_design_system"
# Description of the generated package. No description will be generated by default.
packageDescription: "A package generated from Figma designs."
# Default: true. Determines whether to drop unresolvable values. When true, values that cannot be resolved (e.g., an alias pointing to a missing variable) are omitted, ensuring all tokens are resolvable in all modes (e.g., light and dark mode). When false, unresolved variables are included but will return null. Defaults to false.
dropUnresolved: true
# Whether to fetch only the styles that were published to the library.
# Defaults to false, meaning the file's local styles will be fetched.
stylesFromLibrary: false
colors:
# Default: true. Whether to generate color tokens.
generate: true
# Default: []. Specific paths to generate color tokens from.
from:
- "colors/path"
typography:
# Default: true. Whether to generate typography tokens.
generate: true
# Default: []. Specific paths to generate typography tokens from.
from:
- "typography/path"
# Default: true. Whether to use Google Fonts for font families.
useGoogleFonts: true
numbers:
# Default: false. Whether to generate number tokens (for spacers, paddings, borders).
generate: false
# Default: []. Specific paths to generate number tokens from.
from:
- "numbers/path"
spacers:
# Default: false. Whether to generate spacer tokens from all generated number tokens (see above).
generate: false
paddings:
# Default: false. Whether to generate padding tokens from all generated number tokens (see above).
generate: false
Warning
Spacers and Paddings will always be generated for all included number tokens for now. Any from
paths specified for spacers
and paddings
will be ignored. See this issue for more information.
How to use 📲 #
Next, let's see how you can integrate the generated package into your Flutter app.
🚀 Quick start #
To integrate your newly minted token package into your app, simply add it to your pubspec.yaml
file:
figmage_package:
path: path/to/your/package
You can now add the generated ThemeExtension
s to your app's theme.
Incorporate design tokens into your code as follows:
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.light().copyWith(
extensions: <ThemeExtension<dynamic>>[
ColorsDesignSystem.dark(), // <- added
TypographyDesignSystem.standard(), // <- added
],
),
darkTheme: ThemeData.dark().copyWith(
extensions: <ThemeExtension<dynamic>>[
ColorsDesignSystem.dark(), // <- added
TypographyDesignSystem.standard(), // <- added
],
),
themeMode: isLightTheme ? ThemeMode.light : ThemeMode.dark,
home: Home(
isLightTheme: isLightTheme,
toggleTheme: toggleTheme,
),
);
}
Leverage the tokens within your widgets like so:
@override
Widget build(BuildContext context, WidgetRef ref) {
final colors = context.colorsDesignSystem;
final typography = context.typographyDesignSystem;
return Container(
color: colors.primary,
child: Text('Hello world!', style: typography.body1),
)
...
🎨 Details #
Design tokens are encapsulated within classes based on their type and collection for variable-based tokens or style group name for style-based tokens. Each class implements BuildContext
extension which can be used to propagate the design tokens through your app.