JSFiddle - React, Tailwind, and code Playground

by Gwyn Milcote

HTML

<b>Marking designer tool</b>
<br>No genes, just simple shape/colour/opacity. Each slot is 6 characters long, ideal for DB storage.<br>
As an example, try loading this: vb4ca9-yb3ce5-gb3cb4-yb3cc3-tb3da9-sd5de8<br>

<p>
Enter string: <input type='text' id='genome_string'> <button id='load_string'>Load</button>
<br>
<button id='output_string'>Output current design?</button>
<br>
<span id='output_result'>...</span>
</p>

<div id='mark_tabs'>
    <div class='mark_tab active_tab' id='mark_tab_1' data-slot='1'>Slot 1</div>
    <div class='mark_tab' id='mark_tab_2' data-slot='2'>Empty</div>
    <div class='mark_tab' id='mark_tab_3' data-slot='3'>Empty</div>
    <div class='mark_tab' id='mark_tab_4' data-slot='4'>Empty</div>
    <div class='mark_tab' id='mark_tab_5' data-slot='5'>Empty</div>
    <div class='mark_tab' id='mark_tab_6' data-slot='6'>Empty</div>
    <div class='mark_tab' id='mark_tab_7' data-slot='7'>Empty</div>
    <div class='mark_tab' id='mark_tab_8' data-slot='8'>Empty</div>
    <div class='mark_tab' id='mark_tab_9' data-slot='9'>Empty</div>
    <div class='mark_tab' id='mark_tab_10' data-slot='10'>Empty</div>
</div>

<div id='design_mark' class='section'>
    <b>Design a Marking</b>
    <p>
        <b>Slot <span id='current_slot'>1</span></b> - <span id='mark_description'>desc</span>
    </p>
    <button id='toggle_colour' class='optional'>Toggle Palette</button> 
    
    Area: <select id='mark_area'>
        <option value='a'>None</option>
        <option value='b'>Mask</option>
        <option value='c'>Underside</option>
        <option value='d'>Streak</option>
    </select> 

    Effect: <select id='mark_effect' class='optional'>
        <option value='a'>Solid</option>
        <option value='b'>Marbled</option>
        <option value='c'>Cascading</option>
        <option value='d'>Soft</option>
        <option value='e'>Filigree</option>
        <option value='f'>Dalmatian</option>
        <option value='g'>Tobiano</option>
        <option...

CSS

img, div, button {
    box-sizing: border-box;
}

.section {
    border: 1px solid grey;
    padding: 10px;
    margin: 10px auto;
}

#mark_tabs {
    display: flex;
    flex-flow: row wrap;
}

#mark_tabs .mark_tab {
    border: 1px solid grey;
    margin: 5px;
    padding: 10px;
    background-color: #ccc;
    transition: 0.2s;
}

#mark_tabs .mark_tab:hover {
    cursor: pointer;
    background-color: #eee;
    transition: 0.2s;
}

#mark_tabs .active_tab {
    background-color: #fff;
}



.center {
    text-align: center;
}

#colour_palette {
    display: flex;
    flex-flow: row wrap;
}

#colour_palette .swatch {
    display: inline-block;
    width: 10%;
    height: 20px;
}

.beast_coat {
    border: 1px dotted grey;
    width: 250px;
    height: 250px;
    position: relative;
    margin: auto;
}

.beast_coat img {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}



#colour_palette table {
    width: 50%;
    /*height: 100%;*/
}

#colour_palette table td {
    height: 20px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.3) inset;
    transition: 0.2s;
}

#colour_palette table td:hover {
    cursor: pointer;
    box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.3) inset;
    transition: 0.2s;
}

#colour_palette .active_colour {
    box-shadow: 0 0 0 3px rgba(0, 0, 0, 0.4) inset;
    transition: 0.2s;
}




.c_white { background-color: #FFFFFF; }
.f_white { filter: invert(100%); }

/* Silver */

.f_sb1 { filter: invert(100%); }
.f_sb2 { filter: invert(90%); }
.f_sb3 { filter: invert(80%); }
.f_sb4 { filter: invert(70%); }
.f_sb5 { filter: invert(60%); }

.f_sd1 { filter: invert(50%); }
.f_sd2 { filter: invert(40%); }
.f_sd3 { filter: invert(30%); }
.f_sd4 { filter: invert(28%); }
.f_sd5 { filter: invert(10%); }

/* Red */

.f_rb1 { filter: invert(85%) sepia(10%) saturate(708%) hue-rotate(314deg) brightness(101%) contrast(91%); }
.f_rb2 { filter: invert(66%) sepia(81%) saturate(1057%) hue-rotate(308deg) brightness(98%) contrast(81%); }
.f_rb3...

JavaScript

const path = "http://mythstable.epizy.com/thing2/images/";

const markAreas = ["Mask", "Underside", "Streak"];
const markEffects = ["Solid", "Marbled", "Cascading", "Soft", "Filigree", "Dalmatian", "Tobiano", "Flecked", "Swirly", "Patchy"];

// Red, amber, yellow... purple, magenta, silver.
// Used for colour wheel and calculations.
const validColours = "rayogtbivpms".split("");

// a-l are bright, m-x are dull. Same 12 colours as above.
// Single letter is stored in DB and used for CSS class.
const validLetters = "abcdefghijklmnopqrstuvwx".split("");

// Look up proper colour names and hex codes here.
const colourInfo = {
    r: {
        b: [ // Bright Red
            {name: "Powder Pink", hex: "F4CCCC"},
            {name: "Salmon", hex: "E48181"},
            {name: "Cherry", hex: "D52F2F"},
            {name: "Ruby", hex: "9B2020"},
            {name: "Cranberry", hex: "681515"}
        ],
        d: [ // Dull Red
            {name: "Misty Rose", hex: "E9D7D7"},
            {name: "Blush", hex: "C99999"},
            {name: "Russet", hex: "A75B5B"},
            {name: "Rose Vale", hex: "7A4040"},
            {name: "Mahogany", hex: "562C2C"}
        ]
    },
    a: {
        b: [ // Bright Amber
            {name: "Shell", hex: "FADBC5"},
            {name: "Peach", hex: "F2AB77"},
            {name: "Chestnut", hex: "E86F15"},
            {name: "Copper", hex: "AB5210"},
            {name: "Walnut", hex: "75380B"}
        ],
        d: [ // Dull Amber
            {name: "Almond", hex: "E6CEC4"},
            {name: "Toast", hex: "CC9C86"},
            {name: "Coffee", hex: "B36D4D"},
            {name: "Umber", hex: "825037"},
            {name: "Chocolate", hex: "5C3827"}
        ]
    },
    y: {
        b: [ // Bright Yellow
            {name: "Vanilla", hex: "FEECB4"},
            {name: "Topaz", hex: "FCD152"},
            {name: "Gold", hex: "F3B805"},
            {name: "Honey", hex: "BE9105"},
            {name: "Mustard", hex: "896803"}
        ],
 ...