Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: DesignToken refactor for FF3 #6171

Merged
merged 97 commits into from
Aug 9, 2022

Conversation

nicholasrice
Copy link
Contributor

@nicholasrice nicholasrice commented Jun 29, 2022

Pull Request

📖 Description

This PR refactors the FF DesignToken feature to align with #6134. The notable changes follow:

Refactor DesignToken to a core implementation that is isomorphic

The entire feature has been refactored and built on top of a core infrastructure that does not leverage any DOM APIs. This means the core can be used to build implementations that work in any JavaScript environment, including plugins for design software such as Figma.

Restrict mutation operations to FASTElement instances

getting, setting, and deleting operations for DesignToken now require a FASTElement instance to operate on instead of any HTMLElement reference. This was done to patch up some odd edge case bugs and to ensure DesignToken behavior between SSR and CSR would be consistent.

DesignToken and CSSDesignToken classes are now exported

Two new exports, DesignToken and CSSDesignToken replace the original DesignToken factory and configuration object. Additoinally, function type DesignToken instances can now be created, where before they were restricted:

DesignToken.create<() => boolean>("my-function-design-token")

Adjust derived values to receive a token resolver argument

Derived values are provided 'resolver' function, where before they were provided a target HTMLElement. This pattern is easier to understand (I think it was always a little confusing why an HTML element was provided) and also remove HTMLElement as a core dependency of the system, allowing it to work outside the browser. For example, assigning a derived value that uses a token now looks like this:

someToken.withDefault((resolve) => resolve(someOtherToken) * 2);

🎫 Issues

Closes #6134, #5903, #5902

👩‍💻 Reviewer Notes

📑 Test Plan

✅ Checklist

General

  • I have included a change request file using $ yarn change
  • I have added tests for my changes.
  • I have tested my changes.
  • I have updated the project documentation to reflect my changes.
  • I have read the CONTRIBUTING documentation and followed the standards for this project.

Component-specific

⏭ Next Steps

@nicholasrice nicholasrice force-pushed the users/nirice/design-token-refactor-exploration branch 2 times, most recently from ecdf0df to 8096ceb Compare July 5, 2022 21:08
@nicholasrice nicholasrice force-pushed the users/nirice/design-token-refactor-exploration branch 4 times, most recently from 0da7115 to f31204d Compare July 15, 2022 19:09
@nicholasrice nicholasrice force-pushed the users/nirice/design-token-refactor-exploration branch from c1456b3 to 4165547 Compare July 18, 2022 18:24
@nicholasrice nicholasrice force-pushed the users/nirice/design-token-refactor-exploration branch from b1f0b41 to 28bfdc5 Compare July 27, 2022 20:22
@KingOfTac
Copy link
Collaborator

Does this fix interpolating tokens in css templates not working? That is something that I noticed in alpha.5 after DesignSystem was removed.

@nicholasrice nicholasrice requested a review from Falkicon as a code owner August 3, 2022 19:02
@nicholasrice nicholasrice force-pushed the users/nirice/design-token-refactor-exploration branch from 2653215 to e1ecf34 Compare August 3, 2022 21:18
}

public get children(): DesignTokenNode[] {
return Array.from(this._children);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it return a new array every time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so, but I'm open to suggestions. The children are stored in a Set privately to make identity lookups easier, but I don't want that set mutable publicly so I convert it to an array for public consumption.

this.children[i].dispatch(records[j]);
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if it makes sense, but would there be an efficiencies gained by instead sending the list of records to child instead of using nested for loops to send the individual records? Maybe they just have to loop internally anyway and so there's no advantage. Just thought I'd check.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow on question, is this the dispatch an array improvement slated for a later date?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I touched on it in our sync, but I think we can see some improvement by reconciling all changes for each node and dispatching a set of mutations instead of dispatching one mutation at a time. I'll file a tracking issue.

@@ -27,6 +27,10 @@
"default": "./dist/esm/index.js"
},
"./custom-elements.json": "./dist/custom-elements.json",
"./design-token-core": {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we export also from the exports.js file in the design-token folder as well as the core export? Or package them together so everything exports from the ./dist/esm/design-tokens/exports.js file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to keep them separate. To start, there are some exports with the same name so that would make conflicts or force us to change the name. Additionally, I think most folks don't need to use the core infrastructure, so keeping that separate from the primary package makes sense to me.

}

constructor(public readonly target: FASTElement) {
super();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it declares the target property.

this.children[i].dispatch(records[j]);
}
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow on question, is this the dispatch an array improvement slated for a later date?

