Skip to content

Commit

Permalink
Merge pull request #4 from freemansoft/feature/support-json-file-sets
Browse files Browse the repository at this point in the history
support sets of JSON files
  • Loading branch information
mark-nicepants committed Nov 4, 2023
2 parents a8958ba + 716660c commit 5d2053b
Show file tree
Hide file tree
Showing 56 changed files with 13,542 additions and 113 deletions.
37 changes: 31 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This package converts [Tokens Studio for Figma](https://docs.tokens.studio/) jso
- [Composition support](#composition-support)
- [CompositionToken.toInputDecoration](#compositiontokentoinputdecoration)
- [Token support for composition tokens](#token-support-for-composition-tokens)
- [Examples](#examples)
- [Realised feature ideas](#realised-feature-ideas)
- [Ideas for contributing](#ideas-for-contributing)

Expand All @@ -31,25 +32,43 @@ This package converts [Tokens Studio for Figma](https://docs.tokens.studio/) jso
dart pub global activate figma2flutter
```

## 2. Export
## 2. Export

Export your tokens from Figma and save the json file in your project folder.

You can do this manually or use the [Tokens Studio for Figma](https://docs.tokens.studio/) plugin to export your tokens directly into your repository.

## 3. Generate
figma2flutter supports design token definitions made up of a single json file or defined as a folder of JSON files.

### When using a single JSON design token file that contains $metadata, $theme and defintions
Run the command in the root of your project
```bash
figma2flutter --input <path_to_json_file> --output <path_to_output_folder>
```

Default config values are:

```bash
--input: ./design/tokens.json
--output: ./lib/assets/tokens/
```

### When using a folder of JSON design token files
Multi-file support assumes that the input folder containing the JSON token files, a `$metadata` file, a `$themes` file.

Run the command in the root of your project
```bash
figma2flutter --input <path_to_json_folder> --output <path_to_output_folder>
```

Default config values are:

```bash
--input: ./design/tokens
--output: ./lib/assets/tokens/
```

## 4. Add to your project

Wrap your app in a Tokens widget and pass in a generated ITokens theme. See example for more details.
Expand Down Expand Up @@ -91,7 +110,7 @@ Now you can use your tokens in your app! 🎉
-[color](https://docs.tokens.studio/available-tokens/color-tokens)
-[Solid](https://docs.tokens.studio/available-tokens/color-tokens#solid-colors) (output = Color)
- ✅ hex
- ✅ rgb
- ✅ rgb
- ✅ rgba
- ✅ hsla
-[Gradients](https://docs.tokens.studio/available-tokens/color-tokens#gradients)
Expand Down Expand Up @@ -121,7 +140,7 @@ Now you can use your tokens in your app! 🎉
-[border](https://docs.tokens.studio/available-tokens/border-tokens)
-[borderWidth](https://docs.tokens.studio/available-tokens/border-width-tokens)
- ✅ color
- ✅ style
- ✅ style
- ✅ solid
- ~~dashed~~ (not supported but PRs's are welcome)

Expand All @@ -131,7 +150,7 @@ Tokens Studio supports math operations on tokens. This package supports the foll

A math expression can be used to combine multiple tokens. For example: `{primary} + {tokens.secondary}` will result in a color that is the sum of the primary and secondary color. Each math operation needs to have atleast 1 token on the left side. The right side can be a token or a number. Eg `{primary} + 10` or `{primary} + {secondary}`.

To be able to parse properly the math expression, the tokens need to be wrapped in `{}`. And the operation must be properly spaced to the left and to the right (e.g. ` + ` instead of `+ `).
To be able to parse properly the math expression, the tokens need to be wrapped in `{}`. And the operation must be properly spaced to the left and to the right (e.g. ` + ` instead of `+ `).

- [math operations](https://docs.tokens.studio/tokens/using-math)
- ✅ add
Expand Down Expand Up @@ -235,13 +254,19 @@ You can use composition tokens as `InputDecoration` in `TextField` and `TextForm
- ✅ lineHeights
- ✅ letterSpacing

# Examples

-**Example 1** A Flutter application whose styles and themes were generated from the design token JSON file in the example bin directory. It includes the generated dart files.
-**Example 2** A design token and generated code example that demonstrates generating themes from a _set_ of design token files including seperate `$metadata` and `$themes` files. No Flutter app is included. It includes the generated dart files.


# Realised feature ideas

-**Generate MaterialColors** when we have multiple color values and int base keys (100, 200, 300, 400)
-**Add an example** that illustrates how to use the package (see `/example` folder and `/example/bin/update-tokens.sh`)
- ✅ Figure out a way to convert tokens to **InputDecorations** or even an InputDecorationTheme.
- ✅ Add example json to the repo that makes it easy to start with the package and Figmas Tokens Studio plugin
-
-
# Ideas for contributing

- Generate a Theme.TextTheme with all tokens that match the [material3 spec](https://m3.material.io/styles/typography/type-scale-tokens#d74b73c2-ac5d-43c5-93b3-088a2f67723d). This would allow us to use the tokens as a theme for the whole app.
Expand Down
52 changes: 45 additions & 7 deletions bin/figma2flutter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import 'package:figma2flutter/transformers/size_transformer.dart';
import 'package:figma2flutter/transformers/spacing_transformer.dart';
import 'package:figma2flutter/transformers/typography_transformer.dart';
import 'package:figma2flutter/utils/sets_and_themes.dart';
import 'package:path/path.dart';

/// Code for making terminal output foreground red
const _red = '\x1b[033;0;31m';
Expand Down Expand Up @@ -53,17 +54,38 @@ Future<void> main(List<String> arguments) async {
final options = await ArgumentParser(arguments).parse();

/// Get the input json file and output directory from the parsed arguments
final inputJson = options.getOption<String>(kInput).value;
final inputFileLocation = options.getOption<String>(kInput).value;
final outputDir = options.getOption<String>(kOutput).value;

// Should remove the defaults because you get weird errors for data you didn't know about
if (inputFileLocation.isEmpty) {
_print('Missing parameter -i input file');
exit(-1);
}
if (outputDir.isEmpty) {
_print('Missing parameter -o output directory');
exit(-1);
}

// To be able to debug the example app, uncomment the following lines and
// comment the lines above. Then run main in debug mode.
// final inputJson = 'example/bin/example-themes.json';
// final outputDir = 'example/lib/generated';

/// Parse the input json file and get all resolved tokens from the parser
try {
final themes = _parseInput(inputJson);
List<TokenTheme> themes;
if (FileSystemEntity.isDirectorySync(inputFileLocation)) {
_print(
'Loading `\$metadata`, `\$themes` and design token files from $inputFileLocation',
_green);
_print(''); // New line
themes = _parseFromFileSet(inputFileLocation);
} else {
_print('Loading design tokens from $inputFileLocation', _green);
_print(''); // New line
themes = _parseInputFromFile(inputFileLocation);
}

/// Print the number of tokens found to the terminal output
_print('Found ${themes.length} themes, generating code', _green);
Expand Down Expand Up @@ -112,16 +134,32 @@ List<TokenTheme> _processTokens(List<TokenTheme> themes) {
return processor.themes;
}

/// Parses the input from the files in tokenFileDirectory and returns list of resolved tokens
List<TokenTheme> _parseFromFileSet(String tokenFileDirectory) {
Map<String, dynamic> inputJson =
arrangeJsonFilesBySection(tokenFileDirectory);
final themes = _parseInputJson(inputJson);
return themes;
}

/// Parses the input json file and returns a list of resolved tokens
List<TokenTheme> _parseInput(String inputJson) {
List<TokenTheme> _parseInputFromFile(String inputJsonLocation) {
final input = json.decode(
File(inputJson).readAsStringSync(),
File(inputJsonLocation).readAsStringSync(),
) as Map<String, dynamic>;
return _parseInputJson(input);
}

/// Accepts input json loaded from somewhere and returns list of resolved tokens
List<TokenTheme> _parseInputJson(Map<String, dynamic> inputJson) {
final setOrder = getSetsFromJson(inputJson);
final themes = getThemesFromJson(inputJson);

final setOrder = getSetsFromJson(input);
final themes = getThemesFromJson(input);
// _print('inputJson: ${inputJson.keys}');
// _print('setOrder: $setOrder');
// _print('themes: $themes');

final parser = TokenParser(setOrder, themes)..parse(input);
final parser = TokenParser(setOrder, themes)..parse(inputJson);

return parser.themes;
}
Expand Down
15 changes: 4 additions & 11 deletions example/README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
# example
# figma2flutter example application.

A new Flutter project.
Sample flutter app that demonstrates creating theme from design tokens and using that theme in a simple application.

## Getting Started

This project is a starting point for a Flutter application.
1. This application uses the generated themes located in [lib/generated](lib/generated).
1. The theme was generated using the [script](bin/update-tokens.sh) and [example-themes.json](bin/example-themes.json) definitions in the [bin](bin) directory. Comments in the script describe how to execute it. The script and json files are outside of teh lib directory because the app will only include the generated dart files and not the design token json files.

A few resources to get you started if this is your first Flutter project:

- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)

For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
10 changes: 4 additions & 6 deletions example/bin/update-tokens.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
#!/bin/bash

# Fetch tokens from somewhere via wget of git clone
# ---

# Install (or update) figma2flutter dart package
# Disabled, this project already has it locally in ../bin
# pub global activate figma2flutter
#
# No need to install figma2flutter, this example project has it locally in ../bin

# Run `figma2flutter` to generate Flutter content from given tokens
# figma2flutter -o ./lib/ui/utils
# Run `figma2flutter` to generate Flutter content from given token json files
# The script assumes this is being run from the root of the `example`

dart ../bin/figma2flutter.dart -i ./bin/example-themes.json -o ./lib/generated

Expand Down
38 changes: 19 additions & 19 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ packages:
dependency: transitive
description:
name: collection
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
url: "https://pub.dev"
source: hosted
version: "1.17.1"
version: "1.17.2"
cupertino_icons:
dependency: "direct main"
description:
Expand Down Expand Up @@ -75,14 +75,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
js:
dependency: transitive
description:
name: js
sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3
url: "https://pub.dev"
source: hosted
version: "0.6.7"
lints:
dependency: transitive
description:
Expand All @@ -95,18 +87,18 @@ packages:
dependency: transitive
description:
name: matcher
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
url: "https://pub.dev"
source: hosted
version: "0.12.15"
version: "0.12.16"
material_color_utilities:
dependency: transitive
description:
name: material_color_utilities
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
url: "https://pub.dev"
source: hosted
version: "0.2.0"
version: "0.5.0"
meta:
dependency: transitive
description:
Expand All @@ -132,10 +124,10 @@ packages:
dependency: transitive
description:
name: source_span
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.dev"
source: hosted
version: "1.9.1"
version: "1.10.0"
stack_trace:
dependency: transitive
description:
Expand Down Expand Up @@ -172,10 +164,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
url: "https://pub.dev"
source: hosted
version: "0.5.1"
version: "0.6.0"
vector_math:
dependency: transitive
description:
Expand All @@ -184,5 +176,13 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
web:
dependency: transitive
description:
name: web
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
url: "https://pub.dev"
source: hosted
version: "0.1.4-beta"
sdks:
dart: ">=3.0.0 <4.0.0"
dart: ">=3.1.0-185.0.dev <4.0.0"
2 changes: 1 addition & 1 deletion example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ publish_to: 'none'
version: 1.0.0+1

environment:
sdk: '>=2.19.2 <3.0.0'
sdk: '>=2.19.2 <4.0.0'

dependencies:
flutter:
Expand Down
14 changes: 14 additions & 0 deletions example2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
An example without an app that demonstrates mult-file Json design tokens.
Complete Design Token defitions are often delivered as multiple definition files that are stitched together to provide complete definitions.
The merged information from multiple files exactly matches the structure of a set of design tokens defined in a single file.

## Running example2

Run the following from the example2 directory or run the script in bin. It will generate token defition classes

`dart ..\bin\figma2flutter.dart -i .\bin\tokens\ -o .\lib\generated\`

## Assumptions
1. `bin\tokens` contains some number of design token json files and contorl files.
1. `$metadata.json` file that describes the locations of all the files to include.
1. `$themes.json` that describes the themes and which json files are included in each theme.
22 changes: 22 additions & 0 deletions example2/bin/tokens/$metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"tokenSetOrder": [
"global",
"semantic",
"comp/button",
"comp/list-item",
"comp/menu-item",
"comp/toggle",
"pattern/menu-bar",
"pattern/feature",
"pattern/card-user",
"pattern/card-pricing",
"sections/nav",
"sections/hero",
"sections/features",
"sections/team",
"sections/pricing",
"sections/footer",
"theme/light",
"theme/dark"
]
}
Loading

0 comments on commit 5d2053b

Please sign in to comment.