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 ## 0.2.9 - 2018-05-30
* IE11 support updates * 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/) [![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) [![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) [![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 * Clone the repo into your Github account
* Create you a new project on Netlify, build & deploy * 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** * Enable **Identity**
* Change **Registration Preferences** to **Invite Only** * Change **Registration Preferences** to **Invite Only**
* Enable **Git Gateway** * 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** * 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 ## 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` `yarn` or `npm install`
1. Run the development server 1. Run the development server
`yarn start` or `npm run start` `yarn start` or `npm run start`
If you are adding or editing content locally in the CMS, a couple of things to note: 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 ## Editing CMS fields

View file

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

View file

@ -1,9 +1,8 @@
--- ---
title: About page title title: About page title
subtitle: <About />
featuredImage: /images/uploads/tim-marshall-155597.jpg featuredImage: /images/uploads/tim-marshall-155597.jpg
section1: |- section1: |-
## Hello World! ## Lorem Ipsum
Netlify CMS works with both `.md` and `.json`. 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> <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 ## This is a Container component
A sem vel nec sodales mi vivamus senectus sed potenti a parturient nascetur A sem vel nec sodales mi vivamus senectus sed potenti a parturient nascetur
tincidunt nisi pulvinar rhoncus a. Risus imperdiet taciti suspendisse facilisi tincidunt nisi pulvinar rhoncus a. Risus imperdiet taciti suspendisse facilisi
a per metus cubilia varius a nostra adipiscing amet ultrices quisque ac mi a. 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 bibendum duis netus a consectetur dui magnis ac aliquet sem posuere tincidunt
vestibulum. vestibulum.
The image below will have a `srcset` attribute generated: The image below will have a `srcset` attribute generated:
![Tim Marshall](/images/uploads/tim-marshall-155597.jpg) ![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 title: Contact us
subtitle: <Contact /> 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 # Example contact form
This form is setup to use Netlify's form handling: This form is setup to use Netlify's form handling:
- the form action is set to the current absolute url: `action: '/contact/'` * 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'` * 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` * 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/). Find out more in the [Netlify Docs](https://www.netlify.com/docs/form-handling/).

View file

@ -1,13 +1,10 @@
--- ---
title: Hello World! title: Hello World!
subtitle: <Home /> subtitle: This is the home page subtitle
featuredImage: '/images/uploads/isabella juskova.jpg'
--- ---
# 🌶 Netlify CMS + React Starter # 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)
A starter project for creating lightning-fast, offline-first websites with [Netlify CMS](https://netlifycms.org) and React. 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 ⭐️ * **[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 * **[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 ## See also
[Netlify CMS Docs](https://www.netlifycms.org/docs/) [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 status: Published
date: '2018-05-25' date: '2018-05-25'
postFeaturedImage: /images/uploads/isabella juskova.jpg 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 title: Post Two
status: Published status: Published
categories: categories:
- category: Fluff - category: Updates
date: '2018-03-28' date: '2018-03-28'
postFeaturedImage: /images/uploads/vyouw5byhlc.jpeg postFeaturedImage: /images/uploads/vyouw5byhlc.jpeg
excerpt: This is an excerpt of Post Two excerpt: This is an excerpt of Post Two

View file

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

View file

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

View file

@ -14,30 +14,42 @@ collections: # A list of collections the CMS should be able to edit
editor: editor:
preview: true preview: true
files: files:
- file: "content/pages/home.md" - file: "content/pages/contact.md"
label: "Home Page" label: "Contact Page"
name: "home-page" name: "contact-page"
fields: fields:
- {label: Title, name: title, widget: string} - {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: 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" - file: "content/pages/about.md"
label: "About Page" label: "About Page"
name: "about-page" name: "about-page"
fields: fields:
- {label: Title, name: title, widget: string} - {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: Featured Image, name: featuredImage, widget: image}
- {label: Section 1, name: section1, widget: markdown} - {label: Section 1, name: section1, widget: markdown}
- {label: Section 2, name: section2, widget: markdown} - {label: Section 2, name: section2, widget: markdown}
- file: "content/pages/contact.md" - file: "content/pages/home.md"
label: "Contact Page" label: "Home Page"
name: "contact-page" name: "home-page"
fields: fields:
- {label: Title, name: title, widget: string} - {label: Title, name: title, widget: string}
- {label: Subtitle, name: subtitle, widget: string} - {label: Subtitle, name: subtitle, widget: markdown}
- {label: Body, name: body, 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 src="https://identity-js.netlify.com/v1/netlify-identity-widget.js"></script>
<script> <script>
// check for netlifyIdentity, redirect to admin if user is logging in // check for netlifyIdentity, redirect to admin if user is logging in
if (window.localStorage && window.netlifyIdentity) { if (window.localStorage && window.netlifyIdentity) {
netlifyIdentity.on('init', function (user) { netlifyIdentity.on('init', function(user) {
if (!user) { if (!user) {
netlifyIdentity.on('login', function () { netlifyIdentity.on('login', function() {
document.location.href = '/admin/' document.location.href = '/admin/'
}) })
} }
}) })
} }
</script> </script>
</body> </body>
</html> </html>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,19 @@
.PostCard { .PostCard {
text-decoration: none; text-decoration: none;
margin: 4rem 2rem; margin: 2rem;
background: white; 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 { .PostCard--Image {
@ -10,16 +22,15 @@
height: 15rem; height: 15rem;
} }
.PostCard--Title {
margin: 0;
}
.PostCard--Content {
padding: 0 2.5rem 2.5rem;
}
.PostCard--Category { .PostCard--Category {
font-size: 1rem; font-size: 1rem;
text-align: right; text-align: right;
} }
.PostCard--Content {
margin: 0 auto;
width: 90%;
}
.PostCard--Title {
margin: 2rem 0;
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,27 +6,30 @@ import LazyImage from '../components/LazyImage'
import Content from '../components/Content.js' import Content from '../components/Content.js'
import './About.css' import './About.css'
export default ({ page }) => ( export default ({ page }) => {
<div className='About'> const { title, subtitle, featuredImage, section1, section2 } = page
<Helmet> return (
<title>{page.title}</title> <div className='About'>
</Helmet> <Helmet>
<PageHeader <title>{title}</title>
title={page.title} </Helmet>
subtitle={page.subtitle} <PageHeader
backgroundImage={page.featuredImage} title={title}
/> subtitle={subtitle}
<div className='section thin'> backgroundImage={featuredImage}
<div className='container'> />
<Content source={page.section1} /> <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> </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' 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() posts = _sortBy(posts, ['date']).reverse()
return ( return (
<main className='Blog'> <main className='Blog'>
<Helmet> <Helmet>
<title>Blog</title> <title>{title}</title>
</Helmet> </Helmet>
<PageHeader title='Blog' />
<PostCategoriesNav categories={postCategories} /> <PageHeader
title={title}
subtitle={subtitle}
backgroundImage={featuredImage}
/>
{!!postCategories.length && (
<PostCategoriesNav categories={postCategories} />
)}
{!!posts.length && <PostSection posts={posts} />} {!!posts.length && <PostSection posts={posts} />}
</main> </main>
) )

View file

@ -1,2 +1,38 @@
.Contact { .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 React from 'react'
import Helmet from 'react-helmet' import Helmet from 'react-helmet'
import { MapPin, Smartphone, Mail } from 'react-feather'
import PageHeader from '../components/PageHeader' import PageHeader from '../components/PageHeader'
import EnquiryFormControlled from '../components/EnquiryFormControlled'
import EnquiryFormSimple from '../components/EnquiryFormSimple'
import EnquiryFormSimpleAjax from '../components/EnquiryFormSimpleAjax' import EnquiryFormSimpleAjax from '../components/EnquiryFormSimpleAjax'
import Content from '../components/Content' import Content from '../components/Content'
import './Contact.css' import './Contact.css'
export default ({ page, siteTitle }) => ( export default ({ page }) => {
<div className='Contact'> const { title, subtitle, featuredImage, address, phone, email } = page
<PageHeader title={page.title} subtitle='<Contact />' /> return (
<div className='section thin'> <div className='Contact'>
<div className='container'> <Helmet>
<Content source={page.body} /> <title>{page.title}</title>
<h3>{'<EnquiryFormSimple />'}</h3> </Helmet>
<EnquiryFormSimple name='Simple Form' />
<br /> <PageHeader
<h3>{'<EnquiryFormSimpleAjax />'}</h3> title={title}
<EnquiryFormSimpleAjax name='Simple Form Ajax' /> subtitle={subtitle}
<br /> backgroundImage={featuredImage}
<h3>{'<EnquiryFormControlled />'}</h3> />
<EnquiryFormControlled siteTitle={siteTitle} name={'Controlled Form'} />
<br /> <div className='section Contact--Section1'>
<em>Note: these will only work when deployed on Netlify</em> <div className='container Contact--Section1--Container'>
<br /> <div>
<em>Also, they are active and I will receive submissions</em> 😉 <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>
</div> </div>
<Helmet> )
<title>{page.title}</title> }
</Helmet>
</div>
)

View file

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

View file

@ -5,6 +5,27 @@
height: 50rem; 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 { .SinglePost--Content {
background: white; background: white;
margin-top: 30rem; margin-top: 30rem;
@ -43,10 +64,19 @@
} }
.SinglePost--Pagination { .SinglePost--Pagination {
margin: 6rem 0 0 0; margin: 4rem 0 0 0;
display: flex;
align-items: center;
justify-content: space-between;
} }
.SinglePost--Pagination--Link { .SinglePost--Pagination--Link {
text-transform: uppercase; text-transform: uppercase;
font-size: 1.2rem; 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 React from 'react'
import Helmet from 'react-helmet' import Helmet from 'react-helmet'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { ChevronLeft } from 'react-feather'
import Content from '../components/Content' import Content from '../components/Content'
import BackgroundImage from '../components/BackgroundImage' import BackgroundImage from '../components/BackgroundImage'
@ -9,12 +10,13 @@ import { dateFormatted } from '../util/date'
import './SinglePost.css' import './SinglePost.css'
export default ({ singlePost, nextPostURL, prevPostURL }) => { export default ({ singlePost, nextPostURL, prevPostURL }) => {
const { body, categories, postFeaturedImage, title, date } = singlePost const { title, date, postFeaturedImage, body, categories = [] } = singlePost
return ( return (
<article className='SinglePost section light'> <article className='SinglePost section light'>
<Helmet> <Helmet>
<title>{title}</title> <title>{title}</title>
</Helmet> </Helmet>
{postFeaturedImage && ( {postFeaturedImage && (
<BackgroundImage <BackgroundImage
className='SinglePost--BackgroundImage' className='SinglePost--BackgroundImage'
@ -24,9 +26,12 @@ export default ({ singlePost, nextPostURL, prevPostURL }) => {
)} )}
<div className='container skinny'> <div className='container skinny'>
<Link className='SinglePost--BackButton' to='/blog/'>
<ChevronLeft /> BACK
</Link>
<div className='SinglePost--Content relative'> <div className='SinglePost--Content relative'>
<div className='SinglePost--Meta'> <div className='SinglePost--Meta'>
{!!categories && {!!categories.length &&
categories.map(obj => ( categories.map(obj => (
<span key={obj.category} className='SinglePost--Meta--Category'> <span key={obj.category} className='SinglePost--Meta--Category'>
{obj.category} {obj.category}
@ -45,15 +50,21 @@ export default ({ singlePost, nextPostURL, prevPostURL }) => {
<Content source={body} /> <Content source={body} />
</div> </div>
<div className='SinglePost--Pagination Flex alignStretch justifyBetween flexWrap'> <div className='SinglePost--Pagination'>
{nextPostURL && ( {prevPostURL && (
<Link className='SinglePost--Pagination--Link' to={nextPostURL}> <Link
Next Post className='SinglePost--Pagination--Link prev'
to={prevPostURL}
>
Previous Post
</Link> </Link>
)} )}
{prevPostURL && ( {nextPostURL && (
<Link className='SinglePost--Pagination--Link' to={prevPostURL}> <Link
Previous Post className='SinglePost--Pagination--Link next'
to={nextPostURL}
>
Next Post
</Link> </Link>
)} )}
</div> </div>

483
yarn.lock

File diff suppressed because it is too large Load diff