nicholasrice and others added 3 commits August 9, 2022 10:10
…37d60605.json

Co-authored-by: Jane Chu <7559015+janechu@users.noreply.github.com>
…design-token.ts

Co-authored-by: Jane Chu <7559015+janechu@users.noreply.github.com>
@nicholasrice nicholasrice merged commit 218cfc0 into master Aug 9, 2022
@nicholasrice nicholasrice deleted the users/nirice/design-token-refactor-exploration branch August 9, 2022 17:35
janechu added a commit that referenced this pull request Jun 10, 2024
* adding interfaces for new API structure

* adding tests for appendChild / removeChild

* add a stub implementation of DesignToken

* adding minimal design token interface

* save-progress

* adding notification logic

* re-organize notification propagation logic

* adding getTokenValue and tests

* add notification behavior to appndChild

* refactor to use string id

* rename method to retrieve all tokens for a node

* refactor to fix chai bug and issues uncovered when avoiding chai issue

* refactor a bit to centralize notifier for tokens on the token object itself

* adding new test for no notification when assigned the same value

* fixing test

* adding subscription test

* implement isAssigned

* progress on derived tokens

* implement mechanism to notify of static token changes

* make derived token assignments notify down the token tree

* adding and adapting test-cases from original DesignToken implementation

* re-organization of DesignTokenNode

* adding observable map to notify for derived values

* naieve implementation of reflecting upstream derived tokens

* re-oragnize feature and add exports to facilitate testing

* implement circular reference resolution and made a few perf changes

* adding another circular reference test

* adding deleteTokenValue API and privatizing isDerivedFor

* adding subscription tests

* update test names

* further test clean up

* more tests and slight performance improvement

* method organization

* remove observableMap implementation to provide better control over token notification, adds a few tests

* implement more specific notification behavior

* fixing test so it passes w/ new notification behavior

* adding test package

* adds behavior to handle observable value updates

* adding additional observable tests

* refactor token notification to contain mutation type data

* refactor notifications and fix token deletion tests

* adding notification behavior to appending a node

* update readme with perf improvement notes

* in-progress changes for node notification on removal of token and refactoring notification to be single-pass

* refactor notification behavior and fix all test

* batch notifications so the tree is reconciled before subscribers are notified of a change

* implement DesignToken over top of DesignTokenNode, CSS reflection

* isolate design token core from FAST design token implementation

* implement root registration

* Ensure nodes for detached elements can access the defualt node

* passing all tests

* fixing tests

* fixing import

* a bit of cleanup

* refactor type constraints that opens up exporting the token classes instead of an interface/const

* re-organizing files

* re-organize assets, exports, and files. delete legacy design-token

* fix bug in recursive reconciliation of tokens

* update adaptive UI package

* consolidate notification queue

* add children notifier function

* make CSSDesignToken a real CSSDirective

* fixing circular dependency notification bug

* fixing bug in CSS design token css value calculation

* implement observable derived value structure

* refactor to not itterate through all derived values during update

* improving performance of derived tokens

* fixing example

* removing un-necessary method

* adding css directive test

* create tokens with unique name

* lazily create subscriber set for tokens

* implement resolution strategy

* removing debugging spies

* fixing bug in observable bindings where the watcher was not reset if the binding threw

* fixing memory leak caused by observable subscribers

* cleaning up design-token-node tests

* removing tests for scenario that is no longer supported

* adding method comments

* remove test package

* fixing after rebase

* Change files

* Update change/@microsoft-adaptive-ui-881bac8a-4800-4331-9138-0c658998c854.json

* Update change/@microsoft-fast-element-2a4431cf-f1de-44ed-bae4-392f10b74b86.json

* Update change/@microsoft-fast-foundation-d9cdf375-e6b7-4a6e-87e6-81dc37d60605.json

* removing test site from workspaces

* removing readme that is getting processesd by custom element manifest script

* adding API documentation

* removing notes file

* fixing build

* Update change/@microsoft-fast-foundation-d9cdf375-e6b7-4a6e-87e6-81dc37d60605.json

Co-authored-by: Jane Chu <7559015+janechu@users.noreply.github.com>

* Update packages/web-components/fast-foundation/src/design-token/fast-design-token.ts

Co-authored-by: Jane Chu <7559015+janechu@users.noreply.github.com>

Co-authored-by: nicholasrice <nicholasrice@users.noreply.github.com>
Co-authored-by: Jane Chu <7559015+janechu@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants