Move to CSS modules and Sass

This commit is contained in:
LordMathis 2018-05-04 19:34:25 +02:00
parent 93ba6939c1
commit 299ffcadbb
19 changed files with 3238 additions and 959 deletions

View File

@ -27,31 +27,32 @@
"jsonfile": "^4.0.0", "jsonfile": "^4.0.0",
"markdown-it": "^8.4.0", "markdown-it": "^8.4.0",
"moment": "^2.19.1", "moment": "^2.19.1",
"node-sass": "^4.5.3", "node-sass": "^4.9.0",
"react": "^15.0.1", "react": "^15.0.1",
"react-dom": "^15.0.1", "react-dom": "^15.0.1",
"react-redux": "^4.4.4",
"react-router-dom": "^4.1.1", "react-router-dom": "^4.1.1",
"remarkable": "^1.7.1" "remarkable": "^1.7.1"
}, },
"devDependencies": { "devDependencies": {
"babel-core": "^6.7.6", "babel-core": "^6.7.6",
"babel-jest": "*", "babel-jest": "*",
"babel-loader": "^6.2.4", "babel-loader": "^7.1.4",
"babel-plugin-transform-runtime": "^6.7.5", "babel-plugin-transform-runtime": "^6.7.5",
"babel-preset-es2015": "^6.6.0", "babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0", "babel-preset-react": "^6.5.0",
"babel-preset-react-hmre": "^1.1.1", "babel-preset-react-hmre": "^1.1.1",
"babel-preset-stage-0": "^6.5.0", "babel-preset-stage-0": "^6.5.0",
"babel-register": "^6.7.2", "babel-register": "^6.7.2",
"css-loader": "^0.28.4", "css-loader": "^0.28.11",
"css-modules-require-hook": "^4.0.6", "css-modules-require-hook": "^4.0.6",
"extract-text-webpack-plugin": "^2.1.2", "file-loader": "^1.1.11",
"sass-loader": "^6.0.6", "postcss-loader": "^2.1.4",
"style-loader": "^0.18.2", "sass-loader": "^7.0.1",
"style-loader": "^0.21.0",
"url-loader": "^0.5.9", "url-loader": "^0.5.9",
"webpack": "^2.5.1", "webpack": "^4.7.0",
"webpack-dev-middleware": "^1.10.2", "webpack-cli": "^2.1.2",
"webpack-dev-middleware": "^3.1.3",
"webpack-hot-middleware": "^2.18.0" "webpack-hot-middleware": "^2.18.0"
} }
} }

1
postcss.config.js Normal file
View File

@ -0,0 +1 @@
module.exports = {};

View File

