carpenter_mordant 0.3.0
carpenter_mordant: ^0.3.0 copied to clipboard
Typed design tokens and YAML code generation for Flutter.
Carpenter Mordant #
Typed design tokens and YAML code generation for Flutter.
Mordant turns declarative token files into strongly typed Dart APIs.
Installation #
Add Mordant:
dependencies:
carpenter_mordant: ^0.1.0
dev_dependencies:
build_runner: any
Basic usage #
Create a Mordant file under lib:
# lib/tokens/tokens.mordant.yaml
palette:
brand:
500: "#987654"
600: "#825E4A"
space:
sm: 0.5rem
md: 1rem
button:
primary:
background: "${palette.brand[500]}"
padding: "${space.md}"
Generate Dart code:
dart run build_runner build --delete-conflicting-outputs
Mordant generates:
lib/tokens/tokens.mordant.g.dart
The generated API can be used directly:
palette.brand[500
]
palette.brand[600
]
space.md
button.primary.background
button.primary.padding
Unit tokens integrate with carpenter_units and resolve through an explicit
runtime context:
final padding = button.primary.padding.resolve(
const LengthUnitContext(rootFontSize: 16),
);
Includes #
Large token sets can be split across multiple files.
lib/tokens/
├── tokens.mordant.yaml
├── palette.mordant.part.yaml
├── space.mordant.part.yaml
└── button.mordant.part.yaml
Root file:
$include:
- palette.mordant.part.yaml
- space.mordant.part.yaml
- button.mordant.part.yaml
Includes are resolved relative to the file containing $include.
They may also be nested:
$include:
- components/button.mordant.part.yaml
Included files use the .mordant.part.yaml suffix so they do not generate standalone Dart files.
Duplicate token definitions are rejected.
Circular includes are rejected.
Generated palettes #
Mordant can generate a color scale from a seed:
palette:
brand:
$generate: palette
seed:
colorSpace: oklch
components: [0.62, 0.18, 288]
alpha: 1
pivot: 500
gamut: srgb
This produces:
palette.brand[0]
palette.brand[50]
palette.brand[100]
palette.brand[200]
palette.brand[300]
palette.brand[400]
palette.brand[500]
palette.brand[600]
palette.brand[700]
palette.brand[800]
palette.brand[900]
palette.brand[950]
palette.brand[1000]
The default scale contains stops 0, 50 through 950, and 1000. Mordant
uses the OKLCH lightness and chroma curves documented by Carpenter and maps
out-of-gamut colors by reducing chroma while preserving lightness and hue.
Hex seeds and the former start name remain supported for compatibility:
palette:
brand:
$generate: palette
seed: "#987654"
start: 500
Custom steps are supported:
palette:
brand:
$generate: palette
seed: "#987654"
start: 400
steps:
- 50
- 100
- 200
- 300
- 400
- 500
- 600
- 700
- 800
- 900
- 950
Palette lightness targets and chroma envelope can also be configured:
palette:
brand:
$generate: palette
seed:
colorSpace: oklch
components: [0.62, 0.18, 288]
alpha: 1
pivot: 500
gamma: 1.15
lightness:
50: 0.975
950: 0.175
Token values #
Mordant currently recognizes:
color: "#987654"
px: 12px
em: 1.25em
rem: 1rem
duration: 200ms
number: 42
decimal: 1.25
enabled: true
label: Hello
reference: "${space.md}"
Hex colors must be quoted because an unquoted # starts a YAML comment.
References #
References use ${...} syntax:
space:
md: 1rem
button:
padding: "${space.md}"
Indexed groups may be referenced with bracket syntax:
palette:
brand:
500: "#987654"
button:
background: "${palette.brand[500]}"
References are validated during generation.
Missing and circular references cause the build to fail.
Generated code #
Generated files are automatically formatted.
Mordant generates typed Dart structures instead of runtime string lookups.
For example:
button:
primary:
filled:
background: "${palette.brand[500]}"
becomes an API shaped like:
button.primary.filled.background
No runtime token-path parsing is involved.
License #
Apache License 2.0.