Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions .claude/EXFIG.toon
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
meta:
name: ExFig
version: current
description: CLI tool for exporting Figma assets to iOS, Android, Flutter
description: CLI tool for exporting Figma assets to iOS, Android, Flutter, Web
swift: 6.0
platforms: macOS 12.0+, Linux
license: MIT
Expand Down Expand Up @@ -54,7 +54,7 @@ commands:
init:
purpose: Generate starter config file
options:
platform: -p/--platform ios|android (required)
platform: -p/--platform ios|android|flutter|web (required)

batch:
purpose: Process multiple configs in parallel
Expand Down Expand Up @@ -107,13 +107,14 @@ commands:
failFast: --fail-fast
resume: --resume

modules[7]{name,path,purpose}:
modules[8]{name,path,purpose}:
ExFig,Sources/ExFig,CLI commands and orchestration
ExFigCore,Sources/ExFigCore,Domain models and processors
FigmaAPI,Sources/FigmaAPI,HTTP client with rate limiting
XcodeExport,Sources/XcodeExport,iOS xcassets and Swift extensions
AndroidExport,Sources/AndroidExport,Android XML and Compose code
FlutterExport,Sources/FlutterExport,Flutter Dart code
WebExport,Sources/WebExport,Web CSS variables and React/TypeScript
SVGKit,Sources/SVGKit,SVG parsing and vector generation

keyDirectories:
Expand All @@ -132,7 +133,7 @@ configTypes:
IconsConfiguration:
purpose: Enum for backward-compatible icons config parsing
cases: [single(Icons), multiple([IconsEntry])]
platforms: [iOS, Android, Flutter]
platforms: [iOS, Android, Flutter, Web]
properties:
entries: "[IconsEntry] - unified access to all entries"
isMultiple: "Bool - true if array format"
Expand All @@ -145,7 +146,7 @@ configTypes:
IconsLoaderConfig:
purpose: Sendable struct for IconsLoader frame settings
file: Sources/ExFig/Loaders/IconsLoader.swift
factoryMethods: [forIOS, forAndroid, forFlutter, defaultConfig]
factoryMethods: [forIOS, forAndroid, forFlutter, forWeb, defaultConfig]

keyFiles:
cli: Sources/ExFig/ExFigCommand.swift
Expand Down Expand Up @@ -237,11 +238,12 @@ templates:
ios[10]: UIColor+extension, Color+extension, UIFont+extension, Font+extension, UIImage+extension, Image+extension, Label, LabelStyle, LabelStyle+extension, header
android[6]: colors.xml, Colors.kt, typography.xml, Typography.kt, Icons.kt, header
flutter[4]: colors.dart, icons.dart, images.dart, header
web[8]: theme.css, variables.ts, theme.json, Icon.tsx, types.ts, IconIndex.ts, Image.tsx, ImageIndex.ts, header

config:
files: exfig.yaml, figma-export.yaml
envVar: FIGMA_PERSONAL_TOKEN
sections: figma, common, ios, android, flutter
sections: figma, common, ios, android, flutter, web
reference: CONFIG.md

buildCommands:
Expand Down Expand Up @@ -281,11 +283,12 @@ figmaAPI:
tier3: 50-150 req/min
docs: https://www.figma.com/developers/api

testTargets[7]{name,tests}:
testTargets[8]{name,tests}:
ExFigTests,CLI commands and loaders
ExFigCoreTests,Domain models and processors
XcodeExportTests,iOS export output
AndroidExportTests,Android export output
FlutterExportTests,Flutter export output
WebExportTests,Web CSS and React/TypeScript output
FigmaAPITests,API client and endpoints
SVGKitTests,SVG parsing and code generation
106 changes: 106 additions & 0 deletions CONFIG.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,64 @@ flutter:
encoding: lossy
# Encoding quality in percents. Only for lossy encoding.
quality: 90

# [optional] Web export parameters (React/TypeScript)
web:
# Relative or absolute path to the output directory for generated files
output: "./src/generated"
# [optional] Path to the Stencil templates used to generate code
templatesPath: "./templates"

# Parameters for exporting colors
colors:
# [optional] Output file name for CSS variables. Defaults to "theme.css"
cssFile: "theme.css"
# [optional] Output file name for TypeScript constants. Defaults to "variables.ts"
tsFile: "variables.ts"
# [optional] Output file name for JSON tokens. When specified, exports colors as JSON
jsonFile: "tokens.json"

# Parameters for exporting icons
# Can be a single object (legacy format) or an array of objects (new format)
# Legacy format (single icons configuration):
icons:
# [optional] Where to place SVG icon assets (relative path)
assetsDirectory: "assets/icons"
# [optional] Generate React TSX components for each icon. Defaults to true
generateReactComponents: true
# [optional] Export types.ts with TypeScript interfaces. Defaults to true
exportTypes: true
# [optional] Icon size in pixels for viewBox. Defaults to 24
iconSize: 24

# New format (multiple icons configurations from different Figma frames):
# icons:
# - figmaFrameName: Actions # Export icons from "Actions" frame
# assetsDirectory: "assets/icons/actions"
# generateReactComponents: true
# iconSize: 24 # Icon size for viewBox
# - figmaFrameName: Navigation # Export icons from "Navigation" frame
# assetsDirectory: "assets/icons/nav"
# generateReactComponents: true
# iconSize: 20 # Different icon size for navigation

