Skip to main content
Question

Dark to light theme plugin development

  • December 22, 2022
  • 0 replies
  • 1092 views

Nidhin_Kuttikkattu_Rajeevan

Hi,
I am trying to write a simple plugin to switch theme from light mode to dark mode.

I got a sample project from here. GitHub - destefanis/auto-theme: A figma plugin for automatically theming your designs.

I want to create a very simple proof of concept project having a single rectangle with light and dark theme something as below

From Figma plugin development tutorial, I created the plugin with UI, removed the rectangle creating default code, started using the code from this github project. I started copying from initial commit of this github project to mine. But I don’t know how to test in the sample Figma project I created. I kept continuing use the github project into my project till I found react framework use in that repository. I don’t want react so I am stuck there.

Right now, I have a Figma project with a basic frame/rectangle/text and a running plugin where code.ts is as below.

Figma.showUI(html, {width: 380, height: 350});

const themeMapping = {
// Headings
‘5c1691cbeaaf4270107d34f1a12f02fdd04afa02’: {
name: ‘Dark / Header / Primary (White)’,
mapsToName: “Light / Header / Primary (900)”,
mapsToKey: ‘b19a14675b8adeb1528ab5f84e57b2eeed10d46c’,
},
‘bc090cb3b1c7313ae276acbd791b5b87b478ec59’: {
name: “Dark / Header / Secondary (300)”,
mapsToName: “Light / Header / Secondary (600)”,
mapsToKey: “608f2ea1aa64ff7f202e8c22cc4147a02be9d85b”,
},
// Text
“5c77a96137b698b5575557c069cabd6877d66e1e”: {
name: ‘Dark / Text / Normal (200)’,
mapsToName: “Light / Text / Normal (700)”,
mapsToKey: “546c7d46e754ac2b23b338783d72f206b77b6436”,
},
‘5d84ad92f3ad152f196e2093a3c0542a08dfba11’: {
name: “Dark / Text / Muted (400)”,
mapsToName: “Light / Text / Muted (500)”,
mapsToKey: “7d8703ec132ddaf6968f6d190d1e80031c559d7c”,
},
‘bf03232753079bdd5bec6c55343b659876b5283f’: {
name: “Dark / Text / Link”,
mapsToName: “Light / Text / Link”,
mapsToKey: “64d3058dd508a4985670b2d19418a06a3503c9c2”,
},
// Interactive Text & Icons
‘287463bade90c1eed5ea4cb0b5d63794daa8aec2’: {
name: “Dark / Interactive Text & Icons / Normal (300)”,
mapsToName: “Light / Interactive Text & Icons / Normal (600)”,
mapsToKey: “9c23a031773711e026394f4354661c37ee5b4682”,
},
‘502dcdf04992818dcbaed125ad711b446dee4c68’: {
name: “Dark / Interactive Text & Icons / Hover (200)”,
mapsToName: “Light / Interactive Text & Icons / Hover (700)”,
mapsToKey: “e9542e95adf3bbe74286c2cf279fee64f7ba3279”,
},
‘3eddc15e90bbd7064aea7cc13dc13e23a712f0b0’: {
name: “Dark / Interactive Text & Icons / Active (White)”,
mapsToName: “Light / Interactive Text & Icons / Active (900)”,
mapsToKey: “620c98e8f9255a6107dee91745669e5b702b413c”,
},
‘fa698aa2a724522a7c29efb0a662aec75a1be5a1’: {
name: “Dark / Interactive Text & Icons / Muted (500)”,
mapsToName: “Light / Interactive Text & Icons / Muted (300)”,
mapsToKey: “9328cd78a39149b070d68f98d9fe4df7a92bf67d”,
},
// Backgrounds
‘4b93d40f61be15e255e87948a715521c3ae957e6’: {
name: ‘Dark / Background / Primary (600)’,
mapsToName: “Light / Background / Primary (White)”,
mapsToKey: “2449a2983d43793d80baa20c6c60e8a48e7f3a0c”,
},
‘fb1358e5bd6dec072801298238cf49ff77b79a4b’: {
name: “Dark / Background / Secondary (630)”,
mapsToName: “Light / Background / Secondary (130)”,
mapsToKey: “83704278c845a6a7ceb1f837387972ccb6d41960”,
},
“ef179b6abe6cb8779857e05a6333d33f7a2b9320”: {
name: “Dark / Background / Tertiary (700)”,
mapsToName: “Light / Background / Tertiary (200)”,
mapsToKey: “dbd02a76b7b77c1976114c04068f0fbc22015fab”,
},
“3dd0e30ce0a8287eb91ec1fbeff92031e634ed01”: {
name: “Dark / Background / Accent (500)”,
mapsToName: “Light / Interactive Text & Icons / Muted (300)”,
mapsToKey: “9328cd78a39149b070d68f98d9fe4df7a92bf67d”,
},
“11516f4b43f381afb5a6bdf2c34b9437f0eecde1”: {
name: “Dark / Background / Floating (800)”,
mapsToName: “Light / Background / Floating (White)”,
mapsToKey: “6c8b08a42f9614842e880bf7bb795014d8fbae94”,
},
// Background Modifiers
‘d6c9270834b11c99ee651f0f5072ad2c63701165’: {
name: ‘Dark / Background Mod / Hover’,
mapsToName: “Light / Background Mod / Hover”,
mapsToKey: “35307396ae29aaeb583ae65891c69ec689f0c41e”,
},
“bcf890d7a215c65deef97fb3d3f5bcebc9869bab”: {
name: “Dark / Background Mod / Active”,
mapsToName: “Light / Background Mod / Active”,
mapsToKey: “ddadf76919d9bacb925242a024dc1e2f5f517a46”,
},
“ce012db42f35fb58b4fe1d6d8b46c4905a8fad0a”: {
name: “Dark / Background Mod / Selected”,
mapsToName: “Light / Background Mod / Selected”,
mapsToKey: “5af2eaf14901472c26b641997796bdba76ee1794”,
},
“a6a3dc153f0e589408186176ebf8f20ed2f9bda3”: {
name: “Dark / Background Mod / Accent”,
mapsToName: “Light / Background Mod / Accent”,
mapsToKey: “08c7091f8d6950dc3f616afe8ed45b086f9124c7”,
},
}

Figma.ui.onmessage = msg => {

if (msg.type === ‘update-theme’) {

// If nothing is selected update the whole page
if (figma.currentPage.selection.length === 0) {
  const frameNodes = figma.currentPage.children;
  const allNodes = figma.currentPage.findAll();
  allNodes.map(selected => updateTheme(selected));
}
else if (figma.currentPage.selection.length === 1) {

  // Find all the nodes
  let node = figma.currentPage.selection[0];
  if ( isFrameOrGroup(node) ) { 
    let allNodes = node.findAll();
    // Update the nodes
    allNodes.map(selected => updateTheme(selected));
  }
  
}
else {
  let allNodes:any[] = [];
  let nodeLength = figma.currentPage.selection.length;

  // Find all the children nodes from the selected layers
  for (let i = 0; i < nodeLength; i++) {
    let node = figma.currentPage.selection[i];
    if ( isFrameOrGroup(node) ) 
    { 
      let foundChildren = node.findAll();
      allNodes.push(foundChildren);
      // Update the nodes
       
    }

   // allNodes.push(figma.currentPage.selection[i].findAll());
  }

  allNodes.forEach(function(selectedNode) {
    selectedNode.map(selected => updateTheme(selected));
  });
}

}

function isFrameOrGroup(node: SceneNode):node is FrameNode | GroupNode {
return node.type === ‘FRAME’ || node.type === ‘GROUP’
}

function updateTheme(node) {
switch (node.type) {
case ‘COMPONENT’:
case ‘INSTANCE’:
case ‘RECTANGLE’:
case ‘ELLIPSE’:
case ‘POLYGON’:
case ‘STAR’:
case ‘LINE’:
case ‘BOOLEAN_OPERATION’:
case ‘FRAME’:
case ‘VECTOR’: {
// Check to see if the node has a style
if (node.fillStyleId) {
// Fetch the style by using the ID.
let style = Figma.getStyleById(node.fillStyleId);
// Pass in the layer we want to change, the style the node has
// and the set of mappings we want to check against.
replaceStyles(node, style, themeMapping);
} else if (node.backgroundStyleId) {
// Some elements have backgrounds instead of fills.
let style = Figma.getStyleById(node.backgroundStyleId);
replaceBackground(node, style, themeMapping);
}
break
}
case ‘TEXT’: {
if (node.fillStyleId) {
let style = Figma.getStyleById(node.fillStyleId);
replaceStyles(node, style, themeMapping);
}
}
default: {
// do nothing
}
}
}

// Replaces fills with corresponding styles
function replaceStyles(node, style, mappings) {
// Find the style the ID corresponds to in the team library
let importedStyle = Figma.importStyleByKeyAsync(style.key);

// Once the promise is resolved, then see if the
// key matches anything in the mappings object.
importedStyle.then((object) => {

  // If it's null, no mapping exists yet.
  if (mappings[object.key] !== undefined) {
    let mappingStyle = mappings[object.key];

    // Use the mapping value to fetch the official style.
    let newStyle = figma.importStyleByKeyAsync(mappingStyle.mapsToKey);

    newStyle.then(function(object) {
      // Update the current style with the mapping.
      node.fillStyleId = object.id;
    });
  }
});

}

// Updates backgrounds with styles @todo combine this function with replaceStyles
function replaceBackground(node, style, mappings) {
let importedStyle = Figma.importStyleByKeyAsync(style.key);

importedStyle.then((object) => {
  if (mappings[object.key] !== undefined) {
    let mappingStyle = mappings[object.key];
  
    let newStyle = figma.importStyleByKeyAsync(mappingStyle.mapsToKey);

    newStyle.then(function(object) {
      node.backgroundStyleId = object.id;
    });
  }
});

}

Figma.closePlugin();
};

0 replies

Be the first to reply!

Reply


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings