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

2.0: Make variable creation work across multiple files #2568

Merged
merged 38 commits into from
May 26, 2024

Conversation

six7
Copy link
Collaborator

@six7 six7 commented Apr 4, 2024

Fixes #2023

This PR enables creation of variables that reference other variables part of other files.
Also fixed an issue with variable creation from sets, where there'd be duplicate variables
Renamed the function that's responsible for creating variables based on sets to something more understandable

Had to comment out a few lines part of the syncVariables and syncStyles files - but didnt want to do the brunt work of removing those functions from the plugin in this PR. will do that in a followup.

Testing this change

  • Create tokens and try to create from a set - try it in multple sets as well (something that was skipped in prior PRs it seems)
  • Create themes and tokens that reference other tokens in other themes, and have those create in multiple files and notice references will work
CleanShot.2024-04-08.at.23.28.05.mp4
CleanShot.2024-04-08.at.23.31.25.mp4

Copy link

changeset-bot bot commented Apr 4, 2024

🦋 Changeset detected

Latest commit: 19d781f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@tokens-studio/figma-plugin Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@six7 six7 changed the title wip: remote variables Make variable creation work across multiple files Apr 8, 2024
referenceVariableCandidates.push({
variable,
modeId: mode,
referenceVariable: referenceTokenName.split('.').join('/'),
referenceVariable: referenceTokenName,
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Changed this so we're normalzing on dot notation as we do elsewhere

await Promise.all(referenceVariableCandidates.map(async (aliasVariable) => {
const referenceVariable = figmaVariables.get(aliasVariable.referenceVariable);
if (!referenceVariable) return;
const variable = await figma.variables.importVariableByKeyAsync(referenceVariable);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

changed implementation to get variable remotely instead of just checking locally

@@ -2,7 +2,6 @@ import { AliasRegex } from '@/constants/AliasRegex';
import { UpdateTokenVariablePayload } from '@/types/payloads/UpdateTokenVariablePayload';
import { SingleToken } from '@/types/tokens';

export function checkCanReferenceVariable(payload: UpdateTokenVariablePayload | SingleToken<true, { path: string, variableId: string }> | null) {
if (!payload) return false;
export function checkCanReferenceVariable(payload: UpdateTokenVariablePayload | SingleToken<true, { path: string, variableId: string }>) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

removed the unneccessary check if what we pass in even exists - lets do this outside

} else {
const newCollection = figma.variables.createVariableCollection(theme.group ?? theme.name);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

refactored this to re-use instead of duplicating everything

@six7 six7 marked this pull request as ready for review April 8, 2024 21:39
@six7 six7 changed the title Make variable creation work across multiple files 2.0: Make variable creation work across multiple files Apr 8, 2024
@six7 six7 linked an issue Apr 11, 2024 that may be closed by this pull request
@six7 six7 marked this pull request as draft April 26, 2024 08:35
@six7 six7 marked this pull request as ready for review May 8, 2024 15:15
@six7 six7 marked this pull request as draft May 8, 2024 15:19
@six7 six7 marked this pull request as draft May 8, 2024 15:19
@six7 six7 marked this pull request as ready for review May 20, 2024 07:11
Copy link

@cuserox cuserox left a comment

Choose a reason for hiding this comment

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

I trust it works as expected, judging by the videos and the thorough extra tests 💪

.changeset/empty-geckos-roll.md Outdated Show resolved Hide resolved

export type LocalVariableInfo = {
collectionId: string;
modeId: string;
variableIds: Record<string, string>
};
// This function is used to create variables based on themes
Copy link

Choose a reason for hiding this comment

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

This gets triggered by the above message -> CREATE_LOCAL_VARIABLES?

Would be good to have a list of message handlers + what they do and what message triggers it, not a blocker but just to see the overlaps and maybe refactoring opportunities!

Copy link

Choose a reason for hiding this comment

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

Yes:

AsyncMessageChannel.PluginInstance.handle(AsyncMessageTypes.CREATE_LOCAL_VARIABLES, asyncHandlers.createLocalVariables);

Async message event handlers, in the plugin, are registered in controller.ts.

This is called in the UI, here:

}, async () => await AsyncMessageChannel.ReactInstance.message({
type: AsyncMessageTypes.CREATE_LOCAL_VARIABLES,
tokens: multiValueFilteredTokens,
settings,
}));

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Agree - the variables flow in psrticular feels super repetitive. I tried to refactor parts in this PR but much more can be done here

const allVariableObj = await updateVariables({
collection, mode: modeId, theme, tokens, settings,
});
if (Object.keys(allVariableObj.variableIds).length > 0) {
Copy link

Choose a reason for hiding this comment

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

Would allVariableObj always have variableIds defined?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, but it can be an empty array. I didnt work on this original implementation and i think we should improve this in a follow-up

Copy link

Choose a reason for hiding this comment

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

Not necessary to make the changes now, but a lot of these tests could be rearranged and grouped follow the order of logic of each file, to see better what happy / sad paths are being covered.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I added a note in 7b05ae3 and added setValuesOnVariable as something to pay closer attention to during DX step where we mentioned we wanted to increase coverage of some of our core functions (this one has a few missing steps in logic)

// This could be because the user is in a free Figma plan and we werent able to create more than 1 mode
if (!collection || !modeId) return;

const allVariableObj = await updateVariables({

Choose a reason for hiding this comment

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

Having two different files called updateVariables is a little confusing.

controller.ts -> asyncHandlers.updateVariables – this is a different function to updateVariables which is called in createLocalVariablesInPlugin.ts.
controller.ts -> asyncHandlers.createLocalVariables
asyncMessageHandlers/createLocalVariables.ts -> createLocalVariablesInPlugin(...)
createLocalVariablesInPlugin.ts -> updateVariables

In a future refactor it could be worth reducing the number of functions re message handling and reuse more code. Moving between many different files/functions makes it harder to track the data flow.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

💯 I agree. We should refactor this. I think we can get away with just 1 function that just does things a little bit different depending on if we're using themes or if we're using sets (we also have different props being passed in).

I've added this as one of the issues in the DX epic. #2792

@six7 six7 merged commit 890c5b2 into release-139 May 26, 2024
5 of 6 checks passed
@six7 six7 deleted the six7/remote-variables branch May 26, 2024 09:42
@six7 six7 added the 2.0-rc7 label Jun 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for referencing non-local variables
4 participants