feat(mix): add MixScope.inherit to combine parent and child tokens#853
feat(mix): add MixScope.inherit to combine parent and child tokens#853tilucasoli wants to merge 3 commits intomainfrom
Conversation
- Add MixScope.inherit() factory that merges nearest parent scope tokens with provided tokens so both upstream and local tokens resolve in the same subtree (additive token scope). - Document in mix-scope-and-theming.md and add tests for outer+inner resolution, Material+inherit, light/dark theme, override behavior, and no-parent case. Co-authored-by: Cursor <cursoragent@cursor.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
To view this pull requests documentation preview, visit the following URL: Documentation is deployed and generated using docs.page. |
leoafarias
left a comment
There was a problem hiding this comment.
Code review — 2 issues found (details in inline comments below).
| builder: (context) { | ||
| final parent = MixScope.maybeOf(context); | ||
|
|
||
| return MixScope.combine(scopes: [?parent, nestedScope], child: child); |
There was a problem hiding this comment.
Bug: key parameter is silently ignored
The key passed to inherit() goes into nestedScope, but nestedScope is never inserted into the widget tree — it's only used as a data carrier for combine(). The Builder returned here doesn't receive the key, and combine is called without forwarding it (defaults to null).
A caller passing key: ValueKey('foo') would expect it to affect widget identity, but it has zero effect.
Suggested fix — forward key to combine:
return MixScope.combine(key: key, scopes: [?parent, nestedScope], child: child);| ```dart | ||
| // Outer scope provides base tokens; inherit combines them with yours | ||
| MixScope( | ||
| colors: { ColorToken('brand.primary'): Colors.blue }, |
There was a problem hiding this comment.
Doc: Invalid Dart — duplicate named parameter colors:
This constructor call has colors: twice, which is a compile error in Dart. The second entry should be merged into a single map:
MixScope(
colors: {
ColorToken('brand.primary'): Colors.blue,
ColorToken('custom.accent'): Colors.orange,
},
child: MixScope.inherit(
spaces: { SpaceToken('custom.gap'): 12.0 },
child: MySubtree(),
),
)Expand docs to explain that nesting a MixScope replaces the parent for token resolution and can drop parent tokens; add examples and sections for MixScope.combine (merge order, use-case) and MixScope.inherit (merge with parent at build time). In code, remove the key from the temporary nested scope and pass the key into MixScope.combine in the builder so the combined scope receives the key (ensuring the merged scope is keyed correctly).
Description
Adds MixScope.inherit, a way to combine tokens from the nearest parent MixScope with additional tokens in a single merged scope. A nested
MixScopenormally replaces the parent for its subtree;MixScope.inheritinstead merges parent + child token maps so both upstream and local tokens resolve. Inner tokens override parent when the same token key is defined in both. Implemented via a Builder that reads the parent scope and builds one MixScope with the merged map (no change togetToken/tokenOfresolution).Changes
MixScope.inherit()that takes the same token maps as the main factory, uses a Builder to getMixScope.maybeOf(context, 'tokens'), merges{...?parent?.tokens, ...childTokens}, and returns a singleMixScopewith merged tokens and optionalorderOfModifiers(child then parent)..lightand.dark; inner overrides parent when same key; inherit with no parent.MixScope.inheritas the way to combine tokens (parent + yours, yours override). Example with plain outerMixScopeandMixScope.inherit.Review Checklist
Additional Information (optional)
Validation (from original what-if): one “Fortal” token and one custom Mix token both resolve in the same subtree; resolution validated for
.lightand.darkwithin the outer scope.