# Parameters for exporting images
# Can be a single object (legacy format) or an array of objects (new format)
# Legacy format (single images configuration):
images:
# [optional] Where to place image assets (relative path)
assetsDirectory: "assets/images"
# [optional] Generate React TSX components for each image. Defaults to true
generateReactComponents: true

# New format (multiple images configurations from different Figma frames):
# images:
# - figmaFrameName: Illustrations
# assetsDirectory: "assets/images/illustrations"
# generateReactComponents: true
# - figmaFrameName: Promo
# assetsDirectory: "assets/images/promo"
# generateReactComponents: true
```

## Multiple Icons Configuration
Expand Down Expand Up @@ -392,6 +450,22 @@ When using multiple entries with the same Figma file:
This means 17 icon entries with the same `lightFileId` result in only 1 Components API call (plus 1 Images API call per
unique frame), not 17 separate calls.

### Web Icons Array Format

```yaml
web:
icons:
- figmaFrameName: Actions
assetsDirectory: assets/icons/actions
generateReactComponents: true
iconSize: 24
- figmaFrameName: Navigation
assetsDirectory: assets/icons/nav
generateReactComponents: true
exportTypes: true
iconSize: 20
```

## Multiple Colors Configuration

ExFig supports exporting colors from multiple Figma Variable collections in a single config file. This is useful when
Expand Down Expand Up @@ -493,6 +567,25 @@ flutter:
className: ThemeColors
```

### Web Colors Array Format

```yaml
web:
colors:
- tokensFileId: abc123
tokensCollectionName: Base Palette
lightModeName: Light
cssFile: base-theme.css
tsFile: base-variables.ts
- tokensFileId: def456
tokensCollectionName: Theme Colors
lightModeName: Light
darkModeName: Dark
cssFile: theme.css
tsFile: theme-variables.ts
jsonFile: theme-tokens.json
```

## Multiple Images Configuration

ExFig supports exporting images from multiple Figma frames in a single config file. This is useful when your design
Expand Down Expand Up @@ -575,6 +668,19 @@ flutter:
scales: [1, 2, 3]
```

### Web Images Array Format

```yaml
web:
images:
- figmaFrameName: Illustrations
assetsDirectory: assets/images/illustrations
generateReactComponents: true
- figmaFrameName: Promo
assetsDirectory: assets/images/promo
generateReactComponents: true
```

### Fallback Behavior

If `figmaFrameName` is not specified in an entry, it falls back to:
Expand Down
16 changes: 16 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ let package = Package(
"XcodeExport",
"AndroidExport",
"FlutterExport",
"WebExport",
"SVGKit",
.product(name: "XcodeProj", package: "XcodeProj"),
.product(name: "ArgumentParser", package: "swift-argument-parser"),
Expand Down Expand Up @@ -95,6 +96,15 @@ let package = Package(
]
),

// Exports resources to Web/React project
.target(
name: "WebExport",
dependencies: ["ExFigCore", "Stencil", "StencilSwiftKit"],
resources: [
.copy("Resources/"),
]
),

// MARK: - Tests

.testTarget(
Expand Down Expand Up @@ -142,6 +152,12 @@ let package = Package(
"FlutterExport", .product(name: "CustomDump", package: "swift-custom-dump"),
]
),
.testTarget(
name: "WebExportTests",
dependencies: [
"WebExport", .product(name: "CustomDump", package: "swift-custom-dump"),
]
),
.testTarget(
name: "SVGKitTests",
dependencies: ["SVGKit", .product(name: "CustomDump", package: "swift-custom-dump")]
Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
[![CI](https://github.com/alexey1312/ExFig/actions/workflows/ci.yml/badge.svg)](https://github.com/alexey1312/ExFig/actions/workflows/ci.yml)
[![Release](https://github.com/alexey1312/ExFig/actions/workflows/release.yml/badge.svg)](https://github.com/alexey1312/ExFig/actions/workflows/release.yml)
[![Docs](https://github.com/alexey1312/ExFig/actions/workflows/deploy-docc.yml/badge.svg)](https://alexey1312.github.io/ExFig/documentation/exfig)
![Coverage](https://img.shields.io/badge/coverage-51.30%25-yellow)
![Coverage](https://img.shields.io/badge/coverage-50.19%25-yellow)
[![License](https://img.shields.io/github/license/alexey1312/ExFig.svg)](LICENSE)

Command-line utility to export colors, typography, icons, and images from Figma to Xcode, Android Studio, and Flutter
projects.
Command-line utility to export colors, typography, icons, and images from Figma to Xcode, Android Studio, Flutter, and
Web (React/TypeScript) projects.

Automatically sync your design system from Figma to code with support for Dark Mode, SwiftUI, UIKit, Jetpack Compose,
and Flutter.
Flutter, and React/TypeScript.

## Why ExFig?

Expand All @@ -38,6 +38,7 @@ and Flutter.
- 📱 SwiftUI and UIKit (iOS/macOS)
- 🤖 Jetpack Compose and XML resources (Android)
- 🦋 Flutter / Dart
- 🌐 React / TypeScript (CSS variables, TSX components)
- 🔧 Customizable code templates (Stencil)

### Export Formats
Expand Down
Loading
Loading