Merge pull request #19 from Jinksi/0.3.0

0.3.0
This commit is contained in:
Eric Jinks 2018-06-01 15:52:35 +10:00 committed by GitHub
commit 7ed482a204
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 533 additions and 660 deletions

View file

@ -1,3 +1,14 @@
## 0.3.0 - 2018-06-01
* General design updates
* Improved default logo / favicon
* Improved default card-og.png
* Improved contact page layout
* Update <BackgroundImage />
* Change normalize.css to modern-normalize
* Add react-feather icons
* Remove AOS
## 0.2.9 - 2018-05-30
* IE11 support updates

View file

@ -1,4 +1,4 @@
# 🌶 Netlify CMS + React Starter
# Netlify CMS + React Starter
[![Standard - JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg?style=flat-square)](http://standardjs.com/)
[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
@ -18,18 +18,18 @@ I aim to include commonly used components and best-practices e.g. forms, setting
[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/Jinksi/netlify-cms-react-starter)
1. Hit the **Deploy to Netlify** button. This will:
1. Hit the **Deploy to Netlify** button. This will:
* Clone the repo into your Github account
* Create you a new project on Netlify, build & deploy
1. Once your Netlify project has been created, change a couple of settings:
1. Once your Netlify project has been created, change a couple of settings:
* Enable **Identity**
* Change **Registration Preferences** to **Invite Only**
* Enable **Git Gateway**
1. Invite users (probably yourself) to enable admin access
1. Invite users (probably yourself) to enable admin access
* Open the **Identity** tab and hit **Invite Users**
@ -39,21 +39,21 @@ The CMS lives at [\_\_YOUR_SITE_NAME\_\_.netlify.com/admin](https://__YOUR_SITE_
## Developing
1. Clone your repo to your local machine
1. Clone your repo to your local machine
1. Install dependencies
1. Install dependencies
`yarn` or `npm install`
1. Run the development server
1. Run the development server
`yarn start` or `npm run start`
If you are adding or editing content locally in the CMS, a couple of things to note:
1. Changes will be pushed to the remote repo.
1. Changes will be pushed to the remote repo.
1. You will be prompted to enter your site's url, this is necessary for Netlify Identity to manage user login. This is stored in `localStorage`, so you might have to empty your browser cache if you are switching projects but remaining on `localhost:3000`.
1. You will be prompted to enter your site's url, this is necessary for Netlify Identity to manage user login. This is stored in `localStorage`, so you might have to empty your browser cache if you are switching projects but remaining on `localhost:3000`.
## Editing CMS fields

View file

@ -4,8 +4,9 @@ import '../src/globalStyles.css'
import data from '../src/data.json'
import Home from '../src/views/Home'
import About from '../src/views/About'
import SinglePost from '../src/views/SinglePost'
import Contact from '../src/views/Contact'
import Blog from '../src/views/Blog'
import SinglePost from '../src/views/SinglePost'
console.log('React version', React.version)
@ -17,7 +18,10 @@ CMS.registerPreviewStyle('/admin/cms.bundle.css')
const getDocument = (collection, name) =>
data[collection] && data[collection].filter(page => page.name === name)[0]
const getDocuments = (collection, name) => data[collection]
const globalSettings = getDocument('settings', 'global')
const posts = getDocuments('posts')
// Preview Templates
CMS.registerPreviewTemplate('home-page', ({ entry }) => (
@ -29,6 +33,9 @@ CMS.registerPreviewTemplate('about-page', ({ entry }) => (
CMS.registerPreviewTemplate('contact-page', ({ entry }) => (
<Contact page={entry.toJS().data} siteTitle={globalSettings.siteTitle} />
))
CMS.registerPreviewTemplate('blog-page', ({ entry }) => (
<Blog page={entry.toJS().data} posts={posts} />
))
CMS.registerPreviewTemplate('posts', ({ entry }) => (
<SinglePost singlePost={entry.toJS().data} />
))

View file

@ -1,9 +1,8 @@
---
title: About page title
subtitle: <About />
featuredImage: /images/uploads/tim-marshall-155597.jpg
section1: |-
## Hello World!
## Lorem Ipsum
Netlify CMS works with both `.md` and `.json`.
@ -15,10 +14,9 @@ section1: |-
<iframe width="560" height="315" src="https://www.youtube.com/embed/Js00yn142ic" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
section2: >-
section2: |-
## This is a Container component
A sem vel nec sodales mi vivamus senectus sed potenti a parturient nascetur
tincidunt nisi pulvinar rhoncus a. Risus imperdiet taciti suspendisse facilisi
a per metus cubilia varius a nostra adipiscing amet ultrices quisque ac mi a.
@ -28,9 +26,7 @@ section2: >-
bibendum duis netus a consectetur dui magnis ac aliquet sem posuere tincidunt
vestibulum.
The image below will have a `srcset` attribute generated:
![Tim Marshall](/images/uploads/tim-marshall-155597.jpg)
---

4
content/pages/blog.md Normal file
View file

@ -0,0 +1,4 @@
---
title: Blog
featuredImage: /images/uploads/ng-32703.jpg
---

View file

@ -1,13 +1,18 @@
---
title: Contact
subtitle: <Contact />
title: Contact us
subtitle: ''
featuredImage: '/images/uploads/mark-chang-74-3.jpg'
address: 404 James St, Burleigh Heads QLD 4220
phone: 0987 123 456
email: example@example.com
---
# Example contact form
This form is setup to use Netlify's form handling:
- the form action is set to the current absolute url: `action: '/contact/'`
- a name attribute is sent with the form's data `'form-name': 'Contact'`
- netlify data attributes are added to the form `data-netlify data-netlify-honeypot`
* the form action is set to the current absolute url: `action: '/contact/'`
* a name attribute is sent with the form's data `'form-name': 'Contact'`
* netlify data attributes are added to the form `data-netlify data-netlify-honeypot`
Find out more in the [Netlify Docs](https://www.netlify.com/docs/form-handling/).

View file

@ -1,13 +1,10 @@
---
title: Hello World!
subtitle: <Home />
subtitle: This is the home page subtitle
featuredImage: '/images/uploads/isabella juskova.jpg'
---
# 🌶 Netlify CMS + React Starter
[![Standard - JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](http://standardjs.com/)
[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
[![dependencies](https://david-dm.org/jinksi/netlify-cms-react-starter.svg)](https://david-dm.org/jinksi/netlify-cms-react-starter)
# Netlify CMS + React Starter
A starter project for creating lightning-fast, offline-first websites with [Netlify CMS](https://netlifycms.org) and React.
@ -17,50 +14,6 @@ A starter project for creating lightning-fast, offline-first websites with [Netl
* **[React Snapshot](https://github.com/geelen/react-snapshot)** for pre-rendering to static html so it works without Javascript ⭐️
* **[Netlify CMS](https://github.com/netlify/netlify-cms)** for content management
I aim to include commonly used components and best-practices e.g. forms, settings, <head> tags, lazy-loading images, etc.
## Get going
[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/Jinksi/netlify-cms-react-starter)
1. Hit the **Deploy to Netlify** button. This will:
* Clone the repo into your Github account
* Create you a new project on Netlify, build & deploy
1. Once your Netlify project has been created, change a couple of settings:
* Enable **Identity**
* Change **Registration Preferences** to **Invite Only**
* Enable **Git Gateway**
1. Invite users (probably yourself) to enable admin access
* Open the **Identity** tab and hit **Invite Users**
## Developing
1. Clone your repo to your local machine
1. Install dependencies
`yarn` or `npm install`
1. Run the development server
`yarn start` or `npm run start`
If you are adding or editing content locally in the CMS, a couple of things to note:
* Changes will be pushed to the remote repo.
* You will be prompted to enter your site's url, this is necessary for Netlify Identity to manage user login. This is stored in `localStorage`, so you might have to empty your browser cache if you are switching projects but remaining on `localhost:3000`.
## Editing CMS fields
The Netlify CMS configuration is located in `public/admin/config.yml`. This is where you will configure the pages, fields, posts and settings that are editable by the CMS.
Find out more in the [Netlify CMS Docs](https://www.netlifycms.org/docs/#configuration).
## See also
[Netlify CMS Docs](https://www.netlifycms.org/docs/)

View file

@ -1,4 +0,0 @@
---
title: Fluff
---

View file

@ -0,0 +1,3 @@
---
title: Updates
---

View file

@ -1,8 +1,11 @@
---
title: Testing 1.8.2
title: Post Three
status: Published
date: '2018-05-25'
postFeaturedImage: /images/uploads/isabella juskova.jpg
excerpt: Test
excerpt: This is placeholder text that our web designers put here to make sure words appear properly on your website. This text is going to be replaced once the website is completed. You are currently reading text that is written in English, not any other language.
---
Test
This is placeholder text that our web designers put here to make sure words appear properly on your website. This text is going to be replaced once the website is completed. You are currently reading text that is written in English, not any other language.
Be careful not to waste too much time reading placeholder text! This text isnt going to remain here because it doesn't pertain to the website. This paragraph has been copied from a program that automatically generates paragraphs like this. It is useful for web designers to use placeholder text so they can easily see what different fonts look like on a realistic paragraph.

View file

@ -2,7 +2,7 @@
title: Post Two
status: Published
categories:
- category: Fluff
- category: Updates
date: '2018-03-28'
postFeaturedImage: /images/uploads/vyouw5byhlc.jpeg
excerpt: This is an excerpt of Post Two

View file

@ -31,17 +31,17 @@
},
"dependencies": {
"@researchgate/react-intersection-observer": "^0.7.0",
"aos": "^2.2.0",
"core-js": "^2.5.3",
"date-fns": "^1.29.0",
"dom-form-serializer": "^1.0.7",
"intersection-observer": "^0.5.0",
"lodash": "^4.17.10",
"modern-normalize": "^0.4.0",
"moveto": "^1.7.1",
"netlify-identity-widget": "^1.2.0",
"normalize.css": "^8.0.0",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-feather": "^1.1.0",
"react-helmet": "^5.1.3",
"react-markdown": "3",
"react-router-dom": "^4.1.1",

View file

@ -53,7 +53,7 @@
/* Custom logo */
/* .nc-githubAuthenticationPage-logo {
.nc-githubAuthenticationPage-logo {
background-image: url(/images/logo.svg);
background-position: center;
background-repeat: no-repeat;
@ -79,4 +79,4 @@
transform: translate(-50%, -50%);
width: auto;
text-indent: 0;
} */
}

View file

@ -14,30 +14,42 @@ collections: # A list of collections the CMS should be able to edit
editor:
preview: true
files:
- file: "content/pages/home.md"
label: "Home Page"
name: "home-page"
- file: "content/pages/contact.md"
label: "Contact Page"
name: "contact-page"
fields:
- {label: Title, name: title, widget: string}
- {label: Subtitle, name: subtitle, widget: string}
- {label: Subtitle, name: subtitle, widget: markdown}
- {label: Featured Image, name: featuredImage, widget: image}
- {label: Body, name: body, widget: markdown}
- {label: Address, name: address, widget: text}
- {label: Phone, name: phone, widget: string}
- {label: Email Address, name: email, widget: string}
- file: "content/pages/blog.md"
label: "Blog Page"
name: "blog-page"
fields:
- {label: Title, name: title, widget: string}
- {label: Subtitle, name: subtitle, widget: markdown}
- {label: Featured Image, name: featuredImage, widget: image}
- file: "content/pages/about.md"
label: "About Page"
name: "about-page"
fields:
- {label: Title, name: title, widget: string}
- {label: Subtitle, name: subtitle, widget: string}
- {label: Subtitle, name: subtitle, widget: markdown}
- {label: Featured Image, name: featuredImage, widget: image}
- {label: Section 1, name: section1, widget: markdown}
- {label: Section 2, name: section2, widget: markdown}
- file: "content/pages/contact.md"
label: "Contact Page"
name: "contact-page"
- file: "content/pages/home.md"
label: "Home Page"
name: "home-page"
fields:
- {label: Title, name: title, widget: string}
- {label: Subtitle, name: subtitle, widget: string}
- {label: Subtitle, name: subtitle, widget: markdown}
- {label: Body, name: body, widget: markdown}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View file

@ -1 +1,6 @@
<svg fill="#FF3D3D" width="100pt" height="100pt" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><path d="M79 34.699c-.3.398-.898.602-1.7.602-1 0-2.3-.301-3.698-.801-1.5-.602-3.899-1.899-4.301-3.102L69 31.5c-2.3.8-4.3 2.5-5.898 4.398C60.703 38.698 59 42 58.3 45.797c-3.2 17.3-17.301 33.602-38.602 37.8-2.102.399-3.7 1.7-3.7 3.301 0 1.602 1.7 2.899 4.102 3C44.203 91 68.101 77.2 79.402 53.2c2.602-5.3 2.602-11.3.899-15.602-.2-.996-.7-1.996-1.301-2.898zM61.699 53.398c-5.8 14.699-18 25.898-32.898 30.5-.2.102-.398 0-.5-.102 0-.101.102-.3.3-.398 14.5-5.2 25.603-16.699 30.5-30.898.302-1 1.2-1.7 1.9-1.5.8.3 1.1 1.398.698 2.398z"/><path d="M83.801 10.801c-.102-.602-.602-.898-1.2-.7-2.1.602-2.898 2.5-3.3 4.4-.5 2.6-.7 5.198-1.398 7.8-.399 1.5-.899 2.898-1.602 4.3-.3.7-.7 1.4-1.2 2-.898 1.4-2.198 1.7-3.698 2.102-.301.102-1.399.399-1.399.399-.199.699 1.399 2 3.801 2.8 2.3.9 4.398 1 4.7.301 0 0-1.2-1.5-1.9-2.5a1.358 1.358 0 0 1 0-1.699c3.102-4.101 3.5-9.5 4.4-14.398.3-1.5.398-3.398 2.198-3.898.399-.008.696-.508.598-.906z"/></svg>
<svg width="100pt" height="100pt" version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<g fill-rule="evenodd">
<path d="m55.441 1.5547 33.68 19.172c3.625 2.0742 5.6992 5.6992 5.6992 9.8438v38.859c0 4.1445-2.0742 7.7734-5.6992 9.8438l-33.68 19.172c-3.625 2.0742-7.7734 2.0742-11.398 0l-33.16-19.172c-3.625-2.0742-5.6992-5.6992-5.6992-9.8438v-38.859c0-4.1445 2.0742-7.7734 5.6992-9.8438l33.16-19.172c3.625-2.0742 7.7734-2.0742 11.398 0zm-2.0742 8.8086 29.016 16.582c2.5898 1.5547 3.625 3.625 3.625 6.2188v33.68c0 2.5898-1.0352 4.6641-3.625 6.2188l-29.016 16.582c-2.0742 1.0352-4.6641 1.0352-6.7344 0l-29.016-16.582c-2.5898-1.5547-3.625-3.625-3.625-6.2188v-33.68c0-2.5898 1.0352-4.6641 3.625-6.2188l29.016-16.582c2.0742-1.5547 4.6641-1.5547 6.7344 0z"/>
<path d="m49.742 16.582 29.016 16.578v33.68l-29.016 16.578-29.016-16.578v-33.68z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1 KiB

After

Width:  |  Height:  |  Size: 872 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 KiB

View file

@ -31,16 +31,16 @@
-->
<script src="https://identity-js.netlify.com/v1/netlify-identity-widget.js"></script>
<script>
// check for netlifyIdentity, redirect to admin if user is logging in
if (window.localStorage && window.netlifyIdentity) {
netlifyIdentity.on('init', function (user) {
if (!user) {
netlifyIdentity.on('login', function () {
document.location.href = '/admin/'
})
}
})
}
</script>
// check for netlifyIdentity, redirect to admin if user is logging in
if (window.localStorage && window.netlifyIdentity) {
netlifyIdentity.on('init', function(user) {
if (!user) {
netlifyIdentity.on('login', function() {
document.location.href = '/admin/'
})
}
})
}
</script>
</body>
</html>

View file

@ -15,7 +15,6 @@ import Nav from './components/Nav'
import Footer from './components/Footer'
import GithubCorner from './components/GithubCorner'
import ServiceWorkerNotifications from './components/ServiceWorkerNotifications'
import AOS from './components/AOS'
import data from './data.json'
import { slugify } from './util/url'
import { documentHasTerm, getCollectionTerms } from './util/collection'
@ -52,7 +51,6 @@ class App extends Component {
return (
<Router>
<div className='React-Wrap'>
<AOS options={{ duration: 250 }} />
<ScrollToTop />
<ServiceWorkerNotifications reloadOnUpdate />
<GithubCorner url='https://github.com/Jinksi/netlify-cms-react-starter' />
@ -111,6 +109,7 @@ class App extends Component {
exact
render={props => (
<Blog
page={this.getDocument('pages', 'blog')}
posts={posts}
postCategories={postCategories}
{...props}
@ -128,6 +127,7 @@ class App extends Component {
if (!categoryPosts.length) return <NoMatch siteUrl={siteUrl} />
return (
<Blog
page={this.getDocument('pages', 'blog')}
posts={categoryPosts}
postCategories={postCategories}
showFeatured={false}
@ -145,8 +145,8 @@ class App extends Component {
item => slugify(item.title) === slug
)
const singlePost = posts[singlePostID]
const nextPost = posts[singlePostID + 1]
const prevPost = posts[singlePostID - 1]
const nextPost = posts[singlePostID - 1]
const prevPost = posts[singlePostID + 1]
if (!singlePost) return <NoMatch siteUrl={siteUrl} />
return (
<SinglePost

View file

@ -1,31 +0,0 @@
import React from 'react'
import AOS from 'aos'
import Helmet from 'react-helmet'
import 'aos/dist/aos.css'
export default ({ options }) => {
// See more: https://github.com/michalsnik/aos
const defaultOptions = {
offset: 300,
duration: 300,
easing: 'ease-out-sine',
delay: 0,
once: true
}
AOS.init({ ...defaultOptions, ...options })
return (
<Helmet>
<noscript>{`
<style>
/* override AOS css if no JS */
[data-aos] {
opacity: 1 !important;
transform: translate(0) scale(1) !important;
}
</style>
`}</noscript>
</Helmet>
)
}

View file

@ -5,7 +5,8 @@
bottom: 0;
right: 0;
background-position: center;
transition: opacity 0.5s ease;
transform: translate3d(0, 0, 0);
transition: filter 0.3s ease-in-out;
overflow: hidden;
}

View file

@ -54,8 +54,22 @@ export default class BackgroundImage extends React.Component {
}
render () {
let { className, contain, opacity, lazy } = this.props
let { className, contain, opacity, lazy, imageSize } = this.props
let { loaded, src } = this.state
if (!lazy) {
return (
<div
className={`BackgroundImage absolute ${className}`}
style={{
backgroundImage: `url(${getImageSrc(this.props.src, imageSize)})`,
backgroundSize: contain ? 'contain' : 'cover',
opacity: opacity
}}
/>
)
}
if (loaded) className += ' BackgroundImage-lazy-loaded'
if (lazy) className += ' BackgroundImage-lazy'
const options = {
@ -68,7 +82,6 @@ export default class BackgroundImage extends React.Component {
<Observer {...options}>
<div
className={`BackgroundImage absolute ${className}`}
src={src}
style={{
backgroundImage: `url(${src})`,
backgroundSize: contain ? 'contain' : 'cover',

View file

@ -8,7 +8,7 @@
}
.EnquiryForm > * + * {
margin-top: 1.5rem;
margin-top: 2rem;
}
.EnquiryForm--Label {
@ -21,21 +21,19 @@
.EnquiryForm--Input {
font-family: inherit;
font-weight: 400;
flex-grow: 1;
box-sizing: border-box;
display: block;
margin: 0;
border: none;
border-bottom: 1px solid #bababa;
padding: 0.75rem 0.5rem;
line-height: 1;
border: 1px solid #bababa;
padding: 1.5rem 2rem;
border-radius: var(--borderRadius);
line-height: 1.25em;
transition: border-color 0.2s;
resize: none;
}
.EnquiryForm--Select {
border-radius: 0;
background: none;
appearance: none;
}
@ -43,7 +41,7 @@
.EnquiryForm--Label.has-arrow:after {
content: '';
position: absolute;
right: 3px;
right: 2.5rem;
top: 50%;
border-right: 1px solid;
border-bottom: 1px solid;

View file

@ -1,14 +1,4 @@
.Footer {
background: var(--primary);
color: white;
}
.Footer--Lower {
background: var(--primary);
padding: 1rem 0;
font-weight: 100;
}
.Footer--Lower a {
color: inherit;
padding: 3rem 0;
background: var(--lightGrey);
}

View file

@ -4,10 +4,8 @@ import './Footer.css'
export default ({ globalSettings, socialSettings, navLinks }) => (
<footer className='Footer'>
<div className='Footer--Lower'>
<div className='container taCenter'>
<span>© 2017 All rights reserved.</span>
</div>
<div className='container taCenter'>
<span>© 2017 All rights reserved.</span>
</div>
</footer>
)

View file

@ -7,8 +7,10 @@
.GithubCorner svg {
color: #fff;
border: 0;
max-width: 12.5vmin;
max-height: 12.5vmin;
width: 12vmin;
height: 12vmin;
max-width: 6rem;
max-height: 6rem;
}
.GithubCorner .octo-arm {

View file

@ -1,9 +1,10 @@
.Logo {
display: block;
display: flex;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
height: 2.5rem;
width: 2.5rem;
margin-right: 1rem;
align-items: center;
justify-content: center;
}

View file

@ -7,4 +7,10 @@
.Nav--Container {
display: flex;
align-items: center;
height: 6rem;
}
.Nav .Logo {
margin-right: 3rem;
}

View file

@ -1,14 +1,18 @@
.NavLink {
padding: 0.5rem 1rem;
display: block;
font-weight: 400;
font-weight: 500;
transition: color 0.2s, border-bottom-color 0.2s;
color: inherit;
text-decoration: none;
border-bottom: 1px solid;
border-bottom: 2px solid;
border-bottom-color: transparent;
}
.NavLink + .NavLink {
margin-left: 1rem;
}
.NavLink:hover,
.NavLink.active,
.NavLink:focus {

View file

@ -1,13 +1,19 @@
.PageHeader {
line-height: 1em;
color: var(--primary);
background: var(--primary);
background-color: var(--darkGrey);
color: white;
padding: 15rem 0;
}
.PageHeader-large {
padding: 20rem 0;
}
.PageHeader--Title {
font-size: 6rem;
margin-bottom: 0;
}
.PageHeader--Subtitle {
font-weight: 200;
font-weight: 400;
font-size: 1.8rem;
}

View file

@ -1,31 +1,32 @@
import React from 'react'
import PropTypes from 'prop-types'
import Content from './Content'
import BackgroundImage from './BackgroundImage'
import './PageHeader.css'
const PageHeader = ({ title, subtitle, backgroundImage }) => (
<div className='section PageHeader relative'>
{backgroundImage && <BackgroundImage src={backgroundImage} opacity={0.5} />}
<div className='container relative'>
<h1 className='PageHeader--Title' data-aos='fade-left'>
{title}
</h1>
{subtitle ? (
<h2
className='PageHeader--Subtitle'
data-aos='fade-left'
data-aos-duration='400'
>
{subtitle}
</h2>
) : (
''
const PageHeader = ({
title,
subtitle,
backgroundImage,
large,
className = ''
}) => {
if (large) className += ' PageHeader-large'
return (
<div className={`PageHeader relative ${className}`}>
{backgroundImage && (
<BackgroundImage src={backgroundImage} opacity={0.4} />
)}
<div className='container relative'>
<h1 className='PageHeader--Title'>{title}</h1>
{subtitle && (
<Content className='PageHeader--Subtitle' src={subtitle} />
)}
</div>
</div>
</div>
)
)
}
PageHeader.propTypes = {
title: PropTypes.string,
subtitle: PropTypes.string

View file

@ -1,7 +1,19 @@
.PostCard {
text-decoration: none;
margin: 4rem 2rem;
margin: 2rem;
background: white;
color: inherit;
border: 1px solid var(--lightGrey);
border-radius: var(--borderRadius);
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1);
transition: all 0.15s ease-in-out;
overflow: hidden;
}
.PostCard:hover,
.PostCard:focus {
transform: translateY(-1px);
box-shadow: 0 2px 30px rgba(0, 0, 0, 0.15);
}
.PostCard--Image {
@ -10,16 +22,15 @@
height: 15rem;
}
.PostCard--Title {
margin: 0;
}
.PostCard--Content {
padding: 0 2.5rem 2.5rem;
}
.PostCard--Category {
font-size: 1rem;
text-align: right;
}
.PostCard--Content {
margin: 0 auto;
width: 90%;
}
.PostCard--Title {
margin: 2rem 0;
}

View file

@ -1,5 +1,5 @@
.PostCategoriesNav {
margin: 4rem 0;
margin: 2rem 0;
display: flex;
align-items: center;
justify-content: flex-start;

View file

@ -1,3 +1,6 @@
.PostSection {
padding: 2rem 0;
}
.PostSection .PostCard {
width: calc(33.33% - 4rem);
}
@ -7,6 +10,7 @@
align-items: flex-start;
justify-content: center;
flex-wrap: wrap;
align-items: stretch;
}
@supports (display: grid) {

View file

@ -34,7 +34,7 @@ class PostSection extends React.Component {
.slice(0, limit || posts.length)
return (
<div className='section thin PostSection'>
<div className='PostSection'>
<div className='container'>
{title && <h2 className='PostSection--Title'>{title}</h2>}
{!!visiblePosts.length && (
@ -46,12 +46,12 @@ class PostSection extends React.Component {
)}
{showLoadMore &&
visiblePosts.length < posts.length && (
<div className='taCenter'>
<button className='button' onClick={this.increaseLimit}>
{loadMoreTitle}
</button>
</div>
)}
<div className='taCenter'>
<button className='button' onClick={this.increaseLimit}>
{loadMoreTitle}
</button>
</div>
)}
</div>
</div>
)

View file

@ -1,9 +1,10 @@
:root {
--primary: #ff3d3d;
--primary-light: #ff6f6f;
--primary: #0984d2;
--primary-light: #6fadff;
--secondary: #212121;
--lightGrey: whitesmoke;
--midGrey: #cacaca;
--darkGrey: #272727;
--danger: #ff3d3d;
--font-primary: 'Open Sans', sans-serif;
--font-system: '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto',
@ -26,18 +27,12 @@ body {
background: white;
color: var(--secondary);
font-size: 1.6em;
font-weight: 300;
font-weight: 400;
letter-spacing: 0.01em;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
*,
*:before,
*:after {
box-sizing: border-box;
}
a {
color: var(--primary);
}
@ -140,13 +135,13 @@ blockquote {
.section {
width: 100%;
padding: 5rem 0;
padding: 7.5rem 0;
}
.section.thick {
padding: 10rem 0;
}
.section.thin {
padding: 2.5rem 0;
padding: 3.5rem 0;
}
.section.noPadding {
padding: 0;
@ -171,11 +166,11 @@ blockquote {
color: white;
text-transform: uppercase;
text-decoration: none;
font-weight: 400;
letter-spacing: 0.15em;
font-weight: 700;
letter-spacing: 0.05em;
font-size: 1.4rem;
display: inline-block;
padding: 1rem 2rem;
padding: 1.25rem 3rem;
border: none;
transition: all 0.2s ease;
cursor: pointer;

View file

@ -1,7 +1,7 @@
import 'core-js/es6'
import React from 'react'
import { render } from 'react-snapshot'
import 'normalize.css'
import 'modern-normalize/modern-normalize.css'
import './globalStyles.css'
import App from './App'
import registerServiceWorker, { unregister } from './registerServiceWorker'

View file

@ -6,27 +6,30 @@ import LazyImage from '../components/LazyImage'
import Content from '../components/Content.js'
import './About.css'
export default ({ page }) => (
<div className='About'>
<Helmet>
<title>{page.title}</title>
</Helmet>
<PageHeader
title={page.title}
subtitle={page.subtitle}
backgroundImage={page.featuredImage}
/>
<div className='section thin'>
<div className='container'>
<Content source={page.section1} />
export default ({ page }) => {
const { title, subtitle, featuredImage, section1, section2 } = page
return (
<div className='About'>
<Helmet>
<title>{title}</title>
</Helmet>
<PageHeader
title={title}
subtitle={subtitle}
backgroundImage={featuredImage}
/>
<div className='section'>
<div className='container'>
<Content source={section1} />
</div>
</div>
<div className='section'>
<div className='container'>
<Content source={section2} />
<p>The image below is a {'<LazyImage />'}</p>
<LazyImage src={featuredImage} alt='LazyImage' />
</div>
</div>
</div>
<div className='section thin'>
<div className='container'>
<Content source={page.section2} />
<p>The image below is a {'<LazyImage />'}</p>
<LazyImage src={page.featuredImage} alt='LazyImage' />
</div>
</div>
</div>
)
)
}

View file

@ -8,17 +8,30 @@ import PostSection from '../components/PostSection'
import './Blog.css'
export default ({ page, posts, postCategories, showFeatured = true }) => {
export default ({
page,
posts = [],
postCategories = [],
showFeatured = true
}) => {
const { title, subtitle, featuredImage } = page
posts = _sortBy(posts, ['date']).reverse()
return (
<main className='Blog'>
<Helmet>
<title>Blog</title>
<title>{title}</title>
</Helmet>
<PageHeader title='Blog' />
<PostCategoriesNav categories={postCategories} />
<PageHeader
title={title}
subtitle={subtitle}
backgroundImage={featuredImage}
/>
{!!postCategories.length && (
<PostCategoriesNav categories={postCategories} />
)}
{!!posts.length && <PostSection posts={posts} />}
</main>
)

View file

@ -1,2 +1,38 @@
.Contact {
}
.Contact--Details {
margin-top: 3rem;
}
.Contact--Details--Item {
display: flex;
padding: 2rem 0;
border-top: 1px solid var(--lightGrey);
font-weight: 500;
text-decoration: none;
color: inherit;
transition: color 0.2s ease-in-out;
}
.Contact--Details--Item:hover,
.Contact--Details--Item:focus {
color: var(--primary);
}
.Contact--Details--Item svg {
margin-right: 1.5rem;
color: var(--primary);
}
@media (min-width: 750px) {
.Contact--Section1--Container {
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.Contact--Section1--Container > * {
width: calc(50% - 2rem);
}
}

View file

@ -1,35 +1,61 @@
import React from 'react'
import Helmet from 'react-helmet'
import { MapPin, Smartphone, Mail } from 'react-feather'
import PageHeader from '../components/PageHeader'
import EnquiryFormControlled from '../components/EnquiryFormControlled'
import EnquiryFormSimple from '../components/EnquiryFormSimple'
import EnquiryFormSimpleAjax from '../components/EnquiryFormSimpleAjax'
import Content from '../components/Content'
import './Contact.css'
export default ({ page, siteTitle }) => (
<div className='Contact'>
<PageHeader title={page.title} subtitle='<Contact />' />
<div className='section thin'>
<div className='container'>
<Content source={page.body} />
<h3>{'<EnquiryFormSimple />'}</h3>
<EnquiryFormSimple name='Simple Form' />
<br />
<h3>{'<EnquiryFormSimpleAjax />'}</h3>
<EnquiryFormSimpleAjax name='Simple Form Ajax' />
<br />
<h3>{'<EnquiryFormControlled />'}</h3>
<EnquiryFormControlled siteTitle={siteTitle} name={'Controlled Form'} />
<br />
<em>Note: these will only work when deployed on Netlify</em>
<br />
<em>Also, they are active and I will receive submissions</em> 😉
export default ({ page }) => {
const { title, subtitle, featuredImage, address, phone, email } = page
return (
<div className='Contact'>
<Helmet>
<title>{page.title}</title>
</Helmet>
<PageHeader
title={title}
subtitle={subtitle}
backgroundImage={featuredImage}
/>
<div className='section Contact--Section1'>
<div className='container Contact--Section1--Container'>
<div>
<Content source={page.body} />
<div className='Contact--Details'>
{address && (
<a
className='Contact--Details--Item'
href={`https://www.google.com.au/maps/search/${encodeURI(
address
)}`}
target='_blank'
>
<MapPin /> {address}
</a>
)}
{phone && (
<a className='Contact--Details--Item' href={`tel:${phone}`}>
<Smartphone /> {phone}
</a>
)}
{email && (
<a className='Contact--Details--Item' href={`mailto:${email}`}>
<Mail /> {email}
</a>
)}
</div>
</div>
<div>
<EnquiryFormSimpleAjax name='Simple Form Ajax' />
</div>
</div>
</div>
</div>
<Helmet>
<title>{page.title}</title>
</Helmet>
</div>
)
)
}

View file

@ -6,18 +6,23 @@ import PageHeader from '../components/PageHeader'
import './Home.css'
export default ({ page }) => {
const { title, subtitle, body } = page
const { title, subtitle, featuredImage, body } = page
return (
<main className='Home'>
<PageHeader title={title} subtitle={subtitle} />
<div className='section thin'>
<Helmet>
<title>{title}</title>
</Helmet>
<PageHeader
large
title={title}
subtitle={subtitle}
backgroundImage={featuredImage}
/>
<div className='section'>
<div className='container'>
<Content source={body} />
</div>
</div>
<Helmet>
<title>{title}</title>
</Helmet>
</main>
)
}

View file

@ -5,6 +5,27 @@
height: 50rem;
}
.SinglePost--BackButton {
color: white;
position: relative;
display: flex;
align-items: center;
font-weight: 600;
text-decoration: none;
letter-spacing: 0.1em;
}
.SinglePost--BackButton svg {
transition: transform 0.2s ease-out;
transform: translateX(0);
height: 1.2em;
}
.SinglePost--BackButton:hover svg,
.SinglePost--BackButton:focus svg {
transform: translateX(-0.25em);
}
.SinglePost--Content {
background: white;
margin-top: 30rem;
@ -43,10 +64,19 @@
}
.SinglePost--Pagination {
margin: 6rem 0 0 0;
margin: 4rem 0 0 0;
display: flex;
align-items: center;
justify-content: space-between;
}
.SinglePost--Pagination--Link {
text-transform: uppercase;
font-size: 1.2rem;
font-weight: 600;
text-decoration: none;
}
.SinglePost--Pagination--Link.next {
margin-left: auto;
}

View file

@ -1,6 +1,7 @@
import React from 'react'
import Helmet from 'react-helmet'
import { Link } from 'react-router-dom'
import { ChevronLeft } from 'react-feather'
import Content from '../components/Content'
import BackgroundImage from '../components/BackgroundImage'
@ -9,12 +10,13 @@ import { dateFormatted } from '../util/date'
import './SinglePost.css'
export default ({ singlePost, nextPostURL, prevPostURL }) => {
const { body, categories, postFeaturedImage, title, date } = singlePost
const { title, date, postFeaturedImage, body, categories = [] } = singlePost
return (
<article className='SinglePost section light'>
<Helmet>
<title>{title}</title>
</Helmet>
{postFeaturedImage && (
<BackgroundImage
className='SinglePost--BackgroundImage'
@ -24,9 +26,12 @@ export default ({ singlePost, nextPostURL, prevPostURL }) => {
)}
<div className='container skinny'>
<Link className='SinglePost--BackButton' to='/blog/'>
<ChevronLeft /> BACK
</Link>
<div className='SinglePost--Content relative'>
<div className='SinglePost--Meta'>
{!!categories &&
{!!categories.length &&
categories.map(obj => (
<span key={obj.category} className='SinglePost--Meta--Category'>
{obj.category}
@ -45,15 +50,21 @@ export default ({ singlePost, nextPostURL, prevPostURL }) => {
<Content source={body} />
</div>
<div className='SinglePost--Pagination Flex alignStretch justifyBetween flexWrap'>
{nextPostURL && (
<Link className='SinglePost--Pagination--Link' to={nextPostURL}>
Next Post
<div className='SinglePost--Pagination'>
{prevPostURL && (
<Link
className='SinglePost--Pagination--Link prev'
to={prevPostURL}
>
Previous Post
</Link>
)}
{prevPostURL && (
<Link className='SinglePost--Pagination--Link' to={prevPostURL}>
Previous Post
{nextPostURL && (
<Link
className='SinglePost--Pagination--Link next'
to={nextPostURL}
>
Next Post
</Link>
)}
</div>

483
yarn.lock

File diff suppressed because it is too large Load diff