diff --git a/src/_mixins.scss b/src/_mixins.scss index d35c7069..2b849ef5 100644 --- a/src/_mixins.scss +++ b/src/_mixins.scss @@ -17,10 +17,12 @@ ::selection { background: $background; /* WebKit/Blink Browsers */ color: $color; + text-shadow: none; } ::-moz-selection { background: $background; /* Gecko Browsers */ color: $color; + text-shadow: none; } } diff --git a/src/_settings.scss b/src/_settings.scss index 2f4132d8..06c5d71f 100644 --- a/src/_settings.scss +++ b/src/_settings.scss @@ -1,13 +1,3 @@ -/** - * Resources - */ - -$arwes-resource-background1: '/img/background.jpg' !default; -$arwes-resource-background1-medium: '/img/background-medium.jpg' !default; -$arwes-resource-background1-large: '/img/background-large.jpg' !default; -$arwes-resource-pattern1: '/img/glow.png' !default; - - /** * General */ diff --git a/src/components/Arwes/Readme.md b/src/components/Arwes/Readme.md deleted file mode 100644 index e69de29b..00000000 diff --git a/src/components/Arwes/_index.scss b/src/components/Arwes/_index.scss index f49d872d..7f93f24a 100644 --- a/src/components/Arwes/_index.scss +++ b/src/components/Arwes/_index.scss @@ -1,5 +1,6 @@ @mixin arwes-arwes () { .arwes { + display: block; background-size: cover; background-position: center; background-attachment: fixed; @@ -34,21 +35,13 @@ } &.arwes--ready { - &.arwes--resources { - background-image: url($arwes-resource-background1); - - @media #{$medium-and-up} { - background-image: url($arwes-resource-background1-medium); - } - - @media #{$large-and-up} { - background-image: url($arwes-resource-background1-large); - } - - .arwes__pattern { - background-image: url($arwes-resource-pattern1); - } - } + // + } + &.arwes--anim { + // + } + &.arwes--resources { + // } } } diff --git a/src/components/Arwes/index.js b/src/components/Arwes/index.js index 014e4070..3bb6aa24 100644 --- a/src/components/Arwes/index.js +++ b/src/components/Arwes/index.js @@ -1,33 +1,53 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import classNames from 'classnames'; import docReady from 'doc-ready'; +import responsive from '../../tools/responsive'; +/** + * Application container. + */ export default class Arwes extends Component { constructor () { super(...arguments); this.state = { + bg: null, + pattern: null, ready: false, }; } componentDidMount () { - docReady(() => { - this.setState({ ready: true }); - }); + + docReady(() => this.setState({ ready: true })); + + this.onUpdateBG(); + } + + componentDidUpdate (prevProps) { + if (prevProps.resources !== this.props.resources) { + this.onupdate(); + } } render () { - const { resources, className, children, ...rest } = this.props; + const { anim, resources, className, children, ...rest } = this.props; const cls = classNames('arwes', { - 'arwes--resources': resources, 'arwes--ready': this.state.ready, + 'arwes--resources': resources, + 'arwes--anim': anim, }, className); + const { pattern } = resources || {}; + + const bg = this.state.bg; + const bgStyle = bg && { backgroundImage: `url(${bg})` }; + const patternStyle = pattern && { backgroundImage: `url(${pattern})` }; return ( -
-
+
+
{children} @@ -36,12 +56,58 @@ export default class Arwes extends Component {
); } + + /** + * Update the background image based on viewport and provided resources. + */ + onUpdateBG () { + + const { resources } = this.props; + let bgs = resources && resources.bg; + + responsive.off(this.onBgChange); + + if (bgs) { + if (typeof bgs === 'string') { + this.setState({ bg: bgs }); + } else { + this.onBgChange = responsive.on(dims => { + const bg = dims.small ? bgs.small : dims.medium ? bgs.medium : bgs.large; + this.setState({ bg }); + }); + } + } + } } Arwes.propTypes = { - resources: PropTypes.bool, + + /** + * Resources to render. + */ + resources: PropTypes.shape({ + + // Background + bg: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.shape({ + small: PropTypes.string, + medium: PropTypes.string, + large: PropTypes.string, + }), + ]), + + // Pattern + pattern: PropTypes.string, + }), + + /** + * Animations enabled. + */ + anim: PropTypes.bool, }; Arwes.defaultProps = { - resources: false, + resources: null, + anim: false, }; diff --git a/src/components/Button/index.js b/src/components/Button/index.js index e0f5e101..62954c7b 100644 --- a/src/components/Button/index.js +++ b/src/components/Button/index.js @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import PropTypes from 'prop-types'; import classNames from 'classnames'; export default function Button (props) { diff --git a/src/components/Card/index.js b/src/components/Card/index.js index 14b668b0..afb516b4 100644 --- a/src/components/Card/index.js +++ b/src/components/Card/index.js @@ -1,4 +1,5 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import classNames from 'classnames'; export default class Card extends Component { diff --git a/src/components/Frame/Readme.md b/src/components/Frame/Readme.md index e69de29b..0fd88438 100644 --- a/src/components/Frame/Readme.md +++ b/src/components/Frame/Readme.md @@ -0,0 +1,5 @@ + +

Arwes Project

+

Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit esse.

+ diff --git a/src/components/Frame/_index.scss b/src/components/Frame/_index.scss index d8847173..e44b07d6 100644 --- a/src/components/Frame/_index.scss +++ b/src/components/Frame/_index.scss @@ -6,10 +6,6 @@ .arwes-frame__box { position: relative; - border-width: 1px; - border-style: solid; - border-color: $arwes-color1-dark; - box-shadow: 0 0 4px rgba($arwes-color1-dark, $arwes-color-alpha); transition: all $arwes-anim-time ease-out; } .arwes-frame__corner { @@ -25,23 +21,19 @@ height: 15px; &.arwes-frame__lt { - left: -2px; - top: -2px; + left: -2px; top: -2px; border-width: 1px 0 0 1px; } &.arwes-frame__lb { - left: -2px; - bottom: -2px; + left: -2px; bottom: -2px; border-width: 0 0 1px 1px; } &.arwes-frame__rt { - right: -2px; - top: -2px; + right: -2px; top: -2px; border-width: 1px 1px 0 0; } &.arwes-frame__rb { - right: -2px; - bottom: -2px; + right: -2px; bottom: -2px; border-width: 0 1px 1px 0; } } @@ -50,59 +42,93 @@ height: 30px; &.arwes-frame__lt { - left: -3px; - top: -3px; + left: -3px; top: -3px; border-width: 2px 0 0 2px; } &.arwes-frame__lb { - left: -3px; - bottom: -3px; + left: -3px; bottom: -3px; border-width: 0 0 2px 2px; } &.arwes-frame__rt { - right: -3px; - top: -3px; + right: -3px; top: -3px; border-width: 2px 2px 0 0; } &.arwes-frame__rb { - right: -3px; - bottom: -3px; + right: -3px; bottom: -3px; border-width: 0 2px 2px 0; } } + &.arwes-frame__corner--l3 { + width: 50px; + height: 50px; + + &.arwes-frame__lt { + left: -5px; top: -5px; + border-width: 4px 0 0 4px; + } + &.arwes-frame__lb { + left: -5px; bottom: -5px; + border-width: 0 0 4px 4px; + } + &.arwes-frame__rt { + right: -5px; top: -5px; + border-width: 4px 4px 0 0; + } + &.arwes-frame__rb { + right: -5px; bottom: -5px; + border-width: 0 4px 4px 0; + } + } } .arwes-frame__content { z-index: 2; position: relative; - background-color: rgba($arwes-color-background2, 0.9); + background-color: rgba($arwes-color-background1, 0.9); overflow: hidden; transition: all $arwes-anim-time ease-out; } - &.arwes-frame--corners1 { - padding: 1px; - } - &.arwes-frame--corners2 { - padding: 3px; - } &.arwes-frame--content { .arwes-frame__content { padding: $arwes-padding; } } - &.arwes-frame--border-down { + + &.arwes-frame--border { .arwes-frame__box { - border-color: $arwes-color1; - border-width: 0 0 4px 0; + border-width: 1px; + border-style: solid; + border-color: $arwes-color1-dark; + box-shadow: 0 0 4px rgba($arwes-color1-dark, $arwes-color-alpha); } } - &.arwes-frame--border-up { - .arwes-frame__box { - border-color: $arwes-color1; - border-width: 1px 0 0 0; + + &.arwes-frame--level1 { + .arwes-frame__content { + background-color: rgba($arwes-color-background2, 0.9); + } + } + &.arwes-frame--level2 { + .arwes-frame__content { + background-color: rgba($arwes-color-background3, 0.9); + } + } + &.arwes-frame--level3 { + .arwes-frame__content { + background-color: rgba($arwes-color-background4, 0.9); } } + &.arwes-frame--corners1 { + padding: 1px; + } + &.arwes-frame--corners2 { + padding: 3px; + } + &.arwes-frame--corners3 { + padding: 5px; + } + &[data-theme='success'] { color: $arwes-color-success; diff --git a/src/components/Frame/index.js b/src/components/Frame/index.js index b53401f7..669c7602 100644 --- a/src/components/Frame/index.js +++ b/src/components/Frame/index.js @@ -1,6 +1,10 @@ -import React, { Component, PropTypes } from 'react'; +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; import classNames from 'classnames'; +/** + * Base container. + */ export default class Frame extends Component { constructor () { @@ -10,8 +14,9 @@ export default class Frame extends Component { render () { const { - component, + node, border, + level, corners, content, theme, @@ -22,18 +27,22 @@ export default class Frame extends Component { const cls = classNames('arwes-frame', { 'arwes-frame--content': content, - 'arwes-frame--border-up': border === 'up', - 'arwes-frame--border-down': border === 'down', + 'arwes-frame--border': border, + 'arwes-frame--level1': level === 1, + 'arwes-frame--level2': level === 2, + 'arwes-frame--level3': level === 3, 'arwes-frame--corners1': corners === 1, 'arwes-frame--corners2': corners === 2, + 'arwes-frame--corners3': corners === 3, }, className); const clsCorners = classNames('arwes-frame__corner', `arwes-frame__corner--l${corners}`); + const boxStyle = border && { borderWidth: border === true ? '1px' : border }; return React.createElement( - component, + node, { className: cls, 'data-theme': theme, ...rest }, -
+
{ !!corners &&
} { !!corners &&
} { !!corners &&
} @@ -47,15 +56,20 @@ export default class Frame extends Component { } Frame.propTypes = { - component: PropTypes.string, - border: PropTypes.oneOf(['up', 'down']), + node: PropTypes.string, + border: PropTypes.oneOfType([ + PropTypes.bool, + PropTypes.string + ]), + level: PropTypes.oneOf([0, 1, 2, 3]), + corners: PropTypes.oneOf([0, 1, 2, 3]), theme: PropTypes.oneOf(['success', 'alert', 'disabled']), - corners: PropTypes.number, }; Frame.defaultProps = { - component: 'div', + node: 'div', border: null, - theme: null, + level: 1, corners: 0, + theme: null, }; diff --git a/src/settings.js b/src/settings.js index e69de29b..9a333de2 100644 --- a/src/settings.js +++ b/src/settings.js @@ -0,0 +1,8 @@ +export default { + version: '1.0.0-alpha', + responsive: { + small: 600, + medium: 992, + large: 1200, + }, +}; diff --git a/src/tools/get-dims.js b/src/tools/get-dims.js new file mode 100644 index 00000000..6ceaf084 --- /dev/null +++ b/src/tools/get-dims.js @@ -0,0 +1,70 @@ +/** + * Get the usable browser window dimentions. + * + * @param {Number} wMin - Minimum width. + * @param {Number} hMin - Minimum height. + * @param {Number} wMax - Maximum width. + * @param {Number} hMax - Maximum height. + * + * @return {Object} { Number width, Number height } + */ +export default function getDims (wMin, hMin, wMax, hMax) { + + var getSize = function (Name) { + + var size; + var name = Name.toLowerCase(); + var document = window.document; + var documentElement = document.documentElement; + + // IE6 & IE7 don't have window.innerWidth or innerHeight + if (window['inner' + Name] === undefined) { + size = documentElement['client' + Name]; + } + + // WebKit doesn't include scrollbars while calculating viewport size so we have to get fancy + else if (window['inner' + Name] !== documentElement['client' + Name]) { + + // Insert markup to test if a media query will match document.doumentElement["client" + Name] + var bodyElement = document.createElement('body'); + bodyElement.id = 'vpw-test-b'; + bodyElement.style.cssText = 'overflow:scroll'; + var divElement = document.createElement('div'); + divElement.id = 'vpw-test-d'; + divElement.style.cssText = 'position:absolute;top:-1000px'; + // Getting specific on the CSS selector so it won't get overridden easily + divElement.innerHTML = ''; + bodyElement.appendChild(divElement); + documentElement.insertBefore(bodyElement, document.head); + + if (divElement['offset' + Name] === 7) { + // Media query matches document.documentElement["client" + Name] + size = documentElement['client' + Name]; + } else { + // Media query didn't match, use window["inner" + Name] + size = window['inner' + Name]; + } + // Cleanup + documentElement.removeChild(bodyElement); + } + + // Default to use window["inner" + Name] + else { + size = window['inner' + Name]; + } + + return size; + }; + + const dims = { + width: getSize('Width'), + height: getSize('Height') + }; + + dims.width = wMin ? (dims.width < wMin ? wMin : dims.width) : dims.width; + dims.width = wMax ? (dims.width > wMax ? wMax : dims.width) : dims.width; + dims.height = hMin ? (dims.height < hMin ? hMin : dims.height) : dims.height; + dims.height = hMax ? (dims.height > hMax ? hMax : dims.height) : dims.height; + + return dims; +} diff --git a/src/tools/responsive.js b/src/tools/responsive.js new file mode 100644 index 00000000..ae971ab9 --- /dev/null +++ b/src/tools/responsive.js @@ -0,0 +1,46 @@ +import settings from '../settings'; +import getDims from './get-dims'; + +export default { + + /** + * Register a on resize window callback to know the current browser viewport + * dimentions. + * @param {Function} callback - It's called on every window resize and receives + * and object defining the current viewport size. + * @return {Function} The event callback. + */ + on (callback) { + + const onChange = function () { + + const { width } = getDims(); + const { small, medium } = settings.responsive; + + if (width <= small) { + callback({ small: true }); + } + else if (width <= medium) { + callback({ medium: true }); + } + else { + callback({ large: true }); + } + }; + + window.addEventListener('resize', onChange); + + onChange(); + + return onChange; + }, + + /** + * Turns off a window on resize callback previously created. + * @param {Function} - The event callback. + */ + off (onChange) { + window.removeEventListener('resize', onChange); + }, + +};