@ -2,7 +2,6 @@ import React from 'react';
import {render} from 'react-dom'; import {render} from 'react-dom';
import {BrowserRouter as Router} from 'react-router-dom'; import {BrowserRouter as Router} from 'react-router-dom';
import {App} from './components'; import {App} from './components';
import './static/stylesheets/main.scss';
const AppClient = () => ( const AppClient = () => (
<Router> <Router>

View File

@ -1,4 +1,6 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import '../static/stylesheets/globals.scss';
import './About.scss';
export default class About extends Component { export default class About extends Component {
@ -13,6 +15,7 @@ export default class About extends Component {
return ( return (
<div className="content-wrapper"> <div className="content-wrapper">
<h1>About</h1>
<div className="content" dangerouslySetInnerHTML={{__html: this.props.about.body}}> <div className="content" dangerouslySetInnerHTML={{__html: this.props.about.body}}>
</div> </div>
</div> </div>

View File

@ -0,0 +1 @@
@import "../static/stylesheets/variables.scss";

View File

@ -1,4 +1,6 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import '../static/stylesheets/globals.scss';
import styles from './Blog.scss';
export default class Blog extends Component { export default class Blog extends Component {
@ -12,20 +14,20 @@ export default class Blog extends Component {
} }
let posts = this.props.posts.map((post) => let posts = this.props.posts.map((post) =>
<div className="post-list-item" key={post.title}> <div className={styles.postListItem} key={post.title}>
<div className="post-header"> <div className={styles.postHeader}>
<div className="post-title"> <div className={styles.postTitle}>
<h3><a href={post.link}>{post.title}</a></h3> <h3><a href={post.link}>{post.title}</a></h3>
</div> </div>
<div className="post-date"> <div className={styles.postDate}>
<h3>{post.published} <h3>{post.published}
</h3> </h3>
</div> </div>
</div> </div>
<div className="post-summary"> <div className={styles.postSummary}>
<p>{post.summary}</p> <p>{post.summary}</p>
</div> </div>
<div className="post-list-footer"> <div className={styles.postListFooter}>
<a href={post.link}>Read More</a> <a href={post.link}>Read More</a>
</div> </div>

38
src/components/Blog.scss Normal file
View File

@ -0,0 +1,38 @@
@import "../static/stylesheets/variables.scss";
.postTitle {
float: left;
h3 {
font-weight: normal
}
}
.postDate {
float: right;
h3 {
font-weight: normal
}
}
.postHeader {
background-color: #F5F5F5;
overflow: hidden;
padding: 0 5px 0 5px;
}
.postSummary {
clear: both;
padding: 0 5px 0 5px;
}
.postListItem {
margin-top: 20px;
border-style: solid;
border-width: 0 0 3px 0;
border-color: $black;
}
.postListFooter {
text-align: center;
padding-bottom: 5px;
}

View File

@ -1,6 +1,8 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import config from '../utils/config.json'; import config from '../utils/config.json';
import '../static/stylesheets/globals.scss';
import styles from './Home.scss';
export default class Home extends Component { export default class Home extends Component {
@ -27,15 +29,15 @@ export default class Home extends Component {
); );
return ( return (
<div id="cover-page" className={this.props.location.pathname === '/' ? 'cover-page-full' : 'cover-page-collapsed'}> <div id={styles.coverPage} className={this.props.location.pathname === '/' ? styles.coverPageFull : styles.coverPageCollapsed}>
<div id="cover-page-content"> <div id={styles.coverPageContent}>
<div> <div>
<h1 id="cover-page-name"><Link to="/">{ config.name }</Link></h1> <h1 id={styles.coverPageName}><Link to="/">{ config.name }</Link></h1>
</div> </div>
<div className="social"> <div className={styles.social}>
{socialLinks} {socialLinks}
</div> </div>
<div className="menu-links"> <div className={styles.menuLinks}>
<ul> <ul>
<li> <li>
<Link to="/blog"> <Link to="/blog">

75
src/components/Home.scss Normal file
View File

@ -0,0 +1,75 @@
@import "../static/stylesheets/variables.scss";
#coverPage {
background: linear-gradient(140deg,rgba(68, 68, 68, 0.6) 20%, rgba(0, 0, 0, 0.9)), url(../static/images/background-cover.jpg) no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
background-size: cover;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
position: fixed;
top: 0;
left: 0;
color: $white;
transition-property: width;
transition-duration: 0.75s;
-webkit-transition-property: width;
-webkit-transition-duration: 0.75s;
}
#coverPage.coverPageFull{
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
#coverPage.coverPageCollapsed {
float: left;
width: 320px;
height: 100%;
@media screen and (max-width: $break-medium) {
width: 100%;
float: none;
}
@media screen and (min-width: $break-large) {
width: 500px;
float: none;
}
}
#coverPageName {
font-size: 5em;
}
#coverPageName a, #coverPageName a:hover {
color: $white;
text-decoration: none;
}
.social {
text-align: center;
a {
color: $white;
display: inline-block;
margin: 10px;
}
}
.menuLinks ul{
list-style: none;
margin-left: 0;
padding: 10px;
li {
margin: 5px;
a {
color: $white;
text-decoration: none;
font-size: 1.4em;
}
}
}

View File

@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import '../static/stylesheets/globals.scss';
export const NotFoundPage = (props) => { export const NotFoundPage = (props) => {
if (props.location.pathname === '/') { if (props.location.pathname === '/') {

View File

@ -1,4 +1,6 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import '../static/stylesheets/globals.scss';
import './Post.scss';
export default class Post extends Component { export default class Post extends Component {
render() { render() {

12
src/components/Post.scss Normal file
View File

@ -0,0 +1,12 @@
@import "../static/stylesheets/variables.scss";
.post-content {
clear: both;
}
.post-date {
float: right;
h3 {
font-weight: normal
}
}

View File

@ -3,8 +3,15 @@ require('babel-register');
var app = new (require('express'))(); var app = new (require('express'))();
var port = process.env.PORT || 3000; var port = process.env.PORT || 3000;
const sass = require('node-sass');
require('css-modules-require-hook')({ require('css-modules-require-hook')({
generateScopedName: '[name]__[local]___[hash:base64:5]' generateScopedName: '[name]__[local]___[hash:base64:5]',
extensions: ['.scss', '.css'],
preprocessCss: (data, filename) => sass.renderSync({
data,
file: filename,
}).css
}); });
var fs = require('fs'); var fs = require('fs');

View File

@ -0,0 +1,40 @@
@import "./variables.scss";
:global(.content-wrapper) {
margin-left: 320px;
overflow: auto;
padding: 20px;
h1 {
text-align: center;
}
a {
color: $blue;
}
@media screen and (max-width: $break-medium) {
width: 100%;
float: none;
}
@media screen and (min-width: $break-large) {
margin-left: 500px;
}
}
:global(body) {
font-family: $font-paragraph;
color: $black;
margin: 0;
}
@for $i from 1 through 6 {
:global(h#{$i}) {
font-family: $font-header;
}
}
:global(.content) {
box-sizing: border-box;
margin: 0 auto;
@media screen and (min-width: $break-large) {
width: 90%;
}
}

View File

@ -1,164 +0,0 @@
$font-header: 'Concert One', cursive;
$font-paragraph: 'Open Sans', sans-serif;
$white: #fdfdfd;
$black: #2f2f2f;
$blue: #428bca;
$break-medium: 768px;
$break-large: 1200px;
#cover-page {
background: linear-gradient(140deg,rgba(68, 68, 68, 0.6) 20%, rgba(0, 0, 0, 0.9)), url(../images/background-cover.jpg) no-repeat center center fixed;
-webkit-background-size: cover;
-moz-background-size: cover;
background-size: cover;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
position: fixed;
top: 0;
left: 0;
color: $white;
transition-property: width;
transition-duration: 0.75s;
-webkit-transition-property: width;
-webkit-transition-duration: 0.75s;
}
#cover-page.cover-page-full{
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
#cover-page.cover-page-collapsed {
float: left;
width: 320px;
height: 100%;
@media screen and (max-width: $break-medium) {
width: 100%;
float: none;
}
@media screen and (min-width: $break-large) {
width: 500px;
float: none;
}
}
body {
font-family: $font-paragraph;
color: $black;
margin: 0;
}
@for $i from 1 through 6 {
h#{$i} {
font-family: $font-header;
}
}
#cover-page-name {
font-size: 5em;
}
#cover-page-name a, #cover-page-name a:hover {
color: $white;
text-decoration: none;
}
.content-wrapper {
margin-left: 320px;
overflow: auto;
padding: 20px;
h1 {
text-align: center;
}
a {
color: $blue;
}
@media screen and (max-width: $break-medium) {
width: 100%;
float: none;
}
@media screen and (min-width: $break-large) {
margin-left: 500px;
}
}
.social {
text-align: center;
a {
color: $white;
display: inline-block;
margin: 10px;
}
}
.menu-links ul{
list-style: none;
margin-left: 0;
padding: 10px;
li {
margin: 5px;
a {
color: $white;
text-decoration: none;
font-size: 1.4em;
}
}
}
.post-title {
float: left;
h3 {
font-weight: normal
}
}
.post-date {
float: right;
h3 {
font-weight: normal
}
}
.post-header {
background-color: #F5F5F5;
overflow: hidden;
padding: 0 5px 0 5px;
}
.post-content {
clear: both;
}
.post-summary, .post-content{
clear: both;
}
.post-summary {
padding: 0 5px 0 5px;
}
.post-list-item {
margin-top: 20px;
border-style: solid;
border-width: 0 0 3px 0;
border-color: $black;
}
.post-list-footer {
text-align: center;
padding-bottom: 5px;
}
.content {
box-sizing: border-box;
margin: 0 auto;
@media screen and (min-width: $break-large) {
width: 90%;
}
}

View File

@ -0,0 +1,7 @@
$font-header: 'Concert One', cursive;
$font-paragraph: 'Open Sans', sans-serif;
$white: #fdfdfd;
$black: #2f2f2f;
$blue: #428bca;
$break-medium: 768px;
$break-large: 1200px;

View File

@ -25,31 +25,27 @@ const config = {
exclude: '/node_modules/' exclude: '/node_modules/'
}, },
{ {
test: /\.css$/, test: /\.scss$/,
use: [ use: [
'style-loader', {
loader: "style-loader"
},
{ {
loader: 'css-loader', loader: 'css-loader',
options: { options: {
modules: true, modules: true,
importLoaders: 1, importLoaders: 2,
localIdentName: '[name]__[local]___[hash:base64:5]' localIdentName: '[name]__[local]___[hash:base64:5]'
} }
}, },
{ {
loader: 'postcss-loader' loader: "postcss-loader"
},
{
loader: "sass-loader"
} }
] ]
}, },
{test: /\.scss$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}]
},
{ {
test: /\.(png|jpg)$/, test: /\.(png|jpg)$/,
exclude: /node_modules/, exclude: /node_modules/,

View File

@ -24,7 +24,7 @@ const config = {
exclude: '/node_modules/' exclude: '/node_modules/'
}, },
{ {
test: /\.css$/, test: /\.scss$/,
use: [ use: [
'style-loader', 'style-loader',
{ {
@ -35,20 +35,9 @@ const config = {
localIdentName: '[name]__[local]___[hash:base64:5]' localIdentName: '[name]__[local]___[hash:base64:5]'
} }
}, },
{ 'sass-loader'
loader: 'postcss-loader'
}
] ]
}, },
{test: /\.scss$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}]
},
{ {
test: /\.(png|jpg)$/, test: /\.(png|jpg)$/,
exclude: /node_modules/, exclude: /node_modules/,

3761
yarn.lock

File diff suppressed because it is too large Load Diff