Hey everyone ,
I am looking to create a library of gradients from the Tailwind color system. I would like to automate the generation of these to avoid the heavy manual work that would be required. I can create (very easily) a JSON file with a list of thousands of gradients and wonder if anyone has any ideas on how to populate the fill color of the shape layer with the hex color codes from the JSON values?
01 Shows the default state of the component.
02 Shows the state after the data is applied.
03 Shows what I would like to achieve.
*from my knowledge of Sketch and JSON data this cannot be done, at all. But curious if anyone has any ideas on how this could be achieved.
**I use the data populator plugin for the JSON file hence the {} in the layer names.
I have attached a screenshot with a sample of the JSON file, The layers setup and the component (gradient chip) which shows its layout, actual outcome and desired outcome.
OK so I was skeptical at first, but I believe you might be able to pull it off using what Data Populator has to offer:
The first thing would be to fix the plugin itself since doesn’t seem to be fully compatible with the latest version of Sketch (it works fine untill you want to use some of its advanced features – see below). I’ve sent a PR to the developer, but in the meantime download a fixed version from here: data-populator.sketchplugin-fixed-for-Sketch-99.zip - Google Drive.
The advanced feature we’re going to use is called Condtional Actions, the #plugin one to be exact: we’ll make Data Populator invoke our little helper plugin that will apply the given gradient to a marked layer. I won’t make you write this helper plugin yourself, feel free to use the one I’ve hacked together: Apply Gradient from JSON.sketchplugin.rev0.zip - Google Drive.
Here's the source code of the plugin, just in case.
const { Document, Style } = require('sketch/dom')
const util = require('util')
var onRun = function (context) {
if (!context.selection[0].userInfo()["datapopulator"]) {
return;
}
let colors = util.toArray(context.selection[0].userInfo()["datapopulator"]).map(String)
if (!colors || colors.length < 2) {
return;
}
let stops = colors.map(function (color, idx) {
let step = 1.0 / (colors.length - 1)
return {
position: step * idx,
color: color
}
})
// Here's a quick guide on how gradient orientation via `from` and `to` anchors work:
//
// 0 0.5 1
// ┌─────────────────────▶ x
// │ (from) │
// │ │
// │ │ │
// │ │
// 0.5 │ │ │
// │ │
// │ │ │
// │ │
// │ ▼ │
// 1 │ (to)
// ▼ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
// y
//
// So, for a linear straight top-to-bottom gradient, the anchor points are:
//
// from: (x = 0.5, y = 0) aka the middle of the top edge
// to: (x = 0.5, y = 1) aka the middle of the bottom edge
let gradientFromTopCenterToBottomCenter = {
from: { x: 0.5, y: 0, },
to: { x: 0.5, y: 1, }
}
let layer = Document.getSelectedDocument().selectedLayers.layers[0]
layer.style.fills = [{
fillType: Style.FillType.Gradient,
gradient: {
gradientType: Style.GradientType.Linear,
from: gradientFromTopCenterToBottomCenter.from,
to: gradientFromTopCenterToBottomCenter.to,
stops: stops,
},
}]
};
Now that you have both plugins installed, rename your “Gradient chip” rectangle layer to #plugin[true, Apply Gradient from JSON > To Selected Layer, {hex-01}, {hex-02}]:
That should be it! Run Data Populator and you should see a gradient applied successfully to that shape layer.
The main limitation of this approach is that, due to the way Data Populator passes data to our helper plugin, we can’t get the whole JSON object there automatically – and that’s why I had to include the {hex-01}, {hex-02} part right in the layer name` – that’s the only way to make this information available to the helper plugin. Which means e.g. if you want to specify a different option for the gradient (say, change its direction) – you’ll have to encode it in the layer name as well.
I guess an alternative approach would be to write an ad-hoc plugin that does both placeholder replacement and gradient drawing when necessary (so there won’t be any limitations whatsoever and you could skip the awkward layer naming part). How complicated that’d be depends on what other features of Data Populator you rely on and what needs to be re-implemented in an ad-hoc plugin. But for simple JSON → text layers mapping it shouldn’t be too hard.
Dmitry, I am blown away with this effort!!!
I sketched this idea out days ago and thought there is no way this could be done.
I have downloaded the plugins and will transfer your notes to my own notes for future ref.
Haha thanks a lot Mark! Let’s just say I’ve spent years building and debugging Sketch plugins so my instincts around automating different tasks in Sketch are pretty good
I feel there was more issues but would need to look over my notes (once i find them) I feel like the data populator app has not got any work done to it in a while, which is a shame because its such a powerful plugin.
I created a data site ‘Sketchappdata.com’ now offline but I am planning on putting up a replacement soon under a new name. I think what you have made is a game changer. I will think of some uses for this and create some sample docs (maybe i will create some content around it). I have your email from your site so i will drop you an email.