feat(flutter/theme): codegen emits dark + light + flat token classes
gen_tokens.dart now produces FabledSwordDarkTokens (dark surface), FabledSwordLightTokens (light surface), and FabledSwordFlatTokens (colors that don't change + radii + fonts). The original FabledSwordTokens class stays as a back-compat alias re-exporting the dark surface + flat values; any code that reads FabledSwordTokens.obsidian etc. continues to work during migration. Source: shared/fabledsword.tokens.json (already had dark/light/flat splits — this was the generator catching up). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,46 @@
|
|||||||
// Run `dart run tool/gen_tokens.dart` to regenerate.
|
// Run `dart run tool/gen_tokens.dart` to regenerate.
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class FabledSwordDarkTokens {
|
||||||
|
static const Color obsidian = Color(0xFF14171A);
|
||||||
|
static const Color iron = Color(0xFF1E2228);
|
||||||
|
static const Color slate = Color(0xFF2C313A);
|
||||||
|
static const Color pewter = Color(0xFF3F4651);
|
||||||
|
static const Color parchment = Color(0xFFE8E4D8);
|
||||||
|
static const Color vellum = Color(0xFFC2BFB4);
|
||||||
|
static const Color ash = Color(0xFF9C9A92);
|
||||||
|
}
|
||||||
|
|
||||||
|
class FabledSwordLightTokens {
|
||||||
|
static const Color obsidian = Color(0xFFF8F5EE);
|
||||||
|
static const Color iron = Color(0xFFECE6D5);
|
||||||
|
static const Color slate = Color(0xFFDCD3BD);
|
||||||
|
static const Color pewter = Color(0xFFB8AE94);
|
||||||
|
static const Color parchment = Color(0xFF14171A);
|
||||||
|
static const Color vellum = Color(0xFF2C313A);
|
||||||
|
static const Color ash = Color(0xFF5C6068);
|
||||||
|
}
|
||||||
|
|
||||||
|
class FabledSwordFlatTokens {
|
||||||
|
static const Color moss = Color(0xFF4A5D3F);
|
||||||
|
static const Color bronze = Color(0xFF8B7355);
|
||||||
|
static const Color oxblood = Color(0xFF6B2118);
|
||||||
|
static const Color warning = Color(0xFF8B6F1E);
|
||||||
|
static const Color error = Color(0xFFC04A1F);
|
||||||
|
static const Color info = Color(0xFF3D5A6E);
|
||||||
|
static const Color accent = Color(0xFF4A6B5C);
|
||||||
|
static const Color onAction = Color(0xFFE8E4D8);
|
||||||
|
static const double radiusSm = 4;
|
||||||
|
static const double radiusMd = 8;
|
||||||
|
static const double radiusLg = 12;
|
||||||
|
static const double radiusXl = 16;
|
||||||
|
static const String fontDisplay = "Fraunces";
|
||||||
|
static const String fontBody = "Inter";
|
||||||
|
static const String fontMono = "JetBrains Mono";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Back-compat alias — dark surface tokens + flat. Prefer the explicit
|
||||||
|
/// FabledSwordDarkTokens / FabledSwordLightTokens / FabledSwordFlatTokens.
|
||||||
class FabledSwordTokens {
|
class FabledSwordTokens {
|
||||||
static const Color obsidian = Color(0xFF14171A);
|
static const Color obsidian = Color(0xFF14171A);
|
||||||
static const Color iron = Color(0xFF1E2228);
|
static const Color iron = Color(0xFF1E2228);
|
||||||
|
|||||||
@@ -2,10 +2,16 @@
|
|||||||
// Run via `dart run tool/gen_tokens.dart`. The generated file is
|
// Run via `dart run tool/gen_tokens.dart`. The generated file is
|
||||||
// committed (CI validates it matches the JSON to catch drift).
|
// committed (CI validates it matches the JSON to catch drift).
|
||||||
//
|
//
|
||||||
// Web tokens.json splits colors into `dark`, `light`, and `flat` blocks
|
// Emits three flat classes mirroring the source JSON:
|
||||||
// for the SPA's theme toggle. Flutter v1 ships dark-only, so we merge
|
// - FabledSwordDarkTokens (surface colors for dark mode)
|
||||||
// dark + flat into a single flat namespace. Light variants will be
|
// - FabledSwordLightTokens (surface colors for light mode)
|
||||||
// emitted alongside as part of the Flutter theme-toggle parity work.
|
// - FabledSwordFlatTokens (colors that don't change between modes,
|
||||||
|
// plus radii + font families)
|
||||||
|
//
|
||||||
|
// Plus a back-compat FabledSwordTokens alias that re-exports the dark
|
||||||
|
// surface colors + flat — kept so any code that still reads
|
||||||
|
// FabledSwordTokens.obsidian (etc.) continues to work during the
|
||||||
|
// migration. Safe to delete once theme_extension.dart switches over.
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
@@ -15,9 +21,8 @@ void main() {
|
|||||||
|
|
||||||
final colorsRoot = (tokens['colors'] as Map).cast<String, dynamic>();
|
final colorsRoot = (tokens['colors'] as Map).cast<String, dynamic>();
|
||||||
final dark = (colorsRoot['dark'] as Map).cast<String, String>();
|
final dark = (colorsRoot['dark'] as Map).cast<String, String>();
|
||||||
|
final light = (colorsRoot['light'] as Map).cast<String, String>();
|
||||||
final flat = (colorsRoot['flat'] as Map).cast<String, String>();
|
final flat = (colorsRoot['flat'] as Map).cast<String, String>();
|
||||||
final colors = <String, String>{...dark, ...flat};
|
|
||||||
|
|
||||||
final radii = (tokens['radii'] as Map).cast<String, String>();
|
final radii = (tokens['radii'] as Map).cast<String, String>();
|
||||||
final fonts = (tokens['fonts'] as Map).cast<String, String>();
|
final fonts = (tokens['fonts'] as Map).cast<String, String>();
|
||||||
|
|
||||||
@@ -25,23 +30,57 @@ void main() {
|
|||||||
..writeln('// GENERATED — do not edit. Source: shared/fabledsword.tokens.json')
|
..writeln('// GENERATED — do not edit. Source: shared/fabledsword.tokens.json')
|
||||||
..writeln('// Run `dart run tool/gen_tokens.dart` to regenerate.')
|
..writeln('// Run `dart run tool/gen_tokens.dart` to regenerate.')
|
||||||
..writeln("import 'package:flutter/material.dart';")
|
..writeln("import 'package:flutter/material.dart';")
|
||||||
..writeln()
|
..writeln();
|
||||||
..writeln('class FabledSwordTokens {');
|
|
||||||
|
|
||||||
colors.forEach((name, hex) {
|
void writeColorClass(String className, Map<String, String> colors) {
|
||||||
|
out.writeln('class $className {');
|
||||||
|
colors.forEach((name, hex) {
|
||||||
|
final value = hex.replaceFirst('#', '0xFF');
|
||||||
|
out.writeln(' static const Color ${_camel(name)} = Color($value);');
|
||||||
|
});
|
||||||
|
out.writeln('}');
|
||||||
|
out.writeln();
|
||||||
|
}
|
||||||
|
|
||||||
|
writeColorClass('FabledSwordDarkTokens', dark);
|
||||||
|
writeColorClass('FabledSwordLightTokens', light);
|
||||||
|
|
||||||
|
out.writeln('class FabledSwordFlatTokens {');
|
||||||
|
flat.forEach((name, hex) {
|
||||||
final value = hex.replaceFirst('#', '0xFF');
|
final value = hex.replaceFirst('#', '0xFF');
|
||||||
out.writeln(' static const Color ${_camel(name)} = Color($value);');
|
out.writeln(' static const Color ${_camel(name)} = Color($value);');
|
||||||
});
|
});
|
||||||
|
|
||||||
radii.forEach((name, px) {
|
radii.forEach((name, px) {
|
||||||
final v = px.replaceAll('px', '');
|
final v = px.replaceAll('px', '');
|
||||||
out.writeln(' static const double radius${_pascal(name)} = $v;');
|
out.writeln(' static const double radius${_pascal(name)} = $v;');
|
||||||
});
|
});
|
||||||
|
|
||||||
fonts.forEach((name, family) {
|
fonts.forEach((name, family) {
|
||||||
out.writeln(' static const String font${_pascal(name)} = ${jsonEncode(family)};');
|
out.writeln(' static const String font${_pascal(name)} = ${jsonEncode(family)};');
|
||||||
});
|
});
|
||||||
|
out.writeln('}');
|
||||||
|
out.writeln();
|
||||||
|
|
||||||
|
// Back-compat alias: dark surface colors + flat. Lets existing
|
||||||
|
// call sites that read FabledSwordTokens.obsidian etc. keep working
|
||||||
|
// until they're migrated to the explicit dark/light/flat classes.
|
||||||
|
out.writeln('/// Back-compat alias — dark surface tokens + flat. Prefer the explicit');
|
||||||
|
out.writeln('/// FabledSwordDarkTokens / FabledSwordLightTokens / FabledSwordFlatTokens.');
|
||||||
|
out.writeln('class FabledSwordTokens {');
|
||||||
|
dark.forEach((name, hex) {
|
||||||
|
final value = hex.replaceFirst('#', '0xFF');
|
||||||
|
out.writeln(' static const Color ${_camel(name)} = Color($value);');
|
||||||
|
});
|
||||||
|
flat.forEach((name, hex) {
|
||||||
|
final value = hex.replaceFirst('#', '0xFF');
|
||||||
|
out.writeln(' static const Color ${_camel(name)} = Color($value);');
|
||||||
|
});
|
||||||
|
radii.forEach((name, px) {
|
||||||
|
final v = px.replaceAll('px', '');
|
||||||
|
out.writeln(' static const double radius${_pascal(name)} = $v;');
|
||||||
|
});
|
||||||
|
fonts.forEach((name, family) {
|
||||||
|
out.writeln(' static const String font${_pascal(name)} = ${jsonEncode(family)};');
|
||||||
|
});
|
||||||
out.writeln('}');
|
out.writeln('}');
|
||||||
|
|
||||||
File('lib/theme/tokens.dart').writeAsStringSync(out.toString());
|
File('lib/theme/tokens.dart').writeAsStringSync(out.toString());
|
||||||
|
|||||||
Reference in New Issue
Block a user