<div id="app">
<div id="generate">
<!-- //Primary color -->
<input type="color" class="" v-model="primary" name="primary" id="primary"></input>
<label for="primary">Primary color</label>
<!-- //Secondary color -->
<input type="color" class="" v-model="secondary" name="secondary" id="secondary"></input>
<label for="secondary">Secondary color</label>
<!-- //Surface color -->
<input type="color" class="" v-model="surface" name="surface" id="surface"></input>
<label for="surface">Surface color</label>
<br />
<button @click="update">Generate palette</button>
<button @click="clear">Clear</button>
</div>
<div v-if="colorList.length" class="palette">
<div v-for="color of colorList" :style="{'background-color' : color.color, 'color' : color.text }">{{ color.name }}<br />{{ color.color }}<br />{{ color.contrastAA }} AA, {{ color.contrastAAA }} AAA,</div>
</div>
<h4 v-if="colorList.length">Copy a code, open <a href="https://www.figma.com/community/plugin/971807532885631684">this nice plugin</a>, import the code as JSON, ... , profit</h4>
<div v-if="colorList.length" class="figma-code" onclick="selectText(this.id)" id="figma-code">
<code>
{{ code }}
</code>
</div>
<p v-else>List is empty.</p>
</div>
#app {
font-family: Helvetica, Arial, sans-serif;
text-align: left;
color: #2c3e50;
margin-top: 60px;
width: 640px;
}
#generate {
margin-bottom: 2em;
}
.palette {
display: grid;
grid-template-columns: 160px 160px 160px 160px;
grid-template-rows: 100px 100px;
grid-auto-flow: row;
}
.palette div {
padding: 1em;
width: 160px;
border: 1px solid #fff;
}
.figma-code {
background-color: #eaeaea;
width: 100%;
padding: 1em;
}
function generatePalette(primary, secondary, surface) {
let positive, negative, surfaceMid, surfaceHigh, strokes;
let primaryLum = chroma(primary).get("oklch.l");
// Positive and Negative colors
if (primaryLum < 0.25) {
positive = chroma(primary)
.set("oklch.l", "0.25")
.set("oklch.c", "0.25")
.set("oklch.h", "145");
} else if (primaryLum > 0.4) {
positive = chroma(primary)
.set("oklch.l", "0.40")
.set("oklch.c", "0.25")
.set("oklch.h", "145");
} else {
positive = chroma(primary).set("oklch.h", "145");
}
if (chroma(positive).get("oklch.c") < 0.14) {
positive = chroma(positive).set("oklch.c", "0.14");
}
negative = chroma(positive)
.set("oklch.h", "26")
.set("oklch.c", "0.225")
.set("oklch.l", chroma(positive).get("oklch.l"))
.hex();
// Secondary
secondary = secondary
? secondary
: chroma(primary).set("oklch.h", "+45").set("oklch.l", primaryLum);
// Surface and strokes
let surfaceLow = surface
? chroma(surface).luminance(0.92)
: chroma(primary).luminance(0.92);
surfaceMid = chroma(surfaceLow).luminance(0.95).hex();
surfaceHigh = chroma(surfaceLow).luminance(0.99).hex();
strokes = chroma(surfaceLow).set("oklch.l", "0.87").hex();
let colorCodes = [
primary,
secondary,
positive,
negative,
surfaceLow,
surfaceMid,
surfaceHigh,
strokes
];
let colorNames = [
"primary",
"secondary",
"positive",
"negative",
"surfaceLow",
"surfaceMid",
"surfaceHigh",
"strokes"
];
// Create color Objects with paired text styles
let colorsArray = [];
for (const i in colorCodes) {
const textColor =
chroma(colorCodes[i]).luminance() < 0.19 ? "#fafafa" : "#0a0a0a";
let contrast = chroma.contrast(colorCodes[i], textColor);
let contrastAA = contrast < 4.5 ? "❌" : "✅";
let contrastAAA = contrast < 7 ? "❌" : "✅";
let color = {
name: colorNames[i],
color: chroma(colorCodes[i]).hex(),
text: textColor,
contrastAA,
contrastAAA
};
colorsArray.push(color);
}
return colorsArray;
}
function createCode(colors, noTextColors) {
let code = [];
for (const i in colors) {
let basicColor = { name: colors[i].name, color: colors[i].color };
code.push(basicColor);
if (!noTextColors.some((el) => el === colors[i].name)) {
let textColor = { name: colors[i].name + "-text", color: colors[i].text };
code.push(textColor);
}
}
return code;
}
const app = Vue.createApp({
data() {
return {
primary: "#002E7A",
secondary: "",
surface: "",
colorList: [],
code: [],
noTextColors: ["surfaceMid", "surfaceHigh", "strokes"]
};
},
methods: {
update() {
this.colorList = generatePalette(
this.primary,
this.secondary,
this.surface
);
this.code = createCode(this.colorList, this.noTextColors);
},
clear() {
this.colorList = [];
this.primary = "#AA00FF";
this.secondary = "";
this.surface = "";
}
}
});
app.mount("#app");
function selectText(id) {
var sel, range;
var el = document.getElementById(id); //get element id
if (window.getSelection && document.createRange) {
//Browser compatibility
sel = window.getSelection();
if (sel.toString() == "") {
//no text selection
window.setTimeout(function () {
range = document.createRange(); //range object
range.selectNodeContents(el); //sets Range
sel.removeAllRanges(); //remove all ranges from selection
sel.addRange(range); //add Range to a Selection.
}, 1);
}
} else if (document.selection) {
//older ie
sel = document.selection.createRange();
if (sel.text == "") {
//no text selection
range = document.body.createTextRange(); //Creates TextRange object
range.moveToElementText(el); //sets Range
range.select(); //make selection.
}
}
}
This Pen doesn't use any external CSS resources.