Skip to content

Instantly share code, notes, and snippets.

@remitbri
Created July 16, 2015 22:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save remitbri/e9889e0b5964e1577f63 to your computer and use it in GitHub Desktop.
Save remitbri/e9889e0b5964e1577f63 to your computer and use it in GitHub Desktop.
my <Icon />
.Icon{
display: inline-block;
vertical-align: middle;
color: inherit;
}
.Icon--defaultSize{
width: 1rem;
}
.Icon-subcontainer{
display: block;
position: relative;
width: 100%;
height: 0;
}
.Icon-svg{
position: absolute;
width: 100%;
height: 100%;
top: 0;
right: 0;
bottom: 0;
left: 0;
fill: currentColor;
}
"use strict"
const React = require("react/addons")
const svgList = require("./svgList.json")
// Note: each svg markup has been cleaned up!!! Very important.
// No width, height, fill, fill-rule, <script>, <style>, <title>
// `preserveAspectRatio=\"xMidYMid meet\"` is added.
const Icon = React.createClass({
// `altText` is not always needed or desired. If [X] is a cross:
// don't add `altText` if you finally render `close [X]`
// add `altText="close"` if you finally render only `[X]`
//
// Same with `tooltip`: add one to the 2nd example above,
// but if the icon is a readable text (eg. a logo), you don't need the toolip
//
// `square` is when you need several icons to "fit in the same square" in your design
//
// Use an `additionalClass` to set the width of your icon and/or its color
//
propTypes : {
icon : React.PropTypes.string.isRequired,
additionalClass : React.PropTypes.string,
altText : React.PropTypes.string,
square : React.PropTypes.bool,
tooltip : React.PropTypes.bool,
},
getDefaultProps() {
return {
additionalClass : "Icon--defaultSize",
altText : "",
square : false,
tooltip : false,
}
},
setPaddingBottom(iconObject) {
if (this.props.square) {
return "100%"
}
const dimensions = iconObject.dimensions
const idealWidth = dimensions.w
const idealHeight = dimensions.h
const nbOfDecimals = 4
const decimalTrick = Math.pow(10, nbOfDecimals)
const paddingBottomPercent = Math.round(idealHeight / idealWidth * 100 * decimalTrick) / decimalTrick
return paddingBottomPercent + "%"
},
getIconObject() {
const svg404 = {
svgMarkup : "<svg class=\"Icon-svg Icon-svg--error\" …>…</svg>",
dimensions : {
w : 100,
h : 100,
},
}
const iconObject = svgList[this.props.icon] || svg404
return iconObject
},
render() {
const currentIcon = this.getIconObject()
const svgDef = {__html : currentIcon.svgMarkup}
return (
<span
className={"Icon Icon--" + this.props.icon + " " + this.props.additionalClass}
aria-label={this.props.altText}
title={(this.props.tooltip) ? this.props.altText : ""}
>
<span
className="Icon-subcontainer"
style={{paddingBottom : this.setPaddingBottom(currentIcon)}}
dangerouslySetInnerHTML={svgDef}
/>
</span>
)
},
})
module.exports = Icon
{
"foo": {
"svgMarkup": "<svg class=\"Icon-svg\" …>…</svg>",
"dimensions": {
"w": 50,
"h": 37
}
},
"bar": {
"svgMarkup": "<svg class=\"Icon-svg\" …>…</svg>",
"dimensions": {
"w": 73,
"h": 73
}
},
"etcaetera": {
"svgMarkup": "<svg class=\"Icon-svg\" …>…</svg>",
"dimensions": {
"w": 45,
"h": 82
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment