├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .jsbeautifyrc ├── .jscsrc ├── LICENSE ├── README.md ├── app ├── App.js ├── App.scss ├── animations.js ├── components │ ├── page │ │ ├── HomePage.js │ │ ├── PageAnimations.js │ │ ├── page.js │ │ └── page.scss │ └── sections │ │ ├── section.js │ │ └── section.scss ├── index.tpl.html ├── main.js └── styles │ ├── background.scss │ ├── colors.scss │ ├── flexbox.scss │ ├── fonts.scss │ ├── reset.scss │ ├── typeplate │ ├── _typeplate-extends.scss │ ├── _typeplate-fonts.scss │ ├── _typeplate-functions.scss │ ├── _typeplate-helpers.scss │ ├── _typeplate-mixins.scss │ ├── _typeplate-styles.scss │ ├── _typeplate-vars.scss │ └── _typeplate.scss │ ├── typography.scss │ ├── vars.scss │ ├── wrapper.scss │ └── z-index.scss ├── images ├── hire_bg.png ├── play_bg.jpg └── work_bg.jpg ├── package.json ├── server.js ├── settings ├── dev.json └── prod.json ├── webpack.config.js └── webpack.production.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react", "stage-0"], 3 | "env":{ 4 | "production":{ 5 | "plugins": [ 6 | "transform-react-display-name", 7 | "transform-runtime", 8 | "transform-decorators-legacy" 9 | ] 10 | }, 11 | "dev":{ 12 | "plugins": [ 13 | "transform-react-display-name", 14 | "transform-runtime", 15 | "transform-decorators-legacy", 16 | ["react-transform", { 17 | "transforms": [{ 18 | "transform": "react-transform-hmr", 19 | "imports": ["react"], 20 | "locals": ["module"] 21 | }, { 22 | "transform": "react-transform-catch-errors", 23 | "imports": ["react", "redbox-react"] 24 | }] 25 | }] 26 | ] 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | coverage 4 | webpack.*.js 5 | *Server.js 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", // https://github.com/babel/babel-eslint 3 | "env": { 4 | "browser": true, 5 | "node": true, 6 | "mocha": true 7 | }, 8 | "globals": { 9 | "expect": true, 10 | "sinon": true, 11 | "__DEV__": true 12 | }, 13 | "ecmaFeatures": { 14 | "arrowFunctions": true, 15 | "blockBindings": true, 16 | "classes": true, 17 | "defaultParams": true, 18 | "destructuring": true, 19 | "forOf": true, 20 | "generators": false, 21 | "modules": true, 22 | "objectLiteralComputedProperties": true, 23 | "objectLiteralDuplicateProperties": false, 24 | "objectLiteralShorthandMethods": true, 25 | "objectLiteralShorthandProperties": true, 26 | "spread": true, 27 | "superInFunctions": true, 28 | "templateStrings": true, 29 | "jsx": true 30 | }, 31 | "rules": { 32 | "no-var": 2, // http://eslint.org/docs/rules/no-var 33 | "prefer-const": 2, // http://eslint.org/docs/rules/prefer-const 34 | 35 | /** 36 | * Variables 37 | */ 38 | "no-shadow": 2, // http://eslint.org/docs/rules/no-shadow 39 | "no-shadow-restricted-names": 2, // http://eslint.org/docs/rules/no-shadow-restricted-names 40 | "no-undef": 2, // http://eslint.org/docs/rules/no-undef 41 | "no-unused-vars": [2, { // http://eslint.org/docs/rules/no-unused-vars 42 | "vars": "local", 43 | "args": "after-used" 44 | }], 45 | "no-use-before-define": 2, // http://eslint.org/docs/rules/no-use-before-define 46 | 47 | /** 48 | * Possible errors 49 | */ 50 | "no-cond-assign": [2, "always"], // http://eslint.org/docs/rules/no-cond-assign 51 | "no-console": 1, // http://eslint.org/docs/rules/no-console 52 | "no-debugger": 1, // http://eslint.org/docs/rules/no-debugger 53 | "no-alert": 1, // http://eslint.org/docs/rules/no-alert 54 | "no-constant-condition": 1, // http://eslint.org/docs/rules/no-constant-condition 55 | "no-dupe-keys": 2, // http://eslint.org/docs/rules/no-dupe-keys 56 | "no-duplicate-case": 2, // http://eslint.org/docs/rules/no-duplicate-case 57 | "no-empty": 2, // http://eslint.org/docs/rules/no-empty 58 | "no-ex-assign": 2, // http://eslint.org/docs/rules/no-ex-assign 59 | "no-extra-boolean-cast": 0, // http://eslint.org/docs/rules/no-extra-boolean-cast 60 | "no-extra-semi": 2, // http://eslint.org/docs/rules/no-extra-semi 61 | "no-func-assign": 2, // http://eslint.org/docs/rules/no-func-assign 62 | "no-inner-declarations": 2, // http://eslint.org/docs/rules/no-inner-declarations 63 | "no-invalid-regexp": 2, // http://eslint.org/docs/rules/no-invalid-regexp 64 | "no-irregular-whitespace": 2, // http://eslint.org/docs/rules/no-irregular-whitespace 65 | "no-obj-calls": 2, // http://eslint.org/docs/rules/no-obj-calls 66 | "no-sparse-arrays": 2, // http://eslint.org/docs/rules/no-sparse-arrays 67 | "no-unreachable": 2, // http://eslint.org/docs/rules/no-unreachable 68 | "use-isnan": 2, // http://eslint.org/docs/rules/use-isnan 69 | "block-scoped-var": 2, // http://eslint.org/docs/rules/block-scoped-var 70 | 71 | /** 72 | * Best practices 73 | */ 74 | "consistent-return": 2, // http://eslint.org/docs/rules/consistent-return 75 | "curly": [2, "multi-line"], // http://eslint.org/docs/rules/curly 76 | "default-case": 2, // http://eslint.org/docs/rules/default-case 77 | "dot-notation": [2, { // http://eslint.org/docs/rules/dot-notation 78 | "allowKeywords": true 79 | }], 80 | "eqeqeq": 2, // http://eslint.org/docs/rules/eqeqeq 81 | "guard-for-in": 2, // http://eslint.org/docs/rules/guard-for-in 82 | "no-caller": 2, // http://eslint.org/docs/rules/no-caller 83 | "no-else-return": 2, // http://eslint.org/docs/rules/no-else-return 84 | "no-eq-null": 2, // http://eslint.org/docs/rules/no-eq-null 85 | "no-eval": 2, // http://eslint.org/docs/rules/no-eval 86 | "no-extend-native": 2, // http://eslint.org/docs/rules/no-extend-native 87 | "no-extra-bind": 2, // http://eslint.org/docs/rules/no-extra-bind 88 | "no-fallthrough": 2, // http://eslint.org/docs/rules/no-fallthrough 89 | "no-floating-decimal": 2, // http://eslint.org/docs/rules/no-floating-decimal 90 | "no-implied-eval": 2, // http://eslint.org/docs/rules/no-implied-eval 91 | "no-lone-blocks": 2, // http://eslint.org/docs/rules/no-lone-blocks 92 | "no-loop-func": 2, // http://eslint.org/docs/rules/no-loop-func 93 | "no-multi-str": 2, // http://eslint.org/docs/rules/no-multi-str 94 | "no-native-reassign": 2, // http://eslint.org/docs/rules/no-native-reassign 95 | "no-new": 2, // http://eslint.org/docs/rules/no-new 96 | "no-new-func": 2, // http://eslint.org/docs/rules/no-new-func 97 | "no-new-wrappers": 2, // http://eslint.org/docs/rules/no-new-wrappers 98 | "no-octal": 2, // http://eslint.org/docs/rules/no-octal 99 | "no-octal-escape": 2, // http://eslint.org/docs/rules/no-octal-escape 100 | "no-param-reassign": 2, // http://eslint.org/docs/rules/no-param-reassign 101 | "no-proto": 2, // http://eslint.org/docs/rules/no-proto 102 | "no-redeclare": 2, // http://eslint.org/docs/rules/no-redeclare 103 | "no-return-assign": 2, // http://eslint.org/docs/rules/no-return-assign 104 | "no-script-url": 2, // http://eslint.org/docs/rules/no-script-url 105 | "no-self-compare": 2, // http://eslint.org/docs/rules/no-self-compare 106 | "no-sequences": 2, // http://eslint.org/docs/rules/no-sequences 107 | "no-throw-literal": 2, // http://eslint.org/docs/rules/no-throw-literal 108 | "no-with": 2, // http://eslint.org/docs/rules/no-with 109 | "radix": 2, // http://eslint.org/docs/rules/radix 110 | "vars-on-top": 2, // http://eslint.org/docs/rules/vars-on-top 111 | "wrap-iife": [2, "any"], // http://eslint.org/docs/rules/wrap-iife 112 | "yoda": 2, // http://eslint.org/docs/rules/yoda 113 | 114 | /** 115 | * Style 116 | */ 117 | "indent": [2, 2], // http://eslint.org/docs/rules/indent 118 | "brace-style": [ 119 | 2, // http://eslint.org/docs/rules/brace-style 120 | "1tbs", { 121 | "allowSingleLine": true 122 | } 123 | ], 124 | "quotes": [ 125 | 2, "single", "avoid-escape" // http://eslint.org/docs/rules/quotes 126 | ], 127 | "camelcase": [2, { // http://eslint.org/docs/rules/camelcase 128 | "properties": "never" 129 | }], 130 | "comma-spacing": [2, { // http://eslint.org/docs/rules/comma-spacing 131 | "before": false, 132 | "after": true 133 | }], 134 | "comma-style": [2, "last"], // http://eslint.org/docs/rules/comma-style 135 | "eol-last": 2, // http://eslint.org/docs/rules/eol-last 136 | "func-names": 1, // http://eslint.org/docs/rules/func-names 137 | "key-spacing": [2, { // http://eslint.org/docs/rules/key-spacing 138 | "beforeColon": false, 139 | "afterColon": true 140 | }], 141 | "new-cap": [0, { // http://eslint.org/docs/rules/new-cap 142 | "newIsCap": true 143 | }], 144 | "no-multiple-empty-lines": [2, { // http://eslint.org/docs/rules/no-multiple-empty-lines 145 | "max": 2 146 | }], 147 | "no-nested-ternary": 2, // http://eslint.org/docs/rules/no-nested-ternary 148 | "no-new-object": 2, // http://eslint.org/docs/rules/no-new-object 149 | "no-spaced-func": 2, // http://eslint.org/docs/rules/no-spaced-func 150 | "no-trailing-spaces": 2, // http://eslint.org/docs/rules/no-trailing-spaces 151 | "no-extra-parens": [2, "functions"], // http://eslint.org/docs/rules/no-extra-parens 152 | "no-underscore-dangle": 0, // http://eslint.org/docs/rules/no-underscore-dangle 153 | "one-var": [2, "never"], // http://eslint.org/docs/rules/one-var 154 | "padded-blocks": [2, "never"], // http://eslint.org/docs/rules/padded-blocks 155 | "semi": [2, "always"], // http://eslint.org/docs/rules/semi 156 | "semi-spacing": [2, { // http://eslint.org/docs/rules/semi-spacing 157 | "before": false, 158 | "after": true 159 | }], 160 | "space-after-keywords": 2, // http://eslint.org/docs/rules/space-after-keywords 161 | "space-before-blocks": 2, // http://eslint.org/docs/rules/space-before-blocks 162 | "space-before-function-paren": [2, "never"], // http://eslint.org/docs/rules/space-before-function-paren 163 | "space-infix-ops": 2, // http://eslint.org/docs/rules/space-infix-ops 164 | "space-return-throw-case": 2, // http://eslint.org/docs/rules/space-return-throw-case 165 | "spaced-comment": [2, "always", {// http://eslint.org/docs/rules/spaced-comment 166 | "exceptions": ["-", "+"], 167 | "markers": ["=", "!"] // space here to support sprockets directives 168 | }], 169 | // React 170 | "jsx-quotes": [2, "prefer-double"], 171 | "react/display-name": 0, 172 | "react/jsx-boolean-value": 1, 173 | "react/jsx-no-undef": 2, 174 | "react/jsx-sort-prop-types": 0, 175 | "react/jsx-sort-props": 0, 176 | "react/jsx-uses-react": 1, 177 | "react/jsx-uses-vars": 1, 178 | "react/no-did-mount-set-state": [2, "allow-in-func"], 179 | "react/no-did-update-set-state": 2, 180 | "react/no-multi-comp": 2, 181 | "react/no-unknown-property": 2, 182 | "react/prop-types": 2, 183 | "react/react-in-jsx-scope": 2, 184 | "react/self-closing-comp": 2, 185 | "react/sort-comp": 2, 186 | "react/wrap-multilines": 2 187 | }, 188 | "plugins": [ 189 | "react" 190 | ] 191 | } 192 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | *.log 5 | coverage 6 | -------------------------------------------------------------------------------- /.jsbeautifyrc: -------------------------------------------------------------------------------- 1 | { 2 | "html": { 3 | "allowed_file_extensions": [html", "xml", "svg"], 4 | "brace_style": "collapse", 5 | "end_with_newline": false, 6 | "indent_char": " ", 7 | "indent_handlebars": false, 8 | "indent_inner_html": false, 9 | "indent_scripts": "keep", 10 | "indent_size": 2, 11 | "max_preserve_newlines": 0, 12 | "preserve_newlines": true, 13 | "wrap_line_length": 0 14 | }, 15 | "css": { 16 | "allowed_file_extensions": ["css", "scss", "sass", "less", "styl"], 17 | "end_with_newline": false, 18 | "indent_char": " ",r 19 | "indent_size": 2, 20 | "newline_between_rules": true, 21 | "selector_separator": " ", 22 | "selector_separator_newline": true 23 | }, 24 | "js": { 25 | "allowed_file_extensions": ["js", "json"], 26 | "brace_style": "collapse", 27 | "break_chained_methods": false, 28 | "indent_char": " ", 29 | "indent_level": 0, 30 | "indent_size": 2, 31 | "indent_with_tabs": false, 32 | "keep_array_indentation": false, 33 | "keep_function_indentation": false, 34 | "max_preserve_newlines": 0, 35 | "preserve_newlines": true, 36 | "space_after_anon_function": false, 37 | "space_before_conditional": true, 38 | "space_in_empty_paren": false, 39 | "space_in_paren": false, 40 | "unescape_strings": false, 41 | "wrap_line_length": 0 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "esprima": "babel-jscs", 3 | "esnext": true, 4 | "requireCurlyBraces": ["else", "for", "while", "do", "try", "catch", "case", "default"], 5 | "requireSpaceAfterKeywords": [ 6 | "if", 7 | "else", 8 | "for", "while", "do", "switch", "return", "try", "catch" 9 | ], 10 | "requireParenthesesAroundIIFE": true, 11 | "requireSpacesInConditionalExpression": true, 12 | "requireSpacesInFunctionExpression": { 13 | "beforeOpeningCurlyBrace": true 14 | }, 15 | "requireSpacesInFunctionDeclaration": { 16 | "beforeOpeningCurlyBrace": true 17 | }, 18 | "disallowMultipleVarDecl": "exceptUndefined", 19 | "requireBlocksOnNewline": 1, 20 | "disallowPaddingNewlinesInBlocks": true, 21 | "disallowEmptyBlocks": true, 22 | "disallowSpacesInsideObjectBrackets": "all", 23 | "disallowSpacesInsideArrayBrackets": "all", 24 | "disallowSpacesInsideParentheses": true, 25 | "disallowSpaceAfterObjectKeys": true, 26 | "requireCommaBeforeLineBreak": true, 27 | "disallowSpacesInCallExpression": true, 28 | "requireSpaceBeforeObjectValues": true, 29 | "requireOperatorBeforeLineBreak": [ 30 | "?", 31 | "+", 32 | "-", 33 | "/", 34 | "*", 35 | "=", 36 | "==", 37 | "===", 38 | "!=", 39 | "!==", 40 | ">", 41 | ">=", 42 | "<", 43 | "<=", 44 | "||", 45 | "&&" 46 | ], 47 | "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"], 48 | "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"], 49 | "requireSpaceBeforeBinaryOperators": [ 50 | "?", "+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<=" 51 | ], 52 | "requireSpaceAfterBinaryOperators": [ 53 | "?", "+", "/", "*", ":", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<=" 54 | ], 55 | "disallowSpaceAfterBinaryOperators": ["!"], 56 | "disallowImplicitTypeConversion": ["numeric", "boolean", "binary", "string"], 57 | "requireCamelCaseOrUpperCaseIdentifiers": "ignoreProperties", 58 | "disallowKeywords": ["with"], 59 | "disallowMultipleLineStrings": true, 60 | "disallowMultipleLineBreaks": true, 61 | "validateLineBreaks": "LF", 62 | "validateQuoteMarks": null, 63 | "validateIndentation": 2, 64 | "disallowMixedSpacesAndTabs": true, 65 | "disallowTrailingWhitespace": true, 66 | "disallowTrailingComma": true, 67 | "disallowKeywordsOnNewLine": ["else", "catch"], 68 | "requireLineFeedAtFileEnd": true, 69 | "maximumLineLength": { 70 | "value": 150, 71 | "allowUrlComments": true 72 | }, 73 | "requireCapitalizedConstructors": true, 74 | "requireDotNotation": true, 75 | "requireSpaceAfterLineComment": true, 76 | "validateParameterSeparator": ", ", 77 | "disallowNewlineBeforeBlockStatements": true, 78 | "requirePaddingNewlinesBeforeKeywords": [ 79 | "do", 80 | "for", 81 | "if", 82 | "switch", 83 | "try", 84 | "void", 85 | "while", 86 | "with", 87 | "return" 88 | ], 89 | "excludeFiles": ["node_modules/**", "dist", "coverage"] 90 | } 91 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Christian Alfoni 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React CSSModules Sass Boilerplate 2 | This repo contains boilerplate for using [React CSS Modules](https://github.com/gajus/react-css-modules) with SASS. It's built using webpack. 3 | 4 | 5 | ## Get Started 6 | Run `npm install` then `npm run startdev` 7 | 8 | To build and run for production, run `npm run build` then `npm run start`. 9 | -------------------------------------------------------------------------------- /app/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import styles from './App.scss'; 5 | 6 | class App extends React.Component { 7 | 8 | render() { 9 | const { children } = this.props; 10 | 11 | return ( 12 |
13 | {children} 14 |
15 | ) 16 | } 17 | } 18 | 19 | export default App; 20 | -------------------------------------------------------------------------------- /app/App.scss: -------------------------------------------------------------------------------- 1 | @import "./styles/reset"; 2 | @import "./styles/fonts"; 3 | @import "./styles/vars"; 4 | @import "./styles/typeplate/typeplate"; 5 | @import "./styles/z-index"; 6 | 7 | *{ 8 | box-sizing: border-box; 9 | } 10 | 11 | body{ 12 | font-family: $sansSerif; 13 | font-weight: 400; 14 | background-color: darken(white, 10%); 15 | } 16 | 17 | a{ 18 | text-decoration: none; 19 | } 20 | -------------------------------------------------------------------------------- /app/animations.js: -------------------------------------------------------------------------------- 1 | export function AnimateItem(item, animation){ 2 | TweenMax.to(item, animation.duration, animation.properties) 3 | } 4 | -------------------------------------------------------------------------------- /app/components/page/HomePage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Page from './page.js'; 3 | import Section from '../sections/section.js'; 4 | 5 | class HomePage extends React.Component{ 6 | 7 | render(){ 8 | return ( 9 | 10 |
11 |
12 |
13 |
14 |
15 | ) 16 | } 17 | 18 | } 19 | 20 | export default HomePage; 21 | -------------------------------------------------------------------------------- /app/components/page/PageAnimations.js: -------------------------------------------------------------------------------- 1 | import gsap from 'gsap'; 2 | 3 | let PageAnimations = { 4 | defaults: { 5 | duration: .5, 6 | properties: { 7 | opacity: 1, 8 | ease: Power4.easeOut 9 | } 10 | } 11 | } 12 | 13 | PageAnimations.animateIn = { 14 | duration: PageAnimations.defaults.duration, 15 | properties: PageAnimations.defaults.properties 16 | } 17 | 18 | PageAnimations.animateOut = { 19 | duration: PageAnimations.defaults.duration, 20 | properties: { 21 | opacity: 0, 22 | ease: Power2.easeOut 23 | } 24 | } 25 | 26 | export default PageAnimations; 27 | -------------------------------------------------------------------------------- /app/components/page/page.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import PageAnimations from './PageAnimations.js'; 4 | import { AnimateItem } from '../../animations.js' 5 | 6 | import CSSModules from 'react-css-modules'; 7 | import styles from './page.scss'; 8 | import wrapperStyles from '../../styles/wrapper.scss'; 9 | 10 | 11 | // Write your package code here! 12 | @CSSModules(styles, {allowMultiple: true}) 13 | class Page extends React.Component{ 14 | 15 | componentDidMount(){ 16 | let animation = this.props.animation || PageAnimations.animateIn; 17 | AnimateItem(this._page, PageAnimations.animateIn); 18 | } 19 | 20 | render(){ 21 | 22 | const { children } = this.props; 23 | 24 | return( 25 |
this._page = c } styleName="base"> 26 | {children} 27 |
28 | ) 29 | } 30 | }; 31 | 32 | export default Page; 33 | -------------------------------------------------------------------------------- /app/components/page/page.scss: -------------------------------------------------------------------------------- 1 | .base{ 2 | composes: container from '../../styles/flexbox.scss'; 3 | position: relative; 4 | min-height: 100vh; 5 | background-color: darken(white, 10%); 6 | background-size: cover; 7 | background-position: center center; 8 | opacity: 0; 9 | transition: opacity 300ms ease-out; 10 | } 11 | -------------------------------------------------------------------------------- /app/components/sections/section.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import CSSModules from 'react-css-modules'; 4 | import styles from './section.scss'; 5 | 6 | @CSSModules(styles, {allowMultiple: true}) 7 | class Section extends React.Component{ 8 | 9 | _renderPostTitle(){ 10 | const title = this.props.title.match(/.{1,2}/g); 11 | return title.map( (fragment, index) => { 12 | return {fragment}

13 | }) 14 | } 15 | 16 | render(){ 17 | 18 | const { type, backgroundImage } = this.props; 19 | const bg = { 20 | backgroundImage: "url('" + backgroundImage + "')", 21 | }; 22 | 23 | const bgClass = backgroundImage ? 'with_background' : ''; 24 | 25 | return( 26 |
27 |

{this._renderPostTitle()}

28 | {this.props.children} 29 |
30 | ) 31 | } 32 | } 33 | 34 | export default Section; 35 | -------------------------------------------------------------------------------- /app/components/sections/section.scss: -------------------------------------------------------------------------------- 1 | .base{ 2 | composes: child_1 container justify_center from '../../styles/flexbox.scss'; 3 | position: relative; 4 | } 5 | 6 | .primary{ 7 | composes: base; 8 | composes: priamry primary_bg from '../../styles/colors.scss'; 9 | } 10 | 11 | .secondary{ 12 | composes: base; 13 | composes: secondary_bg from '../../styles/colors.scss'; 14 | } 15 | 16 | .dark{ 17 | composes: base; 18 | composes: dark_bg from '../../styles/colors.scss'; 19 | } 20 | 21 | .tertiary{ 22 | composes: base; 23 | composes: tertiary_bg from '../../styles/colors.scss'; 24 | } 25 | 26 | .with_background{ 27 | composes: cover center from '../../styles/background.scss'; 28 | position: relative; 29 | 30 | &:after{ 31 | background-color: fade-out(black, .65); 32 | } 33 | } 34 | 35 | .title{ 36 | composes: strong uppercase center bold from '../../styles/typography.scss'; 37 | composes: self_center from '../../styles/flexbox.scss'; 38 | // background-color: fade-out(white, .2); 39 | border: 10px solid fade-out(black, .8); 40 | color: white; 41 | font-size: 6vw; 42 | line-height: 5vw; 43 | padding: 1rem 2rem; 44 | } 45 | -------------------------------------------------------------------------------- /app/index.tpl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | React CSSModules Sass boilerplate 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /app/main.js: -------------------------------------------------------------------------------- 1 | import 'babel-polyfill'; 2 | 3 | import React from 'react'; 4 | import { render } from 'react-dom'; 5 | 6 | import { Router, browserHistory, IndexRoute, Route } from 'react-router'; 7 | 8 | import App from './App.js'; 9 | import HomePage from './components/page/HomePage.js'; 10 | 11 | 12 | render(( 13 | 14 | 15 | 16 | 17 | 18 | ), document.getElementById('root')) 19 | -------------------------------------------------------------------------------- /app/styles/background.scss: -------------------------------------------------------------------------------- 1 | .cover{ 2 | background-size: cover; 3 | } 4 | 5 | .center{ 6 | background-position: center center; 7 | } 8 | 9 | .with_overlay{ 10 | &:after{ 11 | content: ''; 12 | position: absolute; 13 | top: 0; 14 | left: 0; 15 | height: 100%; 16 | width: 100%; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/styles/colors.scss: -------------------------------------------------------------------------------- 1 | @import "vars"; 2 | 3 | .primary_bg{ 4 | background-color: $primary; 5 | } 6 | 7 | .secondary_bg{ 8 | background-color: $secondary; 9 | } 10 | 11 | .tertiary_bg{ 12 | background-color: $tertiary; 13 | } 14 | 15 | .quaternary_bg{ 16 | background-color: $quaternary; 17 | } 18 | 19 | .dark_bg{ 20 | background-color: $dark; 21 | } 22 | 23 | .faded_dark_bg{ 24 | background-color: fade-out($dark, .1); 25 | } 26 | 27 | .red-border{ 28 | border-color: darken($red, 10%); 29 | } 30 | 31 | .dark-border{ 32 | border-color: darken($dark, 10%); 33 | } 34 | 35 | .primary{ 36 | color: $primary; 37 | } 38 | 39 | .dark{ 40 | color: $dark; 41 | } 42 | -------------------------------------------------------------------------------- /app/styles/flexbox.scss: -------------------------------------------------------------------------------- 1 | .container{ 2 | display: flex; 3 | } 4 | 5 | .child_1{ 6 | flex: 1; 7 | } 8 | 9 | .justify_center{ 10 | justify-content: center; 11 | } 12 | 13 | .self_center{ 14 | align-self: center; 15 | } 16 | -------------------------------------------------------------------------------- /app/styles/fonts.scss: -------------------------------------------------------------------------------- 1 | @import url(http://fonts.googleapis.com/css?family=Lora:400,700,400italic); 2 | @import url(http://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700); 3 | -------------------------------------------------------------------------------- /app/styles/reset.scss: -------------------------------------------------------------------------------- 1 | /** * Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/) * http://cssreset.com */html, body, div, span, applet, object, iframe,h1, h2, h3, h4, h5, h6, p, blockquote, pre,a, abbr, acronym, address, big, cite, code,del, dfn, em, img, ins, kbd, q, s, samp,small, strike, strong, sub, sup, tt, var,b, u, i, center,dl, dt, dd, ol, ul, li,fieldset, form, label, legend,table, caption, tbody, tfoot, thead, tr, th, td,article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary,time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline;}/* HTML5 display-role reset for older browsers */article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block;}body { line-height: 1;}ol, ul { list-style: none;}blockquote, q { quotes: none;}blockquote:before, blockquote:after,q:before, q:after { content: ''; content: none;}table { border-collapse: collapse; border-spacing: 0;} 2 | -------------------------------------------------------------------------------- /app/styles/typeplate/_typeplate-extends.scss: -------------------------------------------------------------------------------- 1 | // $Ampersands 2 | // -------------------------------------// 3 | // Call your custom ampersand on any element. 4 | // 5 | // @markup
Dewey Cheat 'em & Howe
6 | // @example .ampersand { @extend %typl8-amp-placeholder; } 7 | 8 | %typl8-amp-placeholder { 9 | @include typl8-ampersand($typl8-amp-fontface, $typl8-amp-fontfamily); 10 | } 11 | 12 | 13 | // $Blockquote 14 | // -------------------------------------// 15 | // Style your blockquote citations 16 | // 17 | // @example .citation { @extend %typl8-cite; } 18 | 19 | %typl8-cite { 20 | @include typl8-cite-style($typl8-cite-display, $typl8-cite-align, $typl8-cite-font-size); 21 | } 22 | 23 | 24 | // $Wordwrap 25 | // -------------------------------------// 26 | // Control word wrapping and breaks in your text. 27 | // 28 | // 'normal' Lines may only break at normal word break points. 29 | // 'break-word' Unbreakable words may be broken at arbitrary points. 30 | // 31 | // @example article { @extend %typl8-breakword; } 32 | 33 | %typl8-breakword { 34 | word-wrap: break-word; 35 | } 36 | 37 | %typl8-normal-wrap { 38 | word-wrap: normal; 39 | } 40 | 41 | %typl8-inherit-wrap { 42 | word-wrap: auto; 43 | } 44 | 45 | 46 | // $OpenType 47 | // -------------------------------------// 48 | // Control OpenType feature settings where desired. 49 | // 50 | // @use 51 | // smallcaps body { @extend %typl8-ot--smcp; } 52 | // text figures body { @extend %typl8-ot--onum; } 53 | 54 | %typl8-ot--smcp { 55 | @each $prefix in $typl8-prefixes { 56 | #{$prefix}font-feature-settings: "smcp"; 57 | } 58 | } 59 | 60 | %typl8-ot--onum { 61 | @each $prefix in $typl8-prefixes { 62 | #{$prefix}font-feature-settings: 'onum'; 63 | } 64 | } -------------------------------------------------------------------------------- /app/styles/typeplate/_typeplate-fonts.scss: -------------------------------------------------------------------------------- 1 | // $Unicode-Range-Ampersand 2 | // -------------------------------------// 3 | 4 | @font-face { 5 | font-family: '#{$typl8-amp-fontface}'; 6 | src: $typl8-amp-src; 7 | unicode-range: U+0026; 8 | } 9 | 10 | @font-face { 11 | font-family: '#{$typl8-amp-fontface}'; // fallback 12 | src: $typl8-amp-fallback; 13 | unicode-range: U+270C; 14 | } 15 | 16 | 17 | // $Icon-Font-Helper 18 | // -------------------------------------// 19 | // Loading multiple icon fonts using Compass 20 | // 21 | // 1. Install Compass. 22 | // 2. Create a 'fonts' directory in the root of your project. 23 | // 3. Specify within your 'config.rb' the following line… 24 | // fonts_dir = "name-of-your-fonts-directory" ( i.e. fonts_dir = "fonts" ) 25 | // 4. Set your '$typl8-icon-fonts' variable as noted 26 | 27 | @if ($typl8-icon-fonts != null) { 28 | @each $font in $typl8-icon-fonts { 29 | @include font-face($font, 30 | font-files( 31 | '#{$font}/#{$font}.woff', 32 | '#{$font}/#{$font}.ttf', 33 | '#{$font}/#{$font}.svg', svg 34 | ), 35 | '#{$font}/#{$font}.eot' 36 | ) 37 | } 38 | } -------------------------------------------------------------------------------- /app/styles/typeplate/_typeplate-functions.scss: -------------------------------------------------------------------------------- 1 | // $Context Calculator 2 | // -------------------------------------// 3 | // target / context = result 4 | // 5 | // @example p { font-size: typl8-context-calc(24, 16, px, 18 * 1.65); } 6 | 7 | @function typl8-context-calc($scale, $base, $value) { 8 | @return ($scale/$base) + $value; 9 | } 10 | 11 | 12 | // $Measure-Margin 13 | // -------------------------------------// 14 | // divide 1 unit of measure by given font-size & return relative value 15 | 16 | @function typl8-measure-margin($scale, $measure, $value) { 17 | $pixelValue: $scale/$measure; // ($measure/$scale) issue#40 https://github.com/typeplate/starter-kit/issues/40 18 | $remValue: $pixelValue * $typl8-font-base; 19 | 20 | @if $value == rem { 21 | @return $pixelValue + $value; 22 | } @else if $value == em { 23 | @return ($remValue/$scale) + $value; 24 | } @else { 25 | @return $remValue * 1px; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/styles/typeplate/_typeplate-helpers.scss: -------------------------------------------------------------------------------- 1 | // $Dropcap 2 | // -------------------------------------// 3 | 4 | .typl8-drop-cap { 5 | @include typl8-dropcap( 6 | $typl8-dropcap-float-position, 7 | $typl8-dropcap-font-size, 8 | $typl8-dropcap-font-family, 9 | $typl8-dropcap-txt-indent, 10 | $typl8-dropcap-margin, 11 | $typl8-dropcap-padding, 12 | $typl8-dropcap-color, 13 | $typl8-dropcap-line-height, 14 | $typl8-dropcap-bg 15 | ); 16 | } 17 | 18 | // @notes 19 | // combats our sibling paragraph syling and indentation 20 | p + .typl8-drop-cap { 21 | text-indent: 0; 22 | margin-top: 0; 23 | } 24 | 25 | 26 | // $Definition-Lists 27 | // -------------------------------------// 28 | /** 29 | * Lining Definition Style Markup 30 | * 31 |
32 |
33 |
34 |
35 | * 36 | * Extend this object into your markup. 37 | * 38 | */ 39 | 40 | .typl8-lining { 41 | @include typl8-definition-list-style(lining); 42 | } 43 | 44 | /** 45 | * Dictionary Definition Style Markup 46 | * 47 |
48 |
49 |
50 |
51 | * 52 | * Extend this object into your markup. 53 | * 54 | */ 55 | 56 | .typl8-dictionary-style { 57 | @include typl8-definition-list-style(dictionary-style); 58 | } 59 | 60 | 61 | // $Blockquote-Markup 62 | // -------------------------------------// 63 | /** 64 | * Blockquote Markup 65 | * 66 |
67 |
68 |

69 |
70 |
71 | 72 | 73 | 74 |
75 |
76 | * 77 | * Extend this object into your markup. 78 | * 79 | */ 80 | 81 | 82 | // $Pull-Quotes 83 | // -------------------------------------// 84 | // @notes 85 | // http://24ways.org/2005/swooshy-curly-quotes-without-images 86 | 87 | /** 88 | * Pull Quotes Markup 89 | * 90 | 95 | * 96 | * Extend this object into your custom stylesheet. 97 | * 98 | */ 99 | 100 | .typl8-pull-quote { 101 | @include typl8-pull-quotes( 102 | $typl8-pull-quote-fontsize, 103 | $typl8-pull-quote-opacity, 104 | $typl8-pull-quote-color 105 | ); 106 | } 107 | 108 | 109 | // $Figures 110 | // -------------------------------------// 111 | /** 112 | * Figures Markup 113 | * 114 |
115 |
116 | Fig. X.X | 117 |
118 |
119 | * 120 | * Extend this object into your markup. 121 | * 122 | */ 123 | 124 | 125 | // $Footnotes 126 | // -------------------------------------// 127 | /** 128 | * Footnote Markup : Replace 'X' with your unique number for each footnote 129 | * 130 |
131 |

132 | 137 |
138 | * 139 | * Extend this object into your markup. 140 | * 141 | */ -------------------------------------------------------------------------------- /app/styles/typeplate/_typeplate-mixins.scss: -------------------------------------------------------------------------------- 1 | // $Typescale 2 | // -------------------------------------// 3 | 4 | @mixin typl8-typescale($scale, $base, $value, $measure:"") { 5 | @if $value == rem { 6 | font-size: $scale * 1px; 7 | // font-size: typl8-context-calc($scale, $base, $value); 8 | } @else if $value == em { 9 | font-size: typl8-context-calc($scale, $base, $value); 10 | } @else { 11 | font-size: $scale * 1px; 12 | } 13 | 14 | @if $measure != "" { 15 | @if $value == rem { 16 | // margin-bottom: typl8-measure-margin($scale, $measure, $value: px); 17 | margin-bottom: typl8-measure-margin($scale, $measure, $value); 18 | } @else if $value == em { 19 | margin-bottom: typl8-measure-margin($scale, $measure, $value: em); 20 | } @else { 21 | margin-bottom: typl8-measure-margin($scale, $measure, $value: px); 22 | } 23 | } 24 | } 25 | 26 | 27 | // $Headings 28 | // https://github.com/typeplate/starter-kit/issues/27 29 | // -------------------------------------// 30 | // Props to Harry Roberts for this trick. 31 | // 32 | // @notes 33 | // optimizeLegibility Enables ligatures and kerning 34 | // single line height Fixes large spaces when a heading wraps two lines 35 | 36 | %typl8-hN { 37 | text-rendering: optimizeLegibility; 38 | line-height: 1; 39 | margin-top: 0; 40 | color: $typl8-heading-color; 41 | } 42 | 43 | @mixin typl8-headings() { 44 | @each $name, $size in $typl8-scale { 45 | .#{$name} { 46 | @extend %typl8-hN; 47 | @include typl8-typescale( 48 | $size, 49 | $typl8-font-base, 50 | $typl8-typescale-unit, 51 | $typl8-measure 52 | ); 53 | } 54 | } 55 | } 56 | 57 | @mixin typl8-headings-style() { 58 | @each $h, $size in $typl8-headings { 59 | #{$h} { 60 | @extend .#{$size}; 61 | } 62 | } 63 | } 64 | 65 | 66 | // $Hypens 67 | // -------------------------------------// 68 | // @notes 69 | // http://caniuse.com/#search=hyphens 70 | // http://trentwalton.com/2011/09/07/css-hyphenation 71 | // 72 | // @values [ none | manual | auto ] 73 | 74 | @mixin typl8-hyphens($val) { 75 | @each $prefix in $typl8-prefixes { 76 | #{$prefix}hyphens: $val; 77 | } 78 | } 79 | 80 | 81 | // $Smallcaps 82 | // -------------------------------------// 83 | // @notes 84 | // http://caniuse.com/#search=font-variant 85 | // http://blog.hypsometry.com/articles/true-small-capitals-with-font-face 86 | // 'font-variant' depends on the font family in use. 87 | // Some font-families don't support small caps 88 | // or don't provide them with their Webfont. 89 | 90 | @mixin typl8-smallcaps($color, $font-weight) { 91 | @each $prefix in $typl8-prefixes { 92 | #{$prefix}font-variant: small-caps; 93 | } 94 | font-weight: $font-weight; 95 | text-transform: lowercase; 96 | color: $color; 97 | } 98 | 99 | 100 | // $Fontsize-Adjust 101 | // -------------------------------------// 102 | // @notes 103 | // firefox 17+ only (as of Feb. 2013) 104 | // correct x-height for fallback fonts. 105 | // requires secret formula yet to be discovered. 106 | 107 | @mixin typl8-font-size-adjust($adjust-value) { 108 | font-size-adjust: $adjust-value; 109 | } 110 | 111 | 112 | // $Ampersand 113 | // -------------------------------------// 114 | 115 | @mixin typl8-ampersand($typl8-amp-fontfamily...) { 116 | font-family: $typl8-amp-fontfamily; 117 | } 118 | 119 | 120 | // $Blockquote 121 | // -------------------------------------// 122 | // "-" is your citation flourish. 123 | // 124 | // I always say important things because I'm so smart 125 | // - Super Important Person 126 | // 127 | // @example .your-class-name { @include typl8-blockquote("-"); } 128 | 129 | @mixin typl8-blockquote($citation-flourish) { 130 | p { 131 | &:last-of-type { 132 | margin-bottom: -#{$typl8-line-height/2}em; 133 | } 134 | } 135 | 136 | + figcaption { 137 | @extend %typl8-cite; 138 | 139 | &:before { 140 | content: $citation-flourish; 141 | } 142 | } 143 | } 144 | 145 | @mixin typl8-cite-style($display, $text-align, $font-size) { 146 | display: $display; 147 | font-size: $font-size; 148 | text-align: $text-align; 149 | } 150 | 151 | 152 | // $Pull-Quotes 153 | // -------------------------------------// 154 | 155 | @mixin typl8-pull-quotes($fontsize, $opacity, $color) { 156 | position: relative; 157 | padding: typl8-context-calc($fontsize, $fontsize, em); 158 | 159 | &:before, 160 | &:after { 161 | height: typl8-context-calc($fontsize, $fontsize, em); 162 | opacity: $opacity; 163 | position: absolute; 164 | font-size: $fontsize; 165 | color: $color; 166 | } 167 | 168 | &:before { 169 | content: '“'; 170 | top: 0; 171 | left: 0; 172 | } 173 | 174 | &:after { 175 | content: '”'; 176 | bottom: 0; 177 | right: 0; 178 | } 179 | } 180 | 181 | 182 | // $Dropcap 183 | // -------------------------------------// 184 | // Add styling to intro paragraphs using a dropcap 185 | // 186 | // @markup

Lorem ipsum dolor sit amet

187 | // @example .dropcap { @include typl8-dropcap; } 188 | 189 | @mixin typl8-dropcap( 190 | $float-position, 191 | $font-size, 192 | $font-family, 193 | $txt-indent, 194 | $margin, 195 | $padding, 196 | $color, 197 | $line-height, 198 | $bg 199 | ) { 200 | &:first-letter { 201 | float: $float-position; 202 | margin: $margin; 203 | padding: $padding; 204 | font-size: $font-size; 205 | font-family: $font-family; 206 | line-height: $line-height; 207 | text-indent: $txt-indent; 208 | background: $bg; 209 | color: $color; 210 | } 211 | } 212 | 213 | 214 | // $Code 215 | // -------------------------------------// 216 | 217 | @mixin typl8-white-space($wrap-space) { 218 | @if $wrap-space == 'pre-wrap' { 219 | white-space: #{-moz-}$wrap-space; 220 | white-space: $wrap-space; 221 | } @else { 222 | white-space: $wrap-space; 223 | } 224 | } 225 | 226 | 227 | // $Definition-Lists 228 | // -------------------------------------// 229 | // @notes 230 | // http://lea.verou.me/2012/02/flexible-multiline-definition-lists-with-2-lines-of-css 231 | // http://lea.verou.me/2012/02/flexible-multiline-definition-lists-with-2-lines-of-css 232 | 233 | @mixin typl8-definition-list-style($style) { 234 | @if $style == lining { 235 | dt, 236 | dd { 237 | display: inline; 238 | margin: 0; 239 | } 240 | 241 | dt, 242 | dd { 243 | & + dt { 244 | &:before { 245 | content: "\A"; 246 | white-space: pre; 247 | } 248 | } 249 | } 250 | 251 | dd { 252 | & + dd { 253 | &:before { 254 | content: ", "; 255 | } 256 | } 257 | &:before { 258 | content: ": "; 259 | margin-left: -0.2rem; //removes extra space between the dt and the colon 260 | } 261 | } 262 | } 263 | 264 | @if $style == dictionary-style { 265 | dt { 266 | display: inline; 267 | counter-reset: definitions; 268 | & + dt { 269 | &:before { 270 | content: ", "; 271 | margin-left: -0.2rem; // removes extra space between the dt and the comma 272 | } 273 | } 274 | } 275 | 276 | dd { 277 | display: block; 278 | counter-increment: definitions; 279 | &:before { 280 | content: counter(definitions, decimal) ". "; 281 | } 282 | } 283 | } 284 | } 285 | -------------------------------------------------------------------------------- /app/styles/typeplate/_typeplate-styles.scss: -------------------------------------------------------------------------------- 1 | // $Global 2 | // -------------------------------------// 3 | 4 | html { 5 | @if $typl8-custom-font { 6 | font: $typl8-font-weight #{$typl8-font-size + "%"}/#{$typl8-line-height} $typl8-custom-font, $typl8-font-family; 7 | } @else { 8 | font: $typl8-font-weight #{$typl8-font-size + "%"}/#{$typl8-line-height} $typl8-font-family; 9 | } 10 | } 11 | 12 | body { 13 | @extend %typl8-breakword; 14 | // @include typl8-hyphens(auto); 15 | color: $typl8-copy-color; 16 | } 17 | 18 | h1,h2,h3,h4,h5,h6{ 19 | font-family: $serif; 20 | } 21 | 22 | 23 | // $Headings 24 | // http://codepen.io/grayghostvisuals/pen/IKsbw 25 | // -------------------------------------// 26 | 27 | @include typl8-headings; 28 | @include typl8-headings-style; 29 | 30 | 31 | // $Parargraphs 32 | // -------------------------------------// 33 | 34 | p { 35 | margin: auto auto $typl8-indent-val; 36 | @if $typl8-paragraph-spacing == true { 37 | & + p { 38 | text-indent: $typl8-indent-val; 39 | margin-top: -$typl8-indent-val; 40 | } 41 | } 42 | } 43 | 44 | // $Blockquotes 45 | // -------------------------------------// 46 | 47 | blockquote { 48 | + figcaption cite { 49 | @extend %typl8-cite; 50 | } 51 | } 52 | 53 | 54 | // $Legal Text 55 | // -------------------------------------// 56 | 57 | small { 58 | font-size: $typl8-small-print-size; 59 | } 60 | 61 | 62 | // $Hyphenation 63 | // -------------------------------------// 64 | // @notes 65 | // http://meyerweb.com/eric/thoughts/2012/12/17/where-to-avoid-css-hyphenation 66 | 67 | input, 68 | abbr, 69 | acronym, 70 | blockquote, 71 | code, 72 | kbd, 73 | q, 74 | samp, 75 | var { 76 | @include typl8-hyphens(none); 77 | } 78 | 79 | 80 | // $Codeblocks 81 | // -------------------------------------// 82 | 83 | pre { 84 | @include typl8-white-space(pre); 85 | 86 | code { 87 | @extend %typl8-normal-wrap; 88 | @include typl8-white-space(pre-wrap); 89 | } 90 | } 91 | 92 | code { 93 | @include typl8-white-space(pre); 94 | font-family: monospace; 95 | } 96 | 97 | 98 | // $Smallcaps 99 | // -------------------------------------// 100 | 101 | abbr { 102 | @include typl8-smallcaps($typl8-smcps-color, $typl8-smcps-weight); 103 | &[title]:hover { 104 | cursor: help; 105 | } 106 | } -------------------------------------------------------------------------------- /app/styles/typeplate/_typeplate-vars.scss: -------------------------------------------------------------------------------- 1 | // $Base 2 | // -------------------------------------// 3 | // General base styles for type 4 | // 5 | // $typl8-custom-font [<"Custom-Font-Name">[, ]] 6 | // $typl8-font-size 112.5% converts to an 18px base 7 | // $typl8-font-base converts % base value to a px value (16 * (112.5/100) = 18) 8 | // $typl8-font-family non-font-face stack 9 | 10 | $typl8-serif-boolean: true !default; 11 | $typl8-custom-font: false !default; 12 | $typl8-font-family: if($typl8-serif-boolean, serif, sans-serif) !default; 13 | $typl8-font-weight: normal !default; 14 | $typl8-line-height: 1.65 !default; 15 | $typl8-font-size: 112.5 !default; 16 | $typl8-font-base: 16 * ($typl8-font-size/100) !default; 17 | $typl8-measure: $typl8-font-base * $typl8-line-height !default; 18 | $typl8-prefixes: -webkit-, -moz-, -ms-, '' !default; 19 | 20 | 21 | // $Paragraphs 22 | // -------------------------------------// 23 | // Controls paragraphs vertical whitespace 24 | // for subsequent paragraphs. 25 | // 26 | // $typl8-paragraph-spacing [<'false'> | <'true'>] 27 | 28 | $typl8-paragraph-spacing: false !default; 29 | $typl8-indent-val: 1.5em !default; 30 | 31 | 32 | // $Small-Print 33 | // -------------------------------------// 34 | 35 | $typl8-small-print-size: 65% !default; 36 | 37 | 38 | // $Base-Colors 39 | // -------------------------------------// 40 | 41 | $typl8-heading-color: #222 !default; 42 | $typl8-copy-color: #444 !default; 43 | 44 | 45 | // $Ampersands 46 | // -------------------------------------// 47 | 48 | $typl8-amp-fontface: Ampersand !default; 49 | $typl8-amp-fontfamily: Verdana, sans-serif !default; 50 | $typl8-amp-src: local('Georgia'), local('Garamond'), local('Palatino'), local('Book Antiqua') !default; 51 | $typl8-amp-fallback: local('Georgia') !default; 52 | 53 | 54 | // $Icon-Font-Helper 55 | // -------------------------------------// 56 | // Link single or multiple icon font sets. Requires Compass 57 | // 58 | // single icon font $typl8-icon-fonts: (icon-name); 59 | // multiple icon fonts $typl8-icon-fonts: (icon-name1, icon-name2, icon-name3); 60 | 61 | $typl8-icon-fonts: null !default; 62 | 63 | 64 | // $Typescale 65 | // -------------------------------------// 66 | // Greek heading names and scale using base font-size 67 | // 68 | // typl8-tera 117 = 18 × 6.5 69 | // typl8-giga 90 = 18 × 5 70 | // typl8-mega 72 = 18 × 4 71 | // typl8-alpha 60 = 18 × 3.3333 72 | // typl8-beta 48 = 18 × 2.6667 73 | // typl8-gamma 36 = 18 × 2 74 | // typl8-delta 24 = 18 × 1.3333 75 | // typl8-epsilon 21 = 18 × 1.1667 76 | // typl8-zeta 18 = 18 × 1 77 | 78 | $typl8-scale: ( 79 | typl8-tera: 117, 80 | typl8-giga: 90, 81 | typl8-mega: 72, 82 | typl8-alpha: 60, 83 | typl8-beta: 48, 84 | typl8-gamma: 36, 85 | typl8-delta: 24, 86 | typl8-epsilon: 21, 87 | typl8-zeta: 18, 88 | ) !default; 89 | 90 | $typl8-headings: ( 91 | h1: typl8-mega, 92 | h2: typl8-alpha, 93 | h3: typl8-beta, 94 | h4: typl8-gamma, 95 | h5: typl8-delta, 96 | h6: typl8-zeta 97 | ) !default; 98 | 99 | 100 | // $Typescale Unit 101 | // -------------------------------------// 102 | 103 | $typl8-typescale-unit: rem !default; 104 | 105 | 106 | // $Pull-Quotes 107 | // -------------------------------------// 108 | 109 | $typl8-pull-quote-fontsize: 4em !default; 110 | $typl8-pull-quote-opacity: 0.5 !default; 111 | $typl8-pull-quote-color: #dc976e !default; 112 | 113 | 114 | // $Citations 115 | // -------------------------------------// 116 | 117 | $typl8-cite-display: block !default; 118 | $typl8-cite-align: right !default; 119 | $typl8-cite-font-size: inherit !default; 120 | 121 | 122 | // $Small-Caps 123 | // -------------------------------------// 124 | 125 | $typl8-smcps-color: gray !default; 126 | $typl8-smcps-weight: 600 !default; 127 | 128 | 129 | // $DropCap 130 | // -------------------------------------// 131 | 132 | $typl8-dropcap-float-position: left !default; 133 | $typl8-dropcap-font-size: 4em !default; 134 | $typl8-dropcap-font-family: inherit !default; 135 | $typl8-dropcap-txt-indent: 0 !default; 136 | $typl8-dropcap-margin: 10px 10px 0 0 !default; 137 | $typl8-dropcap-padding: 0 20px !default; 138 | $typl8-dropcap-color: inherit !default; 139 | $typl8-dropcap-line-height: 1 !default; 140 | $typl8-dropcap-bg: transparent !default; -------------------------------------------------------------------------------- /app/styles/typeplate/_typeplate.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | Typeplate : Starter Kit 3 | URL ........... http://typeplate.com 4 | Version ....... 2.1.0 5 | Github ........ https://github.com/typeplate/starter-kit 6 | Authors ....... Dennis Gaebel (@gryghostvisuals) & Zachary Kain (@zakkain) 7 | License ....... Creative Commmons Attribution 3.0 8 | License URL ... https://github.com/typeplate/starter-kit/blob/master/license.txt 9 | */ 10 | 11 | @import "typeplate-vars"; 12 | @import "typeplate-fonts"; 13 | @import "typeplate-functions"; 14 | @import "typeplate-mixins"; 15 | @import "typeplate-extends"; 16 | @import "typeplate-styles"; 17 | @import "typeplate-helpers"; -------------------------------------------------------------------------------- /app/styles/typography.scss: -------------------------------------------------------------------------------- 1 | .black{ 2 | font-weight: 900; 3 | } 4 | 5 | .bold{ 6 | font-weight: 700; 7 | } 8 | 9 | .thin{ 10 | font-weight: 100; 11 | } 12 | 13 | .uppercase{ 14 | text-transform: uppercase; 15 | } 16 | 17 | .center{ 18 | text-align: center; 19 | } 20 | -------------------------------------------------------------------------------- /app/styles/vars.scss: -------------------------------------------------------------------------------- 1 | $serif: 'proxima-nova', Helvetica, serif; 2 | $sansSerif: 'proxima-nova', Helvetica, sans-serif; 3 | 4 | $primary: #e71e2d; 5 | $secondary: #510a0d; 6 | $tertiary: #3dbbd0; 7 | $quaternary: #8C3B6C; 8 | $green: #2E294E; 9 | $red: #E71D36; 10 | $dark: #1b1e1f; 11 | $lightGrey: #f3f3f3; 12 | $borderGrey: #e0e0e0; 13 | $twitter: #55acee; 14 | 15 | // Breakpoints 16 | // ------------------------- Source: http://blog.scur.pl/2012/06/variable-media-queries-less-css/ 17 | $highdensity: "only screen and (-webkit-min-device-pixel-ratio: 1.5)", 18 | "only screen and (min--moz-device-pixel-ratio: 1.5)", 19 | "only screen and (-o-min-device-pixel-ratio: 3/2)", 20 | "only screen and (min-device-pixel-ratio: 1.5)"; 21 | $mobile: "only screen and (max-width: 568px)"; 22 | $mobile-landscape: "only screen and (min-device-width: 320px) and (max-device-width: 640px) and (orientation: landscape)"; 23 | $tablet: "only screen and (min-width: 569px) and (max-width: 980px)"; 24 | $desktop: "only screen and (min-width: 981px) and (max-width: 1200px)"; 25 | $desktop-xl: "only screen and (min-width: 1201px)"; 26 | 27 | :global { 28 | 29 | .dark_background{ 30 | background-color: $dark; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/styles/wrapper.scss: -------------------------------------------------------------------------------- 1 | .base{ 2 | margin-left: auto; 3 | margin-right: auto; 4 | height: 100%; 5 | } 6 | 7 | .main{ 8 | composes: base; 9 | position: relative; 10 | width: 95%; 11 | max-width: 900px; 12 | } 13 | 14 | .form{ 15 | composes: base; 16 | max-width: 500px; 17 | border-radius: 3px; 18 | padding: 1rem; 19 | 20 | &:not(last-of-type){ 21 | margin-bottom: 1.5rem; 22 | } 23 | } 24 | 25 | .form__white{ 26 | composes: form; 27 | background-color: white; 28 | } 29 | 30 | .tight{ 31 | composes: base; 32 | max-width: 750px; 33 | } 34 | 35 | .full{ 36 | max-width: 100%; 37 | } 38 | 39 | .flex{ 40 | composes: main; 41 | display: flex; 42 | justify-content: space-between; 43 | } 44 | -------------------------------------------------------------------------------- /app/styles/z-index.scss: -------------------------------------------------------------------------------- 1 | :global{ 2 | 3 | .alerts__container{ 4 | z-index: 1000; 5 | } 6 | 7 | .header__base{ 8 | z-index: 900; 9 | } 10 | 11 | .modal__base{ 12 | z-index: 875; 13 | } 14 | 15 | .page__element{ 16 | z-index: 1; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /images/hire_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramsaylanier/react-cssmodules-sass-boilerplate/73f8c414ae988cfadbf62ce1aff688472139fe51/images/hire_bg.png -------------------------------------------------------------------------------- /images/play_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramsaylanier/react-cssmodules-sass-boilerplate/73f8c414ae988cfadbf62ce1aff688472139fe51/images/play_bg.jpg -------------------------------------------------------------------------------- /images/work_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ramsaylanier/react-cssmodules-sass-boilerplate/73f8c414ae988cfadbf62ce1aff688472139fe51/images/work_bg.jpg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-express-boilerplate", 3 | "version": "0.1.0", 4 | "description": "A boilerplate for running a Webpack workflow in Node express", 5 | "main": "server.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/christianalfoni/webpack-express-boilerplate.git" 9 | }, 10 | "keywords": [ 11 | "express", 12 | "webpack", 13 | "node" 14 | ], 15 | "author": "Christian Alfoni", 16 | "license": "MIT", 17 | "bugs": { 18 | "url": "https://github.com/christianalfoni/webpack-express-boilerplate/issues" 19 | }, 20 | "homepage": "https://github.com/christianalfoni/webpack-express-boilerplate", 21 | "scripts": { 22 | "test": "", 23 | "start": "NODE_ENV=production node ./dist/server.js", 24 | "startdev": "NODE_ENV=dev babel-node --debug ./server.js", 25 | "startdevprod": "NODE_ENV=production babel-node --debug ./server.js", 26 | "build-server": "babel -d ./dist ./server.js ./webpack.config.js", 27 | "build": "rimraf dist && NODE_ENV=production webpack --config ./webpack.production.config.js --progress --profile --colors && npm run build-server", 28 | "eslint": "eslint .", 29 | "jscs": "jscs ." 30 | }, 31 | "dependencies": { 32 | "babel-polyfill": "^6.3.14", 33 | "browser-sync": "^2.11.0", 34 | "extract-text-webpack-plugin": "^0.8.2", 35 | "hapi": "^11.1.4", 36 | "history": "^1.17.0", 37 | "lodash": "^3.10.1", 38 | "mysql": "^2.10.0", 39 | "react": "^0.14.5", 40 | "react-css-modules": "^3.7.4", 41 | "react-dom": "^0.14.5", 42 | "react-router": "^2.0.0-rc4" 43 | }, 44 | "devDependencies": { 45 | "autoprefixer": "^6.0.3", 46 | "babel": "^6.3.25", 47 | "babel-cli": "^6.3.17", 48 | "babel-core": "^6.3.26", 49 | "babel-eslint": "^5.0.0-beta6", 50 | "babel-loader": "^6.2.0", 51 | "babel-plugin-react-transform": "^2.0.0-beta1", 52 | "babel-plugin-transform-decorators-legacy": "1.x.x", 53 | "babel-plugin-transform-react-display-name": "^6.3.13", 54 | "babel-plugin-transform-runtime": "6.x.x", 55 | "babel-polyfill": "6.x.x", 56 | "babel-preset-es2015": "^6.3.13", 57 | "babel-preset-react": "^6.3.13", 58 | "babel-preset-stage-0": "^6.3.13", 59 | "babel-relay-plugin": "^0.6.1", 60 | "babel-runtime": "^6.9.2", 61 | "browser-sync-webpack-plugin": "^1.0.1", 62 | "chai": "^3.2.0", 63 | "css-loader": "^0.19.0", 64 | "eslint": "^1.5.0", 65 | "eslint-plugin-react": "^3.4.2", 66 | "express": "^4.13.3", 67 | "extract-text-webpack-plugin": "^0.8.2", 68 | "gsap": "^1.18.2", 69 | "html-webpack-plugin": "^1.6.1", 70 | "jscs": "^2.1.1", 71 | "jsdom": "^6.5.1", 72 | "json-loader": "^0.5.3", 73 | "mocha": "^2.3.3", 74 | "mocha-jsdom": "^1.0.0", 75 | "node-sass": "^3.4.2", 76 | "null-loader": "^0.1.1", 77 | "postcss-loader": "^0.6.0", 78 | "react-addons-test-utils": "^0.14.3", 79 | "react-transform-catch-errors": "^1.0.0", 80 | "react-transform-hmr": "^1.0.0", 81 | "redbox-react": "^1.2.0", 82 | "rimraf": "^2.4.3", 83 | "sass-loader": "^3.1.2", 84 | "sinon": "^1.16.1", 85 | "sinon-chai": "^2.8.0", 86 | "stats-webpack-plugin": "^0.2.1", 87 | "style-loader": "^0.13.0", 88 | "webpack": "^1.12.9", 89 | "webpack-dev-middleware": "^1.2.0", 90 | "webpack-dev-server": "^1.14.0", 91 | "webpack-hot-middleware": "^2.2.0", 92 | "write-file-webpack-plugin": "^3.1.6" 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | import path from 'path'; 3 | import express from 'express'; 4 | import webpack from 'webpack'; 5 | import WebpackDevServer from 'webpack-dev-server'; 6 | import webpackMiddleware from 'webpack-dev-middleware'; 7 | import webpackHotMiddleware from 'webpack-hot-middleware'; 8 | import config from './webpack.config.js'; 9 | 10 | const isDeveloping = process.env.NODE_ENV !== 'production'; 11 | const APP_PORT = isDeveloping ? 3000 : process.env.PORT || 3000; 12 | 13 | let app = express(); 14 | 15 | if (isDeveloping) { 16 | 17 | const compiler = webpack(config); 18 | 19 | app = new WebpackDevServer(compiler, { 20 | hot: true, 21 | historyApiFallback: true, 22 | contentBase: 'src', 23 | publicPath: config.output.publicPath, 24 | stats: { 25 | colors: true, 26 | hash: false, 27 | timings: true, 28 | chunks: false, 29 | chunkModules: false, 30 | modules: false 31 | } 32 | }); 33 | 34 | app.use(webpackHotMiddleware(compiler)); 35 | 36 | } else { 37 | app.use(express.static('./dist')); 38 | app.get('*', function response(req, res, next) { 39 | res.sendFile(path.join(__dirname, '/index.html')); 40 | }); 41 | } 42 | 43 | app.listen(APP_PORT, () => { 44 | console.log(`App is now running on http://localhost:${APP_PORT}`); 45 | }); 46 | -------------------------------------------------------------------------------- /settings/dev.json: -------------------------------------------------------------------------------- 1 | { 2 | "ENV":"Dev", 3 | "wp_prefix": "wp_", 4 | "uploads": "http://wordpressexpress.dev/wp-content/uploads/", 5 | "database": { 6 | "name": "wpexpress_dev", 7 | "username": "root", 8 | "password": "", 9 | "host": "127.0.0.1" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /settings/prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "ENV":"Prod", 3 | "wp-prefix": "wp_", 4 | "database": { 5 | "name": "wpexpress_dev", 6 | "username": "root", 7 | "password": "", 8 | "host": "127.0.0.1" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var webpack = require('webpack'); 5 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 6 | 7 | const devServer = { 8 | contentBase: path.resolve(__dirname, './app'), 9 | outputPath: path.join(__dirname, './dist'), 10 | colors: true, 11 | quiet: false, 12 | noInfo: false, 13 | publicPath: '/', 14 | historyApiFallback: false, 15 | host: '127.0.0.1', 16 | port: 3000, 17 | hot: true 18 | }; 19 | 20 | module.exports = { 21 | devtool: 'eval-source-map', 22 | debug: true, 23 | devServer: devServer, 24 | entry: [ 25 | 'webpack/hot/dev-server', 26 | 'webpack-hot-middleware/client?reload=true', 27 | path.join(__dirname, 'app/main.js') 28 | ], 29 | output: { 30 | path: path.join(__dirname, '/dist/'), 31 | filename: '[name].js', 32 | publicPath: devServer.publicPath 33 | }, 34 | module: { 35 | loaders: [ 36 | { 37 | test: /\.js?$/, 38 | loader: 'babel', 39 | exclude: /node_modules|lib/, 40 | }, 41 | { 42 | test: /\.json?$/, 43 | loader: 'json' 44 | }, 45 | { 46 | test: /\.css$/, 47 | loader: 'style!css?modules&localIdentName=[name]---[local]---[hash:base64:5]' 48 | }, 49 | { 50 | test: /\.scss$/, 51 | loaders: [ 52 | 'style?sourceMap', 53 | 'css?modules&importLoaders=1&localIdentName=[path]___[name]__[local]', 54 | 'sass?sourceMap' 55 | ], 56 | exclude: /node_modules|lib/ 57 | }, 58 | ], 59 | }, 60 | plugins: [ 61 | new HtmlWebpackPlugin({ 62 | template: 'app/index.tpl.html', 63 | inject: 'body', 64 | filename: 'index.html' 65 | }), 66 | new webpack.optimize.OccurenceOrderPlugin(), 67 | new webpack.HotModuleReplacementPlugin(), 68 | new webpack.NoErrorsPlugin(), 69 | new webpack.DefinePlugin({ 70 | 'process.env.NODE_ENV': JSON.stringify('dev') 71 | }) 72 | ], 73 | node: { 74 | fs: 'empty' 75 | } 76 | }; 77 | -------------------------------------------------------------------------------- /webpack.production.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var webpack = require('webpack'); 5 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 6 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 7 | var StatsPlugin = require('stats-webpack-plugin'); 8 | 9 | module.exports = { 10 | entry: [ 11 | path.join(__dirname, 'app/main.js') 12 | ], 13 | output: { 14 | path: path.join(__dirname, '/dist/'), 15 | filename: '[name]-[hash].min.js' 16 | }, 17 | plugins: [ 18 | new ExtractTextPlugin('/app.min.css', { 19 | allChunks: true 20 | }), 21 | new HtmlWebpackPlugin({ 22 | template: 'app/index.tpl.html', 23 | inject: 'body', 24 | filename: 'index.html' 25 | }), 26 | new webpack.optimize.OccurenceOrderPlugin(), 27 | new webpack.optimize.UglifyJsPlugin({ 28 | compressor: { 29 | warnings: false, 30 | screw_ie8: true 31 | } 32 | }), 33 | new webpack.DefinePlugin({ 34 | 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV) 35 | }) 36 | ], 37 | module: { 38 | loaders: [ 39 | { 40 | test: /\.js?$/, 41 | loader: 'babel', 42 | exclude: /node_modules|lib/, 43 | }, 44 | { 45 | test: /\.json?$/, 46 | loader: 'json' 47 | }, 48 | { 49 | test: /\.css$/, 50 | loader: 'style!css?modules&localIdentName=[name]---[local]---[hash:base64:5]' 51 | }, 52 | { 53 | test: /\.scss$/, 54 | loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=1&localIdentName=[name]__[local]!sass'), 55 | exclude: /node_modules|lib/, 56 | }, 57 | ], 58 | } 59 | }; 60 | --------------------------------------------------------------------------------