mirror of
https://github.com/kremalicious/blog.git
synced 2024-12-22 17:23:50 +01:00
add basic styling
This commit is contained in:
parent
1cd59e0a84
commit
a293c93f5e
@ -9,8 +9,8 @@
|
||||
# Basics
|
||||
# --------------------
|
||||
|
||||
name: kremalicious
|
||||
description: 'Blog of designer & developer Matthias Kretschmann'
|
||||
title: kremalicious
|
||||
tagline: 'Blog of designer & developer Matthias Kretschmann'
|
||||
url: https://kremalicious.com
|
||||
author:
|
||||
name: Matthias Kretschmann
|
||||
@ -24,8 +24,4 @@ author:
|
||||
ether: "0x339dbC44d39bf1961E385ed0Ae88FC6069b87Ea1"
|
||||
|
||||
|
||||
# Urls
|
||||
# --------------------
|
||||
|
||||
media_url: "https://res.cloudinary.com/kremalicious"
|
||||
|
||||
typekitID: msu4qap
|
||||
|
@ -40,13 +40,13 @@ Just adding feature after feature out of dubious reasons (“Your competitors ha
|
||||
|
||||
After finding ezeep’s Buddha nature, the next step was to actually create the various elements of our experience and branding, ranging from typography, color, visual style, writing style, interaction models, user flows and more.
|
||||
|
||||
<img src="/media/buddha-colorscheme.png" alt="ezeep color scheme">
|
||||
![ezeep color scheme](../media/buddha-colorscheme.png)
|
||||
|
||||
While being human and friendly sounds like a no-brainer, in the corporate software world, it turns out it isn’t. ezeep’s vivid color scheme, subtle textures, graphics and icons are a visible manifestation of this, tackling the negative perception of printing for our users.
|
||||
|
||||
Creating this layer of delight on top of the functional layers is especially crucial in printing. Good design helps making users more forgiving about errors no matter who’s responsible for them. Printers – the little autistic beings they are – just tend to not work from time to time, and a failing device immediately reflects back on our service. If that’s the case the least we can do is make the experience beautiful.
|
||||
|
||||
<img src="/media/buddha-printer.png">
|
||||
![](../media/buddha-printer.png)
|
||||
|
||||
Paired with helpful and to-the-point copy, this creates a friendly and unifying atmosphere across the whole product, ranging from the web to native apps on Mac, Windows, iOS and Android.
|
||||
|
||||
|
10
gatsby-browser.js
Normal file
10
gatsby-browser.js
Normal file
@ -0,0 +1,10 @@
|
||||
exports.onInitialClientRender = () => {
|
||||
require('./src/styles/base.scss')
|
||||
}
|
||||
|
||||
exports.onClientEntry = () => {
|
||||
// IntersectionObserver polyfill for gatsby-image (Safari, IE)
|
||||
if (typeof window.IntersectionObserver === 'undefined') {
|
||||
require('intersection-observer')
|
||||
}
|
||||
}
|
@ -23,6 +23,13 @@ module.exports = {
|
||||
path: path.join(__dirname, 'content', 'media')
|
||||
}
|
||||
},
|
||||
{
|
||||
resolve: 'gatsby-source-filesystem',
|
||||
options: {
|
||||
name: 'posts',
|
||||
path: path.join(__dirname, 'content')
|
||||
}
|
||||
},
|
||||
{
|
||||
resolve: 'gatsby-transformer-remark',
|
||||
options: {
|
||||
@ -33,7 +40,8 @@ module.exports = {
|
||||
maxWidth: 940,
|
||||
linkImagesToOriginal: false,
|
||||
sizeByPixelDensity: true,
|
||||
showCaptions: true
|
||||
showCaptions: true,
|
||||
backgroundColor: '#e7eef4'
|
||||
}
|
||||
},
|
||||
'gatsby-remark-smartypants',
|
||||
@ -44,7 +52,7 @@ module.exports = {
|
||||
{
|
||||
resolve: 'gatsby-plugin-sass',
|
||||
options: {
|
||||
includePaths: [`${__dirname}/node_modules`]
|
||||
includePaths: [`${__dirname}/node_modules`, `${__dirname}/src/styles`]
|
||||
}
|
||||
},
|
||||
'gatsby-plugin-react-helmet',
|
||||
|
@ -39,6 +39,7 @@
|
||||
"gatsby-transformer-sharp": "^2.1.1-beta.5",
|
||||
"gatsby-transformer-yaml": "^2.1.1-beta.2",
|
||||
"graphql": "^0.13.2",
|
||||
"intersection-observer": "^0.5.0",
|
||||
"node-sass": "^4.9.2",
|
||||
"normalize-css": "^2.3.1",
|
||||
"normalize-opentype.css": "^0.2.4",
|
||||
|
53
src/components/Layout.jsx
Normal file
53
src/components/Layout.jsx
Normal file
@ -0,0 +1,53 @@
|
||||
import React, { Fragment } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { StaticQuery, graphql } from 'gatsby'
|
||||
import Head from './molecules/Head'
|
||||
import styles from './Layout.module.scss'
|
||||
|
||||
const Layout = ({ children, location }) => {
|
||||
return (
|
||||
<StaticQuery
|
||||
query={graphql`
|
||||
query {
|
||||
# the content/meta.yml file
|
||||
contentYaml {
|
||||
title
|
||||
tagline
|
||||
url
|
||||
author {
|
||||
name
|
||||
email
|
||||
uri
|
||||
twitter
|
||||
github
|
||||
facebook
|
||||
googleplus
|
||||
bitcoin
|
||||
ether
|
||||
}
|
||||
}
|
||||
}
|
||||
`}
|
||||
render={data => {
|
||||
const meta = data.contentYaml
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Head meta={meta} />
|
||||
|
||||
<main className={styles.screen} location={location}>
|
||||
{children}
|
||||
</main>
|
||||
</Fragment>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
Layout.propTypes = {
|
||||
children: PropTypes.any.isRequired,
|
||||
location: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default Layout
|
6
src/components/Layout.module.scss
Normal file
6
src/components/Layout.module.scss
Normal file
@ -0,0 +1,6 @@
|
||||
@import 'variables';
|
||||
|
||||
.screen {
|
||||
flex: 1;
|
||||
padding: $spacer;
|
||||
}
|
46
src/components/atoms/Typekit.jsx
Normal file
46
src/components/atoms/Typekit.jsx
Normal file
@ -0,0 +1,46 @@
|
||||
import React from 'react'
|
||||
import { StaticQuery, graphql } from 'gatsby'
|
||||
import Helmet from 'react-helmet'
|
||||
|
||||
const TypekitScript = typekitID => (
|
||||
<script>
|
||||
{`
|
||||
(function(d) {
|
||||
var config = {
|
||||
kitId: '${typekitID}',
|
||||
scriptTimeout: 3000,
|
||||
async: true
|
||||
},
|
||||
h=d.documentElement,t=setTimeout(function(){h.className=h.className.replace(/\bwf-loading\b/g,"")+" wf-inactive";},config.scriptTimeout),tk=d.createElement("script"),f=false,s=d.getElementsByTagName("script")[0],a;h.className+=" wf-loading";tk.src='https://use.typekit.net/'+config.kitId+'.js';tk.async=true;tk.onload=tk.onreadystatechange=function(){a=this.readyState;if(f||a&&a!="complete"&&a!="loaded")return;f=true;clearTimeout(t);try{Typekit.load(config)}catch(e){}};s.parentNode.insertBefore(tk,s)
|
||||
})(document);
|
||||
`}
|
||||
</script>
|
||||
)
|
||||
|
||||
const Typekit = () => (
|
||||
<StaticQuery
|
||||
query={graphql`
|
||||
query {
|
||||
contentYaml {
|
||||
typekitID
|
||||
}
|
||||
}
|
||||
`}
|
||||
render={data => {
|
||||
const { typekitID } = data.contentYaml
|
||||
|
||||
return (
|
||||
typekitID && (
|
||||
<Helmet>
|
||||
<link rel="dns-prefetch" href="https://use.typekit.net/" />
|
||||
<link rel="dns-prefetch" href="https://p.typekit.net/" />
|
||||
|
||||
{TypekitScript(typekitID)}
|
||||
</Helmet>
|
||||
)
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
export default Typekit
|
28
src/components/molecules/Head.jsx
Normal file
28
src/components/molecules/Head.jsx
Normal file
@ -0,0 +1,28 @@
|
||||
import React, { Fragment } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Helmet from 'react-helmet'
|
||||
import Typekit from '../atoms/Typekit'
|
||||
|
||||
const Head = ({ meta }) => {
|
||||
const { title, tagline } = meta
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Helmet
|
||||
defaultTitle={`${title.toLowerCase()} ¦ ${tagline.toLowerCase()}`}
|
||||
titleTemplate={`%s ¦ ${title.toLowerCase()}`}
|
||||
>
|
||||
<meta name="apple-mobile-web-app-title" content={title.toLowerCase()} />
|
||||
<meta name="theme-color" content="#e7eef4" />
|
||||
</Helmet>
|
||||
|
||||
<Typekit />
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
Head.propTypes = {
|
||||
meta: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
export default Head
|
@ -1,16 +1,17 @@
|
||||
import React, { Fragment } from 'react'
|
||||
import React from 'react'
|
||||
import Layout from '../components/Layout'
|
||||
|
||||
const NotFound = () => (
|
||||
<Fragment>
|
||||
<Layout location={location}>
|
||||
<div className="hal-9000" />
|
||||
|
||||
<p className="srverror-title">I am sorry Dave,</p>
|
||||
<p className="srverror-text">I am afraid I can NotFound do that.</p>
|
||||
<p className="srverror-text">I am afraid I can not do that.</p>
|
||||
|
||||
<a href="#" className="js-search-init">
|
||||
How about a nice search?
|
||||
</a>
|
||||
</Fragment>
|
||||
</Layout>
|
||||
)
|
||||
|
||||
export default NotFound
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Link, graphql } from 'gatsby'
|
||||
import Layout from '../components/Layout'
|
||||
|
||||
const IndexPage = ({ data }) => {
|
||||
const edges = data.allMarkdownRemark.edges
|
||||
@ -12,7 +13,11 @@ const IndexPage = ({ data }) => {
|
||||
</li>
|
||||
))
|
||||
|
||||
return <ul>{Posts}</ul>
|
||||
return (
|
||||
<Layout location={location}>
|
||||
<ul>{Posts}</ul>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
IndexPage.propTypes = {
|
||||
|
121
src/styles/base.scss
Normal file
121
src/styles/base.scss
Normal file
@ -0,0 +1,121 @@
|
||||
@import 'variables';
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: $font-size-root;
|
||||
background: $body-background-color;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: $font-family-base;
|
||||
font-weight: $font-weight-base;
|
||||
font-size: $font-size-base;
|
||||
line-height: $line-height;
|
||||
color: $font-color-base;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-feature-settings: 'liga', 'kern';
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
min-height: 100vh;
|
||||
background: $body-background-color;
|
||||
transition: background .6s $easing;
|
||||
|
||||
&.dark {
|
||||
background-color: $body-background-color--dark;
|
||||
color: $text-color--dark;
|
||||
}
|
||||
}
|
||||
|
||||
p,
|
||||
ul,
|
||||
ol {
|
||||
margin: 0 0 $spacer;
|
||||
}
|
||||
|
||||
// Headings
|
||||
/////////////////////////////////////
|
||||
|
||||
h1 {
|
||||
font-size: $font-size-h1;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: $font-size-h2;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: $font-size-h3;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: $font-size-h4;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: $font-size-h5;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: $font-size-h6;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: $font-family-headings;
|
||||
line-height: $line-height-headings;
|
||||
color: $color-headings;
|
||||
font-weight: $font-weight-headings;
|
||||
margin: 0 0 $spacer;
|
||||
letter-spacing: -.02em;
|
||||
|
||||
.dark & {
|
||||
color: $color-headings--dark;
|
||||
}
|
||||
}
|
||||
|
||||
// Links
|
||||
/////////////////////////////////////
|
||||
|
||||
a {
|
||||
color: $brand-cyan;
|
||||
text-decoration: none;
|
||||
transition: .2s ease-out;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: lighten($brand-cyan, 10%);
|
||||
transform: translate3d(0, -.1rem, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Media
|
||||
/////////////////////////////////////
|
||||
|
||||
img,
|
||||
video,
|
||||
svg {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#___gatsby {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
flex-direction: column;
|
||||
}
|
69
src/styles/variables.scss
Normal file
69
src/styles/variables.scss
Normal file
@ -0,0 +1,69 @@
|
||||
$imageMaxWidth: 940px;
|
||||
$easing: cubic-bezier(.75, 0, .08, 1);
|
||||
|
||||
// Colors
|
||||
/////////////////////////////////////
|
||||
|
||||
$brand-main: #015565;
|
||||
$brand-cyan: #43a699;
|
||||
$brand-main-light: #88bec8;
|
||||
$brand-light: #e7eef4;
|
||||
|
||||
$brand-grey: #6b7f88;
|
||||
$brand-grey-light: lighten($brand-grey, 15%);
|
||||
$brand-grey-dimmed: lighten($brand-grey, 50%);
|
||||
|
||||
// Backgrounds
|
||||
/////////////////////////////////////
|
||||
|
||||
$body-background-color: $brand-light;
|
||||
$body-background-color--dark: darken($brand-grey, 30%);
|
||||
|
||||
// Text Colors
|
||||
/////////////////////////////////////
|
||||
|
||||
$text-color: $brand-grey;
|
||||
$text-color-light: $brand-grey-light;
|
||||
|
||||
$text-color--dark: $brand-grey-light;
|
||||
$text-color-light--dark: $brand-grey;
|
||||
|
||||
// Typography
|
||||
/////////////////////////////////////
|
||||
|
||||
$font-size-root: 18px;
|
||||
|
||||
$font-size-base: 1rem;
|
||||
$font-size-large: 1.2rem;
|
||||
$font-size-small: .8rem;
|
||||
$font-size-mini: .7rem;
|
||||
|
||||
$font-size-h1: 2.5rem;
|
||||
$font-size-h2: 2rem;
|
||||
$font-size-h3: 1.75rem;
|
||||
$font-size-h4: $font-size-large;
|
||||
$font-size-h5: $font-size-base;
|
||||
$font-size-h6: $font-size-small;
|
||||
|
||||
$line-height: 1.5;
|
||||
$line-height-small: 1.1428571429;
|
||||
|
||||
$font-family-base: 'ff-tisa-sans-web-pro', 'Trebuchet MS', 'Helvetica Neue',
|
||||
Helvetica, Arial, sans-serif;
|
||||
$font-weight-base: 400;
|
||||
$font-color-base: $text-color;
|
||||
|
||||
$font-family-monospace: Menlo, Monaco, Consolas, 'Courier New', monospace;
|
||||
|
||||
$font-family-headings: 'brandon-grotesque', 'Avenir Next', 'Helvetica Neue',
|
||||
Helvetica, Arial, sans-serif;
|
||||
$font-weight-headings: 500;
|
||||
$line-height-headings: 1.1;
|
||||
|
||||
$color-headings: $brand-main;
|
||||
$color-headings--dark: $brand-main-light;
|
||||
|
||||
// Components spacing
|
||||
/////////////////////////////////////
|
||||
|
||||
$spacer: ($font-size-base * $line-height);
|
@ -2,25 +2,26 @@ import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import Helmet from 'react-helmet'
|
||||
import { graphql } from 'gatsby'
|
||||
import Image from '../components/Image'
|
||||
import Layout from '../components/Layout'
|
||||
import Image from '../components/atoms/Image'
|
||||
|
||||
const Post = ({ data }) => {
|
||||
const { markdownRemark: post } = data
|
||||
const { title, image } = post.frontmatter
|
||||
|
||||
return (
|
||||
<div className="blog-post-container">
|
||||
<Layout location={location}>
|
||||
<Helmet title={title} />
|
||||
|
||||
<div className="blog-post">
|
||||
<article className="blog-post">
|
||||
<h1 className="title">{title}</h1>
|
||||
<Image fluid={image.childImageSharp.fluid} alt={title} />
|
||||
{image && <Image fluid={image.childImageSharp.fluid} alt={title} />}
|
||||
<div
|
||||
className="blog-post-content"
|
||||
dangerouslySetInnerHTML={{ __html: post.html }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user