Color picker

Inspired by Rizzo, with clipboard support and luminance check for overlaying text color.

by Bart Kalisz

HTML

<noscript class="js-template">
  <div class="color-box js-color-box{{isLight}}" style="background-color: {{color}}">
    <div class="color-box__msg color-box__msg--copy">Click to copy</div>
    <div class="color-box__msg color-box__msg--copied">Copied!</div>
    <div class="color-box__hash">
      <span>{{color}}</span>
      <input class="color-box__hash__input js-hash-input" value="{{color}}" />
    </div>
  </div>
</noscript>

SCSS

body {
  font-family: Arial;
  font-size: 12px;
}

.heading {
  width: 100%;
  float: left;
  clearfix: both;
  font-size: 14px;
  line-height: 50px;
  color: #297cbb;
  text-transform: uppercase;
}

.color-box {
  position: relative;
  box-sizing: border-box;
  float: left;
  width: 19%;
  height: 74px;
  margin: 0 1% 1% 0;
  border-radius: 4px;
  color: white;

  text-align: center;
  cursor: copy;
  -webkit-user-select: none;
  
  &.is-light {
    color: #2c3643;
  }
  
  &.is-copied {
    cursor: default
  }
}

.color-box__msg {
  position: absolute;
  width: 100%;
  top: 20px;
  opacity: 0;
  transition: all .2s;
}

.color-box__msg--copy {
  .color-box:hover & {
    opacity: 1
  }
  .color-box.is-copied:hover & {
    opacity: 0
  }  
}

.color-box__msg--copied {
  .color-box.is-copied:hover & {
    opacity: 1
  }
}

.color-box__hash {
  position: absolute;
  height: 20px;
  line-height: 20px;
  width: 100%;
  top: 50%;
  margin-top: -10px;
  font-family: Courier;
  transition: all .1s;

  .color-box:hover & {
    margin-top: 0
  }
}

.color-box__hash__input {
  opacity: 0;
  width: 100%;
}

JavaScript

var COLOR_PALETTES = [{
    name: "gray",
    colors: [{
      name: "darkgray",
      hash: "#2c3643"
    }, {
      name: "titlegray",
      hash: "#3b444f"
    }, {
      name: "bodygray",
      hash: "#67747c"
    }, {
      name: "lightgray",
      hash: "#99a9b3"
    }, {
      name: "subduedgray",
      hash: "#dbe6ec"
    }]
  }, {
    name: "primary",
    colors: [{
      name: "darkblue",
      hash: "#142b44"
    }, {
      name: "navblue",
      hash: "#1d508d"
    }, {
      name: "lpblue",
      hash: "#297CBB"
    }, {
      name: "linkblue",
      hash: "#288ad6"
    }, {
      name: "teal",
      hash: "#0FDEBD"
    }, {
      name: "green",
      hash: "#16c98d"
    }, {
      name: "yella",
      hash: "#feef6d"
    }, {
      name: "orange",
      hash: "#ffc83f"
    }, {
      name: "red",
      hash: "#fa5e5b"
    }, {
      name: "plum",
      hash: "#bf538d"
    }]
  }, {
    name: "secondary",
    colors: [{
      name: "mauve",
      hash: "#684e79"
    }, {
      name: "pink",
      hash: "#ff708e"
    }, {
      name: "darkcyan",
      hash: "#47a899"
    }, {
      name: "softblue",
      hash: "#8abee5"
    }, {
      name: "softgreen",
      hash: "#c7e6aa"
    }, {
      name: "beige",
      hash: "#cfcbaf"
    }, {
      name: "maroon",
      hash: "#582c2b"
    }, {
      name: "darkred",
      hash: "#841e1b"
    }]
  }],
  template = $(".js-template").text(),
  $body = $("body");

function getLuminance(hash) {
  var rgb = hash.replace("#", ""),
    red = parseInt(rgb.substr(0, 2), 16),
    grn = parseInt(rgb.substr(2, 2), 16),
    blu = parseInt(rgb.substr(3, 2), 16);

  return Math.ceil(0.2126 * red + 0.7152 * grn + 0.0722 * blu);
}

function isLight(hash) {
  return getLuminance(hash) > 190;
}

for (var i = 0; i < COLOR_PALETTES.length; i++) {
  var palette = COLOR_PALETTES[i],
    colors = palette.colors,
    len = colors.length;

  $body.append("<div class='heading'>" + palette.name + " palette");

  for (var j = 0; j <...