├── .gitignore
├── manifest.json
├── README.md
├── ui.html
└── code.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Appearance",
3 | "id": "760927481606931799",
4 | "api": "1.0.0",
5 | "main": "code.js",
6 | "ui": "ui.html",
7 | "menu": [
8 | {"name": "Dark mode", "command": "dark"},
9 | {"name": "Light mode", "command": "light"},
10 | {"separator": true},
11 | {"name": "Settings", "command": "name_settings_ui"},
12 | {"name": "Save styles", "command": "get_colors"}
13 | ]
14 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Appearance. Figma plugin.
2 |
3 | This plugin generates a dark/light mode from your selection.
4 | The plugin works with external library styles and local styles.
5 | You can choose styles name identification in settings. By default, the plugin use [day] for light and [night] for dark.
6 |
7 | [Link to the Figma plugin page](https://www.figma.com/c/plugin/760927481606931799/Appearance)
8 |
9 |
10 |
11 | ## How it works:
12 | 1. Use a keyword [day] and [night] in your style names. Example: Style name[day]/ Style name[night].
13 | 2. Apply your color styles.
14 | 3. Select any object, then choose Appearance → Dark mode or Appearance → Light mode.
15 |
16 | ## How it works with external library styles:
17 | 1. Open external library file and use a keyword [day] and [night] in color style names. Example: Style name[day]/ Style name[night].
18 | 2. Publish changes.
19 | 3. Select Appearance → Save styles for saving external color styles to the plugin.
20 | 4. Open any file linked to the library.
21 | 5. Apply color styles.
22 | 6. Select any object then choose Appearance → Dark mode or Appearance → Light mode
23 |
24 | ## Styles name examples:
25 | You can use [day] / [night] at any place of your style name.
26 | ```
27 | Color name [day]
28 | Color name [night]
29 | ```
30 | ```
31 | Style [day] / color-name
32 | Style [night] / color-name
33 | ```
34 | ```
35 | Style / color-name [day]
36 | Style / color-name [night]
37 | ```
38 | ## How to install in the Dev environment
39 | * Select the Plugins Page in the Figma File Browser
40 | * Use the plus (+) button in the Development section
41 | * Choose file manifest.json
42 | * Done
--------------------------------------------------------------------------------
/ui.html:
--------------------------------------------------------------------------------
1 |
2 |
63 |
64 |
65 |
66 |
67 |
114 |
115 |
--------------------------------------------------------------------------------
/code.js:
--------------------------------------------------------------------------------
1 | var day = "[day]";
2 | var night = "[night]";
3 | var allSelection;
4 | var colorsArray = [];
5 | var counter = 0;
6 | var object = {};
7 | var objectLocal = {};
8 | var publicEffectStyles;
9 | var allEffects;
10 |
11 | setNamesToStorage()
12 | async function setNamesToStorage() {
13 | var dayFromStorage = await figma.clientStorage.getAsync('dayFromStorage')
14 | var nightFromStorage = await figma.clientStorage.getAsync('nightFromStorage')
15 |
16 | if (typeof dayFromStorage === 'undefined') {
17 | await figma.clientStorage.setAsync('dayFromStorage', day)
18 | }
19 | if (typeof nightFromStorage === 'undefined') {
20 | await figma.clientStorage.setAsync('nightFromStorage', night)
21 | }
22 | // console.log(dayFromStorage)
23 | }
24 |
25 | // NAME SETTINGS UI
26 | if (figma.command == 'name_settings_ui') {
27 | figma.showUI(__html__, { width: 240, height: 170 })
28 |
29 | sendToUI()
30 | async function sendToUI() {
31 |
32 | var dayFromStorage = await figma.clientStorage.getAsync('dayFromStorage')
33 | var nightFromStorage = await figma.clientStorage.getAsync('nightFromStorage')
34 |
35 | if (typeof dayFromStorage === 'undefined' || typeof nightFromStorage === 'undefined') {
36 | await figma.clientStorage.setAsync('dayFromStorage', day)
37 | await figma.clientStorage.setAsync('nightFromStorage', night)
38 | }
39 | // console.log(dayFromStorage)
40 | if (dayFromStorage.length > 0 || nightFromStorage.length > 0) {
41 | figma.ui.postMessage({ day: dayFromStorage, night: nightFromStorage })
42 | }
43 | // figma.ui.postMessage({ day: dayFromStorage, night: nightFromStorage })
44 | }
45 |
46 |
47 | // Recieving settings from UI
48 | figma.ui.onmessage = async (msg) => {
49 | if (msg.type === 'dayInput') {
50 | await figma.clientStorage.setAsync('dayFromStorage', msg.dayColor)
51 | figma.closePlugin('👌 Settings saved');
52 | }
53 | if (msg.type === 'nightInput') {
54 | await figma.clientStorage.setAsync('nightFromStorage', msg.nightColor)
55 | }
56 | if (msg.type === 'clearStorage') {
57 | await figma.clientStorage.setAsync('dayFromStorage', day)
58 | await figma.clientStorage.setAsync('nightFromStorage', night)
59 | // await figma.clientStorage.setAsync('dayFromStorage')
60 | // await figma.clientStorage.setAsync('nightFromStorage')
61 | // await figma.clientStorage.setAsync('allColors')
62 | // await figma.clientStorage.setAsync('allEffects')
63 | figma.closePlugin('😶 All settings were reset');
64 | }
65 | }
66 | }
67 |
68 | // GET LIBRARY COLORS
69 | if (figma.command == 'get_colors') {
70 |
71 | if (figma.getLocalPaintStyles().length == 0){
72 | figma.closePlugin('😶 This document does not have styles');
73 | } else {
74 | setPaints()
75 | colorsNumber()
76 |
77 | async function setPaints() {
78 | await figma.clientStorage.setAsync('allColors', figma.getLocalPaintStyles().map(a => a.key))
79 | await figma.clientStorage.setAsync('allEffects', figma.getLocalEffectStyles().map(a => a.key))
80 | }
81 |
82 | async function colorsNumber() {
83 | var allColors = await figma.clientStorage.getAsync('allColors')
84 | // console.log(allColors.length)
85 |
86 | if (allColors.length > 0){
87 | figma.closePlugin(`👌 Styles saved`);
88 | } else {
89 | figma.closePlugin('😶 You don`t have saved styles');
90 | }
91 | }
92 | }
93 | }
94 |
95 | // SELECTED DARK MODE
96 | if (figma.command == 'dark') {
97 |
98 | async function getPaints() {
99 | var publicColorStyles = await figma.clientStorage.getAsync('allColors');
100 | var publicEffectStyles = await figma.clientStorage.getAsync('allEffects');
101 |
102 | if (typeof publicColorStyles === 'undefined') {
103 | await figma.clientStorage.setAsync('allColors', "")
104 | // console.log(publicColorStyles)
105 | }
106 | if (typeof publicEffectStyles === 'undefined') {
107 | await figma.clientStorage.setAsync('allEffects', "")
108 | } else {
109 | var publicStyles = [...publicColorStyles, ...publicEffectStyles]
110 | // console.log(publicColorStyles)
111 | }
112 |
113 | var localColorStyles = figma.getLocalPaintStyles();
114 | var localEffectStyles = figma.getLocalEffectStyles();
115 | var localStyles = [...localColorStyles, ...localEffectStyles]
116 | // console.log(localStyles)
117 |
118 | var days = {}
119 | var nights = {}
120 |
121 | // getting identificator words
122 | var dayFromStorage = await figma.clientStorage.getAsync('dayFromStorage')
123 | var nightFromStorage = await figma.clientStorage.getAsync('nightFromStorage')
124 |
125 | if (typeof dayFromStorage === 'undefined') {
126 | dayFromStorage = day;
127 | // console.log(dayFromStorage)
128 | }
129 |
130 | if (typeof publicStyles === 'undefined' && localStyles.length == 0) {
131 | figma.closePlugin('😶 This document does not have styles');
132 |
133 | } else {
134 | var importStyles = await Promise.all(
135 | publicStyles.map((styleKey) =>
136 | figma.importStyleByKeyAsync(styleKey)
137 | .catch(() => {})
138 | )
139 | );
140 |
141 | if (importStyles[0] == undefined) {
142 | // console.log(importStyles)
143 | var importStyles = [];
144 | }
145 |
146 | var allStyles = [...localStyles, ...importStyles]
147 | // console.log(allStyles)
148 |
149 | //Creating style couples
150 | for (let paintStyle of allStyles) {
151 | const name = paintStyle.name
152 | const id = paintStyle.id
153 | if (name.includes(nightFromStorage)) {
154 | const key = name.replace(nightFromStorage, '');
155 | nights[key] = id;
156 | } else if (name.includes(dayFromStorage)) {
157 | const key = name.replace(dayFromStorage, '');
158 | days[key] = id;
159 | }
160 | }
161 |
162 | Object.entries(days).forEach(([name, id]) => {
163 | object[id] = nights[name];
164 | // object[nights[name]] = id;
165 | });
166 |
167 | Object.entries(days).forEach(([name, id]) => {
168 | objectLocal[id.slice(0,43)] = nights[name];
169 | });
170 | }
171 | }
172 |
173 | // Changing colors
174 | function findSelectedFrames() {
175 | if (figma.currentPage.selection.length == 0) {
176 | figma.closePlugin("🤔 No object selected. Please select any object");
177 |
178 | } else {
179 | try {
180 | var allSelection = figma.currentPage.selection[0].findAll();
181 | } catch(error) {
182 | var allSelection = [];
183 | }
184 | allSelection.unshift(figma.currentPage.selection[0]);
185 | }
186 |
187 | for (let frame of allSelection) {
188 | if (frame.fillStyleId && object && object[frame.fillStyleId]) {
189 | frame.fillStyleId = object[frame.fillStyleId];
190 | counter++;
191 | }
192 | if (frame.effectStyleId && object && object[frame.effectStyleId]) {
193 | frame.effectStyleId = object[frame.effectStyleId];
194 | counter++;
195 | }
196 | if (frame.strokeStyleId && object && object[frame.strokeStyleId]) {
197 | frame.strokeStyleId = object[frame.strokeStyleId];
198 | counter++;
199 | }
200 | if (frame.fillStyleId && objectLocal && objectLocal[frame.fillStyleId]) {
201 | frame.fillStyleId = objectLocal[frame.fillStyleId];
202 | counter++;
203 | }
204 | if (frame.effectStyleId && objectLocal && objectLocal[frame.effectStyleId]) {
205 | frame.effectStyleId = objectLocal[frame.effectStyleId];
206 | counter++;
207 | }
208 | if (frame.strokeStyleId && objectLocal && objectLocal[frame.strokeStyleId]) {
209 | frame.strokeStyleId = objectLocal[frame.strokeStyleId];
210 | counter++;
211 | }
212 | }
213 | }
214 | //Checking day colors
215 | function notDayObjects() {
216 | if (counter == 0) {
217 | figma.closePlugin(`😶 Selection does not have style pairs`);
218 | }
219 | }
220 |
221 | getPaints().then(() => {
222 | findSelectedFrames();
223 | return 1;
224 | }
225 | ).then(() => {
226 | notDayObjects();
227 | }
228 | ).then(() => figma.closePlugin(`🤘🌗 Dark theme created!`));
229 |
230 | }
231 |
232 | // SELECTED LIGHT MODE
233 | if (figma.command == 'light') {
234 | async function getPaints() {
235 | var publicColorStyles = await figma.clientStorage.getAsync('allColors');
236 | var publicEffectStyles = await figma.clientStorage.getAsync('allEffects');
237 |
238 | if (typeof publicColorStyles === 'undefined') {
239 | await figma.clientStorage.setAsync('allColors', "")
240 | }
241 | if (typeof publicEffectStyles === 'undefined') {
242 | await figma.clientStorage.setAsync('allEffects', "")
243 | } else {
244 | var publicStyles = [...publicColorStyles, ...publicEffectStyles]
245 | // console.log(publicStyles)
246 | }
247 |
248 | var localColorStyles = figma.getLocalPaintStyles();
249 | var localEffectStyles = figma.getLocalEffectStyles();
250 | var localStyles = [...localColorStyles, ...localEffectStyles]
251 | // console.log(localStyles)
252 |
253 | var days = {}
254 | var nights = {}
255 | var daysLocal = {}
256 | var nightsLocal = {}
257 |
258 | var dayFromStorage = await figma.clientStorage.getAsync('dayFromStorage')
259 | var nightFromStorage = await figma.clientStorage.getAsync('nightFromStorage')
260 |
261 | if (typeof publicStyles === 'undefined' && localStyles.length == 0) {
262 | figma.closePlugin('😶 This document does not have styles');
263 | } else {
264 | var importStyles = await Promise.all(
265 | publicStyles.map((styleKey) =>
266 | figma.importStyleByKeyAsync(styleKey)
267 | .catch(() => {})
268 | )
269 | );
270 |
271 | if (importStyles[0] == undefined) {
272 | // console.log(importStyles)
273 | var importStyles = [];
274 | }
275 |
276 | var allStyles = [...localStyles, ...importStyles]
277 | // console.log(allStyles)
278 |
279 | //Creating style couples
280 | for (let paintStyle of allStyles) {
281 | const name = paintStyle.name
282 | const id = paintStyle.id
283 | if (name.includes(nightFromStorage)) {
284 | const key = name.replace(nightFromStorage, '');
285 | nights[key] = id;
286 | nightsLocal[key] = id.slice(0,43);
287 | } else if (name.includes(dayFromStorage)) {
288 | const key = name.replace(dayFromStorage, '');
289 | days[key] = id;
290 | daysLocal[key] = id.slice(0,43);
291 | }
292 | }
293 |
294 | Object.entries(days).forEach(([name, id]) => {
295 | // object[id] = nights[name];
296 | object[nights[name]] = id;
297 | });
298 |
299 | Object.entries(daysLocal).forEach(([name, id]) => {
300 | objectLocal[nightsLocal[name]] = id;
301 | });
302 | }
303 | }
304 |
305 | // Changing colors
306 | function findSelectedFrames() {
307 | if (figma.currentPage.selection.length == 0) {
308 | figma.closePlugin("🤔 No object selected. Please select any object");
309 |
310 | } else {
311 | try {
312 | var allSelection = figma.currentPage.selection[0].findAll();
313 | } catch(error) {
314 | var allSelection = [];
315 | }
316 | allSelection.unshift(figma.currentPage.selection[0]);
317 | }
318 |
319 | for (let frame of allSelection) {
320 | if (frame.fillStyleId && object && object[frame.fillStyleId]) {
321 | frame.fillStyleId = object[frame.fillStyleId];
322 | counter++
323 | }
324 | if (frame.effectStyleId && object && object[frame.effectStyleId]) {
325 | frame.effectStyleId = object[frame.effectStyleId];
326 | counter++;
327 | }
328 | if (frame.strokeStyleId && object && object[frame.strokeStyleId]) {
329 | frame.strokeStyleId = object[frame.strokeStyleId];
330 | counter++
331 | }
332 | if (frame.fillStyleId && objectLocal && objectLocal[frame.fillStyleId]) {
333 | frame.fillStyleId = objectLocal[frame.fillStyleId];
334 | counter++
335 | }
336 | if (frame.effectStyleId && objectLocal && objectLocal[frame.effectStyleId]) {
337 | frame.effectStyleId = objectLocal[frame.effectStyleId];
338 | counter++;
339 | }
340 | if (frame.strokeStyleId && objectLocal && objectLocal[frame.strokeStyleId]) {
341 | frame.strokeStyleId = objectLocal[frame.strokeStyleId];
342 | counter++
343 | }
344 | }
345 | }
346 |
347 | //Checking night colors
348 | function notNightObjects() {
349 | if (counter == 0) {
350 | figma.closePlugin(`😶 Selection does not have style pairs`);
351 | }
352 | }
353 |
354 | getPaints().then(() => {
355 | findSelectedFrames();
356 | return 1;
357 | }
358 | ).then(() => {
359 | notNightObjects();
360 | }
361 | ).then(() => figma.closePlugin(`🤘🌖 Light theme created!`));
362 | }
--------------------------------------------------------------------------------