diff --git a/.gitignore b/.gitignore
index b5b56cf..68aad34 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
node_modules
-public-min
+build
*.log
.DS_Store
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 0000000..9b57ab3
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,43 @@
+module.exports = function(grunt) {
+ grunt.initConfig({
+ pkg: grunt.file.readJSON('package.json'),
+
+ // =watch
+ watch: {
+ react: {
+ files: ['app/**/*.js'],
+ tasks: ['react'],
+ options: { interrupt: true}
+ },
+ browserify: {
+ files: ['build/**/*.js'],
+ tasks: ['browserify'],
+ options: { interrupt: true}
+ }
+ },
+
+ react: {
+ files: {
+ expand: true,
+ cwd: './app',
+ src: ['**/*.js'],
+ dest: './build',
+ ext: '.js'
+ }
+ },
+
+ browserify: {
+ all: {
+ src: 'build/main.js',
+ dest: 'public/js/cssarrowplease.js'
+ }
+ }
+ });
+
+ grunt.registerTask('build', ['react', 'browserify']);
+ grunt.registerTask('default', 'build');
+
+ grunt.loadNpmTasks('grunt-contrib-watch');
+ grunt.loadNpmTasks('grunt-browserify');
+ grunt.loadNpmTasks('grunt-react');
+};
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 5f4d512..0000000
--- a/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-deps := $(shell find public/ -type f -name "*.*")
-
-public-min: public/index.html $(deps)
- node_modules/assetgraph-builder/bin/buildProduction \
- --root public \
- --outroot public-min \
- $<
-
-PHONY: clean
-
-clean:
- rm -rf public-min
diff --git a/app/app.js b/app/app.js
new file mode 100644
index 0000000..0cce538
--- /dev/null
+++ b/app/app.js
@@ -0,0 +1,18 @@
+/** @jsx React.DOM */
+
+var Page = require('./components/page');
+
+var App = function (props) {
+ this.container = props.container;
+};
+
+App.prototype = {
+ run: function () {
+ React.renderComponent(
+ ,
+ this.container
+ );
+ }
+};
+
+module.exports = App;
diff --git a/app/arrow_generator.js b/app/arrow_generator.js
new file mode 100644
index 0000000..9e5cec4
--- /dev/null
+++ b/app/arrow_generator.js
@@ -0,0 +1,252 @@
+/**
+@class Arrow
+@constructor
+**/
+var Arrow = function () {
+ this._createAttrs();
+};
+
+Arrow.prototype = {
+ /**
+ returns the opposite of the position
+ so 'top' becomes 'bottom' and 'left' becomes 'right'
+ @method invertedPosition
+ @returns {String}
+ **/
+ invertedPosition: function () {
+ var pos = this.get('position');
+
+ if ( pos === 'top' ) return 'bottom';
+ else if ( pos === 'bottom') return 'top';
+ else if ( pos === 'left' ) return 'right';
+ else if ( pos === 'right' ) return 'left';
+ },
+
+ /**
+ returns an rgb color from an hex color
+
+ @method hexToRGB
+ @returns {Array}
+ **/
+ hexToRGB: function (h) {
+ if ( typeof h !== 'string' || !h.match(/^#([0-9A-F]{3}$)|([0-9A-F]{6}$)/i) ) return [0, 0, 0];
+ else if ( h.match(/^(#[0-9a-f]{3})$/i) ) h = '#' + h[1] + h[1] + h[2] + h[2] + h[3] + h[3];
+ var rgb = [],
+ i = 1;
+
+ for(; i < 6; i+=2) {
+ rgb.push(parseInt(h.substring(i, i + 2), 16));
+ }
+ return rgb;
+ },
+
+ /**
+ generates the base css
+
+ @method _baseCSS
+ @returns {String} css
+ @protected
+ **/
+ _baseCSS: function () {
+ var pos = this.get('position'),
+ iPos = this.invertedPosition(),
+ color = this.get('color'),
+ borderSize = this.get('borderSize'),
+ borderColor = this.get('borderColor'),
+ hasBorder = borderSize > 0,
+ css = '.with-arrow {\n';
+
+ css += '\tposition: relative;\n';
+ css += '\tbackground: ' + color + ';\n';
+
+ if (hasBorder) css += '\tborder: ' + borderSize + 'px solid ' + borderColor + ';\n';
+
+ css += '}\n';
+ css += '.with-arrow:after';
+
+ if (hasBorder) css += ', .with-arrow:before {\n';
+ else css += ' {\n';
+
+ css += '\t' + iPos +': 100%;\n';
+
+ if (pos === 'top' || pos === 'bottom') {
+ css += '\tleft: 50%;\n';
+ }
+ else {
+ css += '\ttop: 50%;\n';
+ }
+
+ css += '\tborder: solid transparent;\n';
+ css += '\tcontent: " ";\n';
+ css += '\theight: 0;\n';
+ css += '\twidth: 0;\n';
+ css += '\tposition: absolute;\n';
+ css += '\tpointer-events: none;\n';
+
+ if(hasBorder) css += '}\n';
+
+ return css;
+ },
+
+ /**
+ @method _arrowCSS
+ @description generates arrow css
+ @param {String} color the color of the arrow
+ @param {Integer} size the size of the arrow
+ @param {String} layer :after or :before (defaults to :after)
+ @returns {String} css
+ @protected
+ **/
+ _arrowCSS: function (color, size, layer) {
+ var pos = this.get('position'),
+ iPos = this.invertedPosition(),
+ rgbColor = this.hexToRGB(color),
+ borderSize = this.get('borderSize'),
+ css = "";
+
+ layer = layer || 'after';
+
+ if(borderSize > 0) css += '.with-arrow:' + layer + ' {\n';
+
+ css += '\tborder-color: rgba(' + rgbColor.join(', ') + ', 0);\n';
+ css += '\tborder-' + iPos + '-color: ' + color + ';\n';
+ css += '\tborder-width: ' + size + 'px;\n';
+
+ if (pos === 'top' || pos === 'bottom') {
+ css += '\tmargin-left: -' + size + 'px;\n';
+ }
+ else {
+ css += '\tmargin-top: -' + size + 'px;\n';
+ }
+
+ css += '}';
+
+ return css;
+ },
+
+ /**
+ @method _baseArrowCSS
+ @description generates the base arrow
+ @returns {String} css
+ @protected
+ **/
+ _baseArrowCSS: function () {
+ return this._arrowCSS(
+ this.get('color'),
+ this.get('size'),
+ 'after'
+ );
+ },
+
+ /**
+ @method _arrowBorderCSS
+ @description generates the border arrow
+ @returns {String} css
+ @protected
+ **/
+ _arrowBorderCSS: function () {
+ var css = '',
+ borderSize = this.get('borderSize');
+
+ if (borderSize > 0) {
+ css = this._arrowCSS(
+ this.get('borderColor'),
+ this.get('size') + Math.round(borderSize * 1.41421356), // cos(PI/4) * 2
+ 'before'
+ );
+ }
+
+ return css;
+ },
+
+ /**
+ @method toCSS
+ @description returns a CSS representation of the arrow
+ @returns {String} css
+ **/
+ toCSS: function () {
+
+ var css = [
+ this._baseCSS(),
+ this._baseArrowCSS(),
+ this._arrowBorderCSS()
+ ];
+
+ return css.join(css[2] ? '\n':'');
+ },
+
+ /**
+ @method _createAttrs
+ @description creates attributes from the ATTR constant
+ @protected
+ **/
+ _createAttrs: function () {
+ var ATTRS = Arrow.ATTRS,
+ attributes = {};
+
+ for (var attr in ATTRS) {
+ if (ATTRS.hasOwnProperty(attr)) {
+ attributes[attr] = ATTRS[attr];
+ }
+ };
+
+ this._attributes = attributes;
+ },
+
+ /**
+ @method getAttrs
+ @description returns all the attributes
+ @returns {Object} all the model attributes
+ **/
+ getAttrs: function () {
+ return this._attributes;
+ },
+
+ /**
+ @method get
+ @description returns the provided attribute
+ @param {String} attr the attribute to return
+ @returns {?} the attribute
+ **/
+ get: function (attr) {
+ return this._attributes[attr];
+ },
+
+ /**
+ @method set
+ @description updates the provided attribute
+ @param {String} attr the attribute to update
+ @param {?} val the value to update with
+ **/
+ set: function (attr, val) {
+ if (!(attr in this._attributes)) return;
+
+ this._attributes[attr] = val;
+ },
+
+ setAttrs: function (attrs) {
+ for (var attr in attrs) {
+ if (attrs.hasOwnProperty(attr)) {
+ this.set(attr, attrs[attr]);
+ }
+ }
+ }
+
+};
+
+Arrow.ATTRS = {
+ position: 'top',
+ size: 16,
+ color: '#88b7d5',
+ borderSize: 3,
+ borderColor:'#c2e1f5'
+};
+
+// TODO: refactor!!
+var arrowGenerator = function (config) {
+ var arrow = new Arrow();
+ arrow.setAttrs(config);
+ return arrow.toCSS();
+};
+
+module.exports = arrowGenerator;
diff --git a/app/components/arrow_box.js b/app/components/arrow_box.js
new file mode 100644
index 0000000..976ef5f
--- /dev/null
+++ b/app/components/arrow_box.js
@@ -0,0 +1,15 @@
+/** @jsx React.DOM */
+
+var ArrowBox = React.createClass({
+ render: function () {
+ return (
+
+ Generate tooltips with a
+ CSS triangle in any direction.
+ Configure below
+
+ );
+ }
+});
+
+module.exports = ArrowBox;
diff --git a/app/components/config.js b/app/components/config.js
new file mode 100644
index 0000000..dd70708
--- /dev/null
+++ b/app/components/config.js
@@ -0,0 +1,43 @@
+/** @jsx React.DOM */
+
+var ConfigLabels = require('./config_labels'),
+ ConfigForm = require('./config_form'),
+ GeneratedCode = require('./generated_code'),
+ arrowGenerator = require('../arrow_generator');
+
+var Config = React.createClass({
+
+ /**
+ @method getInitialState
+ @return {Object}
+ **/
+ getInitialState: function () {
+ return {
+ generatedCode: arrowGenerator(this.props.config)
+ };
+ },
+
+ /**
+ @method render
+ @return {ReactComponent}
+ **/
+ render: function() {
+ return (
+
+
+
+
+
+ );
+ },
+
+ /**
+ @method handleConfigChange
+ @param {Object} config
+ **/
+ handleConfigChange: function (config) {
+ this.setState({ generatedCode: arrowGenerator(config) });
+ }
+});
+
+module.exports = Config;
diff --git a/app/components/config_form.js b/app/components/config_form.js
new file mode 100644
index 0000000..fcf0c68
--- /dev/null
+++ b/app/components/config_form.js
@@ -0,0 +1,78 @@
+/** @jsx React.DOM */
+
+var ConfigForm = React.createClass({
+
+ propTypes: {
+ onConfigChange: React.PropTypes.func.isRequired
+ },
+
+ /**
+ @method getInitialState
+ @return {Object}
+ **/
+ getInitialState: function () {
+ return this.props.config;
+ },
+
+ /**
+ @method render
+ @return {ReactComponent}
+ **/
+ render: function () {
+ var change = function (propName) {
+ return this.handleChange.bind(this, propName);
+ }.bind(this);
+
+ var isPositionChecked = function (pos) {
+ return this.state.position === pos;
+ }.bind(this);
+
+ return (
+
+ );
+ },
+
+ handleChange: function (propName, ev) {
+ var nextState = {},
+ val = ev.target.value;
+
+ if (val && propName.indexOf('ize') !== -1) {
+ val = parseInt(val, 10);
+ }
+
+ nextState[propName] = val;
+
+ this.setState(nextState, function () {
+ this.props.onConfigChange(this.state);
+ }.bind(this));
+ }
+});
+
+module.exports = ConfigForm;
diff --git a/app/components/config_labels.js b/app/components/config_labels.js
new file mode 100644
index 0000000..b3aa2df
--- /dev/null
+++ b/app/components/config_labels.js
@@ -0,0 +1,21 @@
+/** @jsx React.DOM */
+
+var ConfigLabels = React.createClass({
+ render: function() {
+ return (
+
+ );
+ }
+});
+module.exports = ConfigLabels;
diff --git a/app/components/generated_code.js b/app/components/generated_code.js
new file mode 100644
index 0000000..129b190
--- /dev/null
+++ b/app/components/generated_code.js
@@ -0,0 +1,29 @@
+/** @jsx React.DOM */
+
+var GeneratedCode = React.createClass({
+
+ propTypes: {
+ code: React.PropTypes.string.isRequired
+ },
+
+ render: function() {
+ this.updateStyles();
+
+ return (
+
+ {this.props.code}
+
+ );
+ },
+
+ componentWillMount: function () {
+ this.styleContainer = document.createElement('style');
+ document.getElementsByTagName('body')[0].appendChild(this.styleContainer);
+ },
+
+ updateStyles: function () {
+ this.styleContainer.innerText = this.props.code;
+ }
+
+});
+module.exports = GeneratedCode;
diff --git a/app/components/header.js b/app/components/header.js
new file mode 100644
index 0000000..60b887e
--- /dev/null
+++ b/app/components/header.js
@@ -0,0 +1,27 @@
+/** @jsx React.DOM */
+
+var ArrowBox = require('./arrow_box');
+
+var Header = React.createClass({
+ render: function() {
+ return (
+
+
+ I would love a
+ CSS Arrow Please
+ By Simon Højberg
+
+
+
+
+
+
+
+
+ )
+ }
+});
+
+module.exports = Header;
diff --git a/app/components/page.js b/app/components/page.js
new file mode 100644
index 0000000..f9e8c5c
--- /dev/null
+++ b/app/components/page.js
@@ -0,0 +1,35 @@
+/** @jsx React.DOM */
+
+var Header = require('./header'),
+ Config = require('./config');
+
+var Page = React.createClass({
+ render: function () {
+
+ // default arrow
+ var config = {
+ position: 'top',
+ size: 16,
+ color: '#FFFFFF',
+ borderSize: 3,
+ borderColor: '#42474E'
+ };
+
+ return (
+
+ );
+ }
+});
+
+module.exports = Page;
diff --git a/app/main.js b/app/main.js
new file mode 100644
index 0000000..bb6d84b
--- /dev/null
+++ b/app/main.js
@@ -0,0 +1,8 @@
+/** @jsx React.DOM */
+
+var Page = require('./components/page');
+
+React.renderComponent(
+ ,
+ document.querySelector('.app')
+);
diff --git a/app/models/arrow.js b/app/models/arrow.js
new file mode 100644
index 0000000..1d02753
--- /dev/null
+++ b/app/models/arrow.js
@@ -0,0 +1,267 @@
+/**
+@class Arrow
+@constructor
+**/
+var Arrow = function () {
+ // jquerify 'this'
+ this._$self = $(this);
+ this._createAttrs();
+};
+
+Arrow.prototype = {
+ /**
+ returns the opposite of the position
+ so 'top' becomes 'bottom' and 'left' becomes 'right'
+ @method invertedPosition
+ @returns {String}
+ **/
+ invertedPosition: function () {
+ var pos = this.get('position');
+
+ if ( pos === 'top' ) return 'bottom';
+ else if ( pos === 'bottom') return 'top';
+ else if ( pos === 'left' ) return 'right';
+ else if ( pos === 'right' ) return 'left';
+ },
+
+ /**
+ returns an rgb color from an hex color
+
+ @method hexToRGB
+ @returns {Array}
+ **/
+ hexToRGB: function (h) {
+ if ( typeof h !== 'string' || !h.match(/^#([0-9A-F]{3}$)|([0-9A-F]{6}$)/i) ) return [0, 0, 0];
+ else if ( h.match(/^(#[0-9a-f]{3})$/i) ) h = '#' + h[1] + h[1] + h[2] + h[2] + h[3] + h[3];
+ var rgb = [],
+ i = 1;
+
+ for(; i < 6; i+=2) {
+ rgb.push(parseInt(h.substring(i, i + 2), 16));
+ }
+ return rgb;
+ },
+
+ /**
+ generates the base css
+
+ @method _baseCSS
+ @returns {String} css
+ @protected
+ **/
+ _baseCSS: function () {
+ var pos = this.get('position'),
+ iPos = this.invertedPosition(),
+ color = this.get('color'),
+ borderWidth = this.get('borderWidth'),
+ borderColor = this.get('borderColor'),
+ hasBorder = borderWidth > 0,
+ css = '.arrow_box {\n';
+
+ css += '\tposition: relative;\n';
+ css += '\tbackground: ' + color + ';\n';
+
+ if (hasBorder) css += '\tborder: ' + borderWidth + 'px solid ' + borderColor + ';\n';
+
+ css += '}\n';
+ css += '.arrow_box:after';
+
+ if (hasBorder) css += ', .arrow_box:before {\n';
+ else css += ' {\n';
+
+ css += '\t' + iPos +': 100%;\n';
+
+ if (pos === 'top' || pos === 'bottom') {
+ css += '\tleft: 50%;\n';
+ }
+ else {
+ css += '\ttop: 50%;\n';
+ }
+
+ css += '\tborder: solid transparent;\n';
+ css += '\tcontent: " ";\n';
+ css += '\theight: 0;\n';
+ css += '\twidth: 0;\n';
+ css += '\tposition: absolute;\n';
+ css += '\tpointer-events: none;\n';
+
+ if(hasBorder) css += '}\n';
+
+ return css;
+ },
+
+ /**
+ @method _arrowCSS
+ @description generates arrow css
+ @param {String} color the color of the arrow
+ @param {Integer} size the size of the arrow
+ @param {String} layer :after or :before (defaults to :after)
+ @returns {String} css
+ @protected
+ **/
+ _arrowCSS: function (color, size, layer) {
+ var pos = this.get('position'),
+ iPos = this.invertedPosition(),
+ rgbColor = this.hexToRGB(color),
+ borderWidth = this.get('borderWidth'),
+ css = "";
+
+ layer = layer || 'after';
+
+ if(borderWidth > 0) css += '.arrow_box:' + layer + ' {\n';
+
+ css += '\tborder-color: rgba(' + rgbColor.join(', ') + ', 0);\n';
+ css += '\tborder-' + iPos + '-color: ' + color + ';\n';
+ css += '\tborder-width: ' + size + 'px;\n';
+
+ if (pos === 'top' || pos === 'bottom') {
+ css += '\tmargin-left: -' + size + 'px;\n';
+ }
+ else {
+ css += '\tmargin-top: -' + size + 'px;\n';
+ }
+
+ css += '}';
+
+ return css;
+ },
+
+ /**
+ @method _baseArrowCSS
+ @description generates the base arrow
+ @returns {String} css
+ @protected
+ **/
+ _baseArrowCSS: function () {
+ return this._arrowCSS(
+ this.get('color'),
+ this.get('size'),
+ 'after'
+ );
+ },
+
+ /**
+ @method _arrowBorderCSS
+ @description generates the border arrow
+ @returns {String} css
+ @protected
+ **/
+ _arrowBorderCSS: function () {
+ var css = '',
+ borderWidth = this.get('borderWidth');
+
+ if (borderWidth > 0) {
+ css = this._arrowCSS(
+ this.get('borderColor'),
+ this.get('size') + Math.round(borderWidth * 1.41421356), // cos(PI/4) * 2
+ 'before'
+ );
+ }
+
+ return css;
+ },
+
+ /**
+ @method toCSS
+ @description returns a CSS representation of the arrow
+ @returns {String} css
+ **/
+ toCSS: function () {
+
+ var css = [
+ this._baseCSS(),
+ this._baseArrowCSS(),
+ this._arrowBorderCSS()
+ ];
+
+ return css.join(css[2] ? '\n':'');
+ },
+
+ /**
+ @method _createAttrs
+ @description creates attributes from the ATTR constant
+ @protected
+ **/
+ _createAttrs: function () {
+ var ATTRS = Arrow.ATTRS,
+ attributes = {};
+
+ $.each(ATTRS, function (attr, value) {
+ attributes[attr] = value;
+ });
+
+ this._attributes = attributes;
+ },
+
+ /**
+ @method getAttrs
+ @description returns all the attributes
+ @returns {Object} all the model attributes
+ **/
+ getAttrs: function () {
+ return this._attributes;
+ },
+
+ /**
+ @method get
+ @description returns the provided attribute
+ @param {String} attr the attribute to return
+ @returns {?} the attribute
+ **/
+ get: function (attr) {
+ return this._attributes[attr];
+ },
+
+ /**
+ @method set
+ @description updates the provided attribute
+ @param {String} attr the attribute to update
+ @param {?} val the value to update with
+ **/
+ set: function (attr, val) {
+ if (!(attr in this._attributes)) return;
+
+ this._attributes[attr] = val;
+ this.fire('change');
+ },
+
+ /**
+ @method on
+ @description adds event listeners
+ @note uses jQuery custom events under the hood
+ @param {String} evType the event type
+ @param {Function} callback the event handler
+ @param {Object} context the 'this' for the callback
+ **/
+ on: function (evType, callback, context) {
+ var $self = this._$self;
+
+ $self.on(
+ evType,
+ $.proxy(callback, context || this)
+ );
+ },
+
+ /**
+ @method fire
+ @description trigger event
+ @note uses jQuery custom events under the hood
+ @param {String} evType the event type
+ **/
+ fire: function (evType) {
+ var $self = this._$self;
+
+ $self.trigger(evType);
+ }
+
+};
+
+Arrow.ATTRS = {
+ position: 'top',
+ size: 30,
+ color: '#88b7d5',
+ borderWidth: 4,
+ borderColor: '#c2e1f5'
+};
+
+module.exports = Arrow;
diff --git a/bin/server b/bin/server
index f1ef1b5..ee3614f 100644
--- a/bin/server
+++ b/bin/server
@@ -1,18 +1,11 @@
#!/usr/bin/env node
-var connect = require('connect'),
+var connect = require('connect'),
http = require('http'),
- port = process.env.PORT || 3000,
+ port = process.env.PORT || 1337,
static;
-if (process.argv.indexOf('--development') !== -1) {
- console.log('CSS Arrow Please in development on http://localhost:' + port);
- static = connect.static('public');
-}
-else {
- static = connect.static('public-min', {
- maxAge: 365 * 24 * 60 * 60 * 1000
- });
-}
+console.log('CSS Arrow Please in development on http://localhost:' + port);
+static = connect.static('public');
http.createServer( connect().use( static ) ).listen( port );
diff --git a/package.json b/package.json
index a47cfab..9579649 100644
--- a/package.json
+++ b/package.json
@@ -11,10 +11,7 @@
"type": "git",
"url": "git://github.com/hojberg/cssarrowplease.git"
},
- "keywords": [
- "nodeapps",
- "helloworld"
- ],
+ "keywords": [ "css", "arrow", "tooltip" ],
"homepage": "http://cssarrowplease.com/",
"scripts": {
"start": "node ./bin/server"
@@ -23,10 +20,15 @@
"connect": "~2.0.3"
},
"devDependencies": {
- "assetgraph-builder": ">=0.2.37"
+ "grunt": "latest",
+ "grunt-contrib-watch": "~0.6.0",
+ "react-tools": "latest",
+ "grunt-react": "latest",
+ "grunt-browserify": "latest"
},
"engines": {
- "node": ">=0.6"
+ "node": "0.8.x",
+ "npm": "1.1.x"
},
"licenses": [
{
diff --git a/public/css/app.css b/public/css/app.css
index c137a21..f521927 100644
--- a/public/css/app.css
+++ b/public/css/app.css
@@ -1,61 +1,204 @@
-/* =BASE
-====================================================== */
-html, body { background: url(../img/noisebg.png); }
-body { font-size: 18px; font-family: 'Terminal Dosis', sans-serif; padding: 0; margin: 0; color: #fff; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4); }
-a { color: #fff; color: rgba(255, 255, 255, 0.7); }
-ul, ol, form { margin: 0; padding: 0; }
-ul, ol { list-style-type: none; }
-h1 { margin: 0; padding: 0; }
-h2 { margin: 0; margin-bottom: 10px; padding: 0; font-weight: normal; font-size: 30px; color: #626569; color: rgba(0, 0, 0, 0.4); text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5); }
-input { font-size: 14px; border: 1px solid #777; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(255, 255, 255, 0.3); border-radius: 4px; padding: 3px; -webkit-background-clip: padding-box; }
-input[type='radio'] { border: 0; }
-
-/* =LAYOUT
-====================================================== */
-#content { width: 800px; margin: auto; padding: 100px; padding-bottom: 60px;
- /* white radial gradient background */
- background: -moz-radial-gradient(center, ellipse cover, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 70%);
- background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(255,255,255,0.5)), color-stop(70%,rgba(255,255,255,0)));
- background: -webkit-radial-gradient(center, ellipse cover, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 70%);
- background: -o-radial-gradient(center, ellipse cover, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 70%);
- background: -ms-radial-gradient(center, ellipse cover, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 70%);
- background: radial-gradient(center, ellipse cover, rgba(255,255,255,0.5) 0%,rgba(255,255,255,0) 70%);
-}
-#footer { padding-top: 10px; font-size: 13px; color: rgba(255, 255, 255, 0.7); text-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); border-top: 1px solid #797f85; border-top-color: rgba(0, 0, 0, 0.15); box-shadow: inset 0 1px 1px 0 rgba(255, 255, 255, 0.2); vertical-align: top; text-align: center; }
-#footer a { vertical-align: top; color: #fff; }
-.clr:after { clear:both; content:"."; display: block; height:0; visibility: hidden; line-height:0; font-size:0; }
-
-.ir { border: 0; font: 0/0 a; text-shadow: none; color: transparent; background-color: transparent; }
-
-.preview_and_configuration { float: left; width: 395px; }
-
-/* =MODULES
-====================================================== */
-/* preview */
-.arrow_box { padding: 40px; width: 280px; height: 100px; border-radius: 6px; }
-
-/* logo */
-.logo { color: #ddf8c6; text-align: center; font-size: 54px; line-height: 54px; font-weight: bold; text-transform: uppercase; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4); }
-
-/* configuration */
-.configuration { margin-top: 20px; }
-.configuration .section { float: left; width: 195px; font-size: 20px }
-.configuration .section.positions { width: 140px; margin-left: 14px }
-.configuration .section li { margin-bottom: 5px; }
-.configuration .section label { display: inline-block; width: 112px; }
-
-.configuration .size,
-.configuration .border_width { width: 28px; text-align: right; }
-
-.configuration .color { width: 65px; text-align: center }
-
-.configuration .unit { font-size: 14px; color: rgba(0, 0, 0, 0.4); text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5); margin-left: 5px; }
-
-/* css_result */
-.css_result { position: relative; float: right; width: 402px; }
-.css_result .code { white-space: pre; padding: 10px; display: block; width: 380px; font-size: 12px; font-family: 'Courier new'; font-weight: bold; background: #8c9196; background: rgba(0, 0, 0, 0.15); border-radius: 4px; color: #fff; text-shadow: 0 1px 1px rgba(0, 0, 0, 0.3); border: 1px solid #696d72; border-color: rgba(0, 0, 0, 0.2); box-shadow: 0 1px 1px 0 rgba(255, 255, 255, 0.3), inset 0 1px 5px rgba(0, 0, 0, 0.1); }
-.css_result .copy_code { position: absolute; bottom: 5px; right: 10px; width: 14px; height: 22px; background: url(../img/clippy.png) no-repeat 0 4px; }
-
-
-/* fork_me */
-.fork_me { position: absolute; top: 0; right: 0; display: block; width: 149px; height: 149px; background: url(../img/fork.png); }
+body {
+ font-family: Arial, sans-serif;
+ background: #F0F0F0;
+ color: #BFBFBF;
+ padding: 0;
+ margin: 0;
+ font-size: 13px;
+}
+
+pre {
+ tab-size: 2;
+}
+
+h1, h2 {
+ margin: 0;
+}
+
+h1 {
+ box-shadow: 0 4px 0 0 rgba(0, 0, 0, 0.1);
+ display: -webkit-flex;
+ display: flex;
+ -webkit-flex-direction: row;
+ flex-direction: row;
+ -webkit-justify-content: center;
+ justify-content: center;
+}
+
+h2 {
+ font-size: 13px;
+ text-transform: uppercase;
+}
+
+a {
+ text-decoration: none;
+ color: rgba(0, 0, 0, 0.4);
+ -webkit-transition: all 0.2s;
+ -moz-transition: all 0.2s;
+ transition: all 0.2s;
+}
+
+a:hover {
+ color: #000;
+}
+
+ol {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+
+ol li {
+ height: 19px;
+ padding-top: 7px;
+ vertical-align: middle;
+}
+ol li.with-input {
+ padding-top: 0;
+ height: 26px;
+ margin-top: 3px;
+}
+ol li.for-input {
+ margin-top: 3px;
+}
+
+input[type=text] {
+ border: 0;
+ padding: 2px 4px;
+ width: 69px;
+ color: #4D4D4D;
+ font-weight: bold;
+ font-size: 14px;
+ height: 22px;
+}
+input[type=text]:focus {
+ outline: none;
+ box-shadow: inset 0 0 0 2px #6CC3FF;
+}
+
+input[type=radio] {
+ width: 18px;
+ position: relative;
+ font-size: 1px;
+}
+input[type=radio]:after {
+ background: #fff;
+ position: absolute;
+ top: -5px;
+ left: -2px;
+ border-radius: 9px;
+ width: 18px;
+ height: 18px;
+ content: ' ';
+}
+input[type=radio]:checked:after {
+ background: #6CC3FF;
+ box-shadow: inset 0 0 0 2px #568aaf;
+}
+
+.content {
+ display: -webkit-flex;
+ display: flex;
+ -webkit-flex-direction: row;
+ flex-direction: row;
+ -webkit-justify-content: center;
+ justify-content: center;
+}
+
+.main-header {
+ background: #535962;
+}
+
+.main-header h1 {
+ padding: 15px 0;
+ background: #ff8786;
+ text-align: center;
+ text-transform: uppercase;
+}
+
+.main-header h1 span {
+ font-size: 11px;
+ color: #cc6c6b;
+ line-height: 24px;
+ margin: 0 5px;
+}
+
+.main-header h1 .logo {
+ font-size: 24px;
+ color: #fff;
+}
+
+.main-header h1 a {
+ font-size: 11px;
+ line-height: 24px;
+ color: #995150;
+}
+.main-header h1 a:hover{
+ color: #fff;
+}
+
+.main-header h2 {
+ background: #42474e;
+ color: rgba(187, 216, 236, 0.44);
+}
+
+.main-header h2 .config {
+ padding: 15px 10px;
+ width: 57px;
+ background: #393c41;
+ display: inline-block;
+}
+.main-header h2 .code {
+ padding: 15px 10px;
+ background: #303338;
+ display: inline-block;
+}
+
+.config {
+ width: 77px;
+}
+
+.code {
+ margin: 0;
+ width: 325px;
+ padding: 10px;
+ font-size: 12px;
+}
+
+.main-content aside {
+ padding-top: 10px;
+ font-weight: bold;
+ text-transform: uppercase;
+}
+
+.main-content .config-labels {
+ text-align: right;
+ margin-right: 20px;
+ width: 170px;
+}
+
+.main-content .who {
+ margin-left: 20px;
+ width: 170px;
+ font-size: 11px;
+ line-height: 14px;
+}
+.main-content .who .twitter-share-button {
+ display: block;
+ margin-bottom: 10px;
+}
+
+.main-content .config {
+ padding-top: 10px;
+ background: #d8d8d8;
+ height: 500px;
+}
+
+.main-content .config li {
+ text-align: center;
+}
+
+.main-content .code {
+ background: #c3c3c3;
+ color: #373737;
+}
diff --git a/public/index.html b/public/index.html
index 413f523..0dcbb93 100644
--- a/public/index.html
+++ b/public/index.html
@@ -3,90 +3,27 @@
cssarrowplease
-
+
+
+
-
-
-
-
-
css arrow please!
-
-
-
-
-
-
-
-
- Fork me on Github
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-