├── .prettierrc ├── gatsby-ssr.js ├── gatsby-browser.js ├── .eslintrc ├── src ├── pages │ ├── 404.js │ ├── projects.js │ ├── about.js │ ├── work.js │ └── index.js ├── images │ └── gap_logo.svg └── components │ ├── seo.js │ ├── projectDisplay.js │ ├── layout.js │ ├── header.js │ └── layout.scss ├── gatsby-node.js ├── LICENSE ├── .gitignore ├── gatsby-config.js ├── package.json └── README.md /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "semi": false, 4 | "singleQuote": false, 5 | "tabWidth": 2, 6 | "trailingComma": "es5" 7 | } 8 | -------------------------------------------------------------------------------- /gatsby-ssr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's SSR (Server Side Rendering) APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/ssr-apis/ 5 | */ 6 | 7 | // You can delete this file if you're not using it 8 | -------------------------------------------------------------------------------- /gatsby-browser.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implement Gatsby's Browser APIs in this file. 3 | * 4 | * See: https://www.gatsbyjs.org/docs/browser-apis/ 5 | */ 6 | 7 | // require('rsuite/dist/styles/rsuite.min.css'); 8 | require('rsuite/styles/less/index.less'); 9 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "settings": { 3 | "react": { 4 | "version": "^16.6.3" 5 | } 6 | }, 7 | "parser": "babel-eslint", 8 | "rules": { 9 | "strict": 0, 10 | "no-console": 1 11 | }, 12 | "extends": [ 13 | "eslint:recommended", 14 | "plugin:react/recommended" 15 | ], 16 | "env": { 17 | "es6": true, 18 | "browser": true, 19 | "amd": true, 20 | "node": true 21 | } 22 | } -------------------------------------------------------------------------------- /src/pages/404.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | import Layout from "../components/layout" 4 | import SEO from "../components/seo" 5 | 6 | const NotFoundPage = () => ( 7 | 8 | 9 |

NOT FOUND

10 |

You just hit a route that doesn't exist... the sadness.

11 |
12 | ) 13 | 14 | export default NotFoundPage 15 | -------------------------------------------------------------------------------- /gatsby-node.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | /** 3 | * Implement Gatsby's Node APIs in this file. 4 | * 5 | * See: https://www.gatsbyjs.org/docs/node-apis/ 6 | */ 7 | exports.onCreatePage = ({ page, actions }) => { 8 | const { createPage, deletePage } = actions 9 | const pageContext = { 10 | readKey: `${process.env.COSMIC_READ_KEY}`, 11 | cosmicBucket: `${process.env.COSMIC_BUCKET_SLUG}`, 12 | } 13 | if (process.env.NODE_ENV === 'production') { 14 | pageContext.buildhookUrl = `${process.env.BUILDHOOK_ENDPOINT}` 15 | } 16 | deletePage(page) 17 | createPage({ 18 | ...page, 19 | context: pageContext, 20 | }) 21 | } 22 | 23 | // You can delete this file if you're not using it 24 | -------------------------------------------------------------------------------- /src/images/gap_logo.svg: -------------------------------------------------------------------------------- 1 | gap_logo -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 gatsbyjs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # dotenv environment variables file 55 | .env 56 | 57 | # gatsby files 58 | .cache/ 59 | public 60 | 61 | # Mac files 62 | .DS_Store 63 | 64 | # Yarn 65 | yarn-error.log 66 | .pnp/ 67 | .pnp.js 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | -------------------------------------------------------------------------------- /gatsby-config.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config() 2 | 3 | module.exports = { 4 | siteMetadata: { 5 | title: `Gatsby Agency Portfolio`, 6 | description: `A portfolio for your creative shop`, 7 | author: `@JacobKnaack`, 8 | }, 9 | plugins: [ 10 | `gatsby-plugin-eslint`, 11 | `gatsby-plugin-react-helmet`, 12 | { 13 | resolve: `gatsby-plugin-manifest`, 14 | options: { 15 | name: `gatsby-agency-portfolio`, 16 | short_name: `GAP`, 17 | start_url: `/`, 18 | icon: `src/images/gap_logo.svg`, 19 | }, 20 | }, 21 | { 22 | resolve: `gatsby-source-filesystem`, 23 | options: { 24 | name: `images`, 25 | path: `${__dirname}/src/images`, 26 | }, 27 | }, 28 | `gatsby-plugin-sass`, 29 | `gatsby-plugin-styled-components`, 30 | { 31 | resolve: `gatsby-plugin-less`, 32 | options: { 33 | javascriptEnabled: true, 34 | } 35 | }, 36 | { 37 | resolve: `gatsby-source-cosmicjs`, 38 | options: { 39 | bucketSlug: process.env.COSMIC_BUCKET_SLUG, 40 | objectTypes: [`pages`, `people`, `services`, `projects`, `settings`, `connects`, `skills`, `clients`, `contacts`], 41 | apiAccess: { 42 | read_key: process.env.COSMIC_READ_KEY, 43 | } 44 | } 45 | } 46 | // this (optional) plugin enables Progressive Web App + Offline functionality 47 | // To learn more, visit: https://gatsby.dev/offline 48 | // `gatsby-plugin-offline`, 49 | ], 50 | } 51 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gatsby-agency-portfolio", 3 | "private": true, 4 | "description": "A Static Portfolio site, designed for creative agencies", 5 | "version": "0.1.0", 6 | "author": "Jacob Knaack", 7 | "dependencies": { 8 | "babel-plugin-styled-components": "^1.10.0", 9 | "dotenv": "^7.0.0", 10 | "gatsby": "^2.3.25", 11 | "gatsby-image": "^2.0.39", 12 | "gatsby-plugin-eslint": "^2.0.4", 13 | "gatsby-plugin-less": "^2.0.12", 14 | "gatsby-plugin-manifest": "^2.0.29", 15 | "gatsby-plugin-offline": "^2.0.25", 16 | "gatsby-plugin-react-helmet": "^3.0.12", 17 | "gatsby-plugin-sass": "^2.0.11", 18 | "gatsby-plugin-sharp": "^2.0.35", 19 | "gatsby-plugin-styled-components": "^3.0.7", 20 | "gatsby-source-cosmicjs": "^0.0.7", 21 | "gatsby-source-filesystem": "^2.0.29", 22 | "gatsby-source-graphql": "^2.0.18", 23 | "gatsby-transformer-sharp": "^2.1.18", 24 | "less": "^3.9.0", 25 | "node-sass": "^4.11.0", 26 | "prop-types": "^15.7.2", 27 | "react": "^16.8.6", 28 | "react-dom": "^16.8.6", 29 | "react-helmet": "^5.2.0", 30 | "rsuite": "^3.8.3", 31 | "styled-components": "^4.2.0" 32 | }, 33 | "devDependencies": { 34 | "prettier": "^1.17.0" 35 | }, 36 | "keywords": [ 37 | "gatsby" 38 | ], 39 | "license": "MIT", 40 | "scripts": { 41 | "build": "gatsby build", 42 | "develop": "gatsby develop", 43 | "format": "prettier --write src/**/*.{js,jsx}", 44 | "start": "npm run develop", 45 | "serve": "gatsby serve", 46 | "test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\"" 47 | }, 48 | "repository": { 49 | "type": "git", 50 | "url": "https://github.com/JacobKnaack/gatsby-agency-portfolio" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/components/seo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SEO component that queries for data with 3 | * Gatsby's useStaticQuery React hook 4 | * 5 | * See: https://www.gatsbyjs.org/docs/use-static-query/ 6 | */ 7 | 8 | import React from "react" 9 | import PropTypes from "prop-types" 10 | import Helmet from "react-helmet" 11 | import { useStaticQuery, graphql } from "gatsby" 12 | 13 | function SEO({ description, lang, meta, keywords, title }) { 14 | const { site } = useStaticQuery( 15 | graphql` 16 | query { 17 | site { 18 | siteMetadata { 19 | title 20 | description 21 | author 22 | } 23 | } 24 | } 25 | ` 26 | ) 27 | 28 | const metaDescription = description || site.siteMetadata.description 29 | 30 | return ( 31 | 0 73 | ? { 74 | name: `keywords`, 75 | content: keywords.join(`, `), 76 | } 77 | : [] 78 | ) 79 | .concat(meta)} 80 | /> 81 | ) 82 | } 83 | 84 | SEO.defaultProps = { 85 | lang: `en`, 86 | meta: [], 87 | keywords: [], 88 | description: ``, 89 | } 90 | 91 | SEO.propTypes = { 92 | description: PropTypes.string, 93 | lang: PropTypes.string, 94 | meta: PropTypes.arrayOf(PropTypes.object), 95 | keywords: PropTypes.arrayOf(PropTypes.string), 96 | title: PropTypes.string.isRequired, 97 | } 98 | 99 | export default SEO 100 | -------------------------------------------------------------------------------- /src/components/projectDisplay.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import PropTypes from 'prop-types' 3 | import { Link } from 'gatsby' 4 | 5 | class ProjectDisplay extends React.Component { 6 | constructor() { 7 | super() 8 | this.state = { 9 | hover: false 10 | } 11 | this.handleHover = this.handleHover.bind(this) 12 | this.handleUnHover = this.handleUnHover.bind(this) 13 | } 14 | 15 | render() { 16 | let styles = { 17 | container: { 18 | margin: '10px 0 0 10px', 19 | minWidth: '400px', 20 | minHeight: '400px', 21 | height: '400px', 22 | overflow: 'hidden', 23 | textDecoration: 'none', 24 | }, 25 | details: { 26 | height: '400px', 27 | width: '400px', 28 | padding: '30px', 29 | opacity: '0', 30 | color: '#d3d3d3', 31 | background: 'rgba(0, 0, 0, 0.6)', 32 | position: 'relative', 33 | display: 'flex', 34 | flexDirection: 'column', 35 | justifyContent: 'flex-end', 36 | alignItems: 'flex-start', 37 | overflowY: 'auto', 38 | transition: '0.3s ease-in-out' 39 | }, 40 | title: { 41 | fontSize: '2rem', 42 | alignText: 'center', 43 | }, 44 | description: { 45 | fontSize: '1rem', 46 | } 47 | } 48 | if (this.props.image) { 49 | styles.container.background = `url(${this.props.image})` 50 | styles.container.backgroundSize = 'cover' 51 | styles.container.backgroundPosition = 'center' 52 | } 53 | if (this.props.size === 'tall') { 54 | styles.container.height = '600px' 55 | styles.details.height = '600px' 56 | } 57 | if (this.state.hover) { 58 | styles.details.opacity = '1' 59 | } 60 | 61 | return ( 62 | 68 |
69 |
{this.props.title}
70 |

{this.props.description}

71 |
72 | 73 | ) 74 | } 75 | 76 | handleHover() { 77 | this.setState({ hover: true }) 78 | } 79 | handleUnHover() { 80 | this.setState({ hover: false }) 81 | } 82 | } 83 | 84 | ProjectDisplay.propTypes = { 85 | title: PropTypes.string, 86 | description: PropTypes.string, 87 | image: PropTypes.string, 88 | size: PropTypes.string, 89 | } 90 | 91 | export default ProjectDisplay -------------------------------------------------------------------------------- /src/components/layout.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Layout component that queries for data 3 | * with Gatsby's StaticQuery component 4 | * 5 | * See: https://www.gatsbyjs.org/docs/static-query/ 6 | */ 7 | 8 | import React from "react" 9 | import PropTypes from "prop-types" 10 | 11 | import { Container, Icon } from 'rsuite' 12 | import Header from "./header" 13 | import "./layout.scss" 14 | 15 | const Layout = ({ children, siteTitle, siteLogo, contact, connect, headerBreakpoint }) => { 16 | const styles = { 17 | main: { 18 | minheight: 'calc(100vh - 185px)', 19 | }, 20 | footer: { 21 | width: "100%", 22 | height: '200px', 23 | position: 'relative', 24 | display: "flex", 25 | flexDirection: 'row', 26 | justifyContent: 'space-around', 27 | alignItems: 'center', 28 | backgroundColor: 'black', 29 | color: 'white', 30 | }, 31 | linkContainer: { 32 | display: 'flex', 33 | flexDirection: 'row', 34 | justifyContent: 'space-around', 35 | alignItems: 'center', 36 | }, 37 | link: { 38 | margin: '0 15px', 39 | }, 40 | span: { 41 | display: 'flex', 42 | flexDirection: 'row', 43 | justifyContent: 'space-between', 44 | alignItems: 'center', 45 | }, 46 | contactLine: { 47 | marginBottom: '10px' 48 | } 49 | } 50 | return ( 51 | 52 |
53 |
{children}
54 |
55 | {contact 56 | ?
57 |
{contact.address1}
58 |
{contact.address2}
59 |
{`${contact.city} ${contact.region}, ${contact.postal_code}`}
60 |
{`Phone: ${contact.country_code ? contact.country_code : null} ${contact.phone_number}`}
61 |
{`Email: ${contact.email}`}
62 |
63 | : null 64 | } 65 | 66 | © {new Date().getFullYear()}, Built with  Gatsby 67 | 68 | 69 | {connect 70 | ?
71 | {connect.map(link => { 72 | return ( 73 | 74 | 75 | 76 | ) 77 | })} 78 |
79 | : null 80 | } 81 |
82 | 83 | ) 84 | } 85 | 86 | Layout.propTypes = { 87 | children: PropTypes.node.isRequired, 88 | siteTitle: PropTypes.string, 89 | siteLogo: PropTypes.object, 90 | contact: PropTypes.object, 91 | connect: PropTypes.array, 92 | headerBreakpoint: PropTypes.number, 93 | } 94 | 95 | export default Layout 96 | -------------------------------------------------------------------------------- /src/components/header.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { Link } from "gatsby" 3 | import PropTypes from "prop-types" 4 | import { Navbar, Nav } from "rsuite" 5 | 6 | class Header extends React.Component { 7 | constructor() { 8 | super() 9 | this.state = { 10 | scrollTop: true, 11 | activeKey: '', 12 | } 13 | this.handleScroll = this.handleScroll.bind(this) 14 | } 15 | 16 | componentWillMount() { 17 | if (typeof window !== 'undefined') { 18 | if (window.location.hash) { 19 | this.setState({ activeKey: window.location.hash }) 20 | } else { 21 | this.setState({ activeKey: window.location.pathname }) 22 | } 23 | } 24 | } 25 | 26 | componentDidMount() { 27 | if (typeof window !== 'undefined') { 28 | window.addEventListener('scroll', this.handleScroll) 29 | } 30 | } 31 | 32 | componentWillUnmount() { 33 | if (typeof window !== 'undefined') { 34 | window.removeEventListener('scroll', this.handleScroll) 35 | } 36 | } 37 | 38 | render() { 39 | const styles = { 40 | container: { 41 | position: 'fixed', 42 | width: '100%', 43 | zIndex: 100, 44 | background: 'none', 45 | display: 'flex', 46 | flexDirection: 'row', 47 | justifyContent: 'space-between', 48 | alignItems: 'center', 49 | transition: '0.75s ease-in-out' 50 | }, 51 | navheader: { 52 | display: 'flex', 53 | flexDirection: 'row', 54 | justifyContent: 'space-between', 55 | alignItems: 'center', 56 | height: '100%', 57 | }, 58 | link: { 59 | color: `#728f99`, 60 | textShadow: '0px 0px 1px #ffffff', 61 | margin: '0 0 0 30px', 62 | textDecoration: `none`, 63 | }, 64 | logo: { 65 | width: '50px', 66 | padding: '10px', 67 | margin: '0', 68 | } 69 | } 70 | if (!this.state.scrollTop) { 71 | styles.container.background = `#000000` 72 | styles.container.color = `#ffffff` 73 | styles.link.color = `#ffffff` 74 | styles.link.textShadow = 'none' 75 | } 76 | 77 | const { siteTitle, logo } = this.props 78 | return ( 79 | 80 | 81 | {logo ? :
GAP
} 82 |

83 | 84 | {siteTitle} 85 | 86 |

87 |
88 | 89 | 119 | 120 |
121 | ) 122 | } 123 | 124 | handleScroll() { 125 | let breakpoint = window.innerHeight / 2 126 | if (this.props.breakpoint) { 127 | breakpoint = this.props.breakpoint 128 | } 129 | if (window.scrollY > breakpoint) { 130 | this.setState({ 131 | scrollTop: false, 132 | }) 133 | } else { 134 | this.setState({ 135 | scrollTop: true, 136 | }) 137 | } 138 | } 139 | } 140 | 141 | Header.propTypes = { 142 | siteTitle: PropTypes.string, 143 | logo: PropTypes.object, 144 | breakpoint: PropTypes.number, 145 | } 146 | 147 | Header.defaultProps = { 148 | siteTitle: ``, 149 | } 150 | 151 | export default Header 152 | -------------------------------------------------------------------------------- /src/pages/projects.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from 'prop-types' 3 | import { graphql } from "gatsby" 4 | import { Modal } from 'rsuite' 5 | 6 | import ProjectDisplay from '../components/projectDisplay.js' 7 | import Layout from "../components/layout" 8 | import SEO from "../components/seo" 9 | 10 | class Projects extends React.Component { 11 | constructor() { 12 | super() 13 | this.state = { 14 | selectedProject: {}, 15 | modalOpen: false 16 | } 17 | } 18 | 19 | static getDerivedStateFromProps(props, state) { 20 | const tempState = state 21 | const list = props.data.allCosmicjsProjects.edges 22 | let projectName 23 | if (typeof window !== "undefined") { 24 | projectName = decodeURI(window.location.search).substring(1) 25 | } 26 | for (const i in list) { 27 | if (list[i].node.title === projectName) { 28 | tempState.selectedProject = list[i].node 29 | tempState.modalOpen = true 30 | } 31 | } 32 | return tempState 33 | } 34 | 35 | render() { 36 | const pageData = this.props.data.cosmicjsPages.metadata 37 | const projectData = this.props.data.allCosmicjsProjects.edges 38 | const connectData = this.props.data.allCosmicjsConnects.edges 39 | const contactData = this.props.data.cosmicjsContacts.metadata 40 | const siteData = this.props.data.cosmicjsSettings.metadata 41 | let headerBreakpoint 42 | if (typeof window !== 'undefined') { 43 | headerBreakpoint = window.innerHeight / 3 44 | } 45 | const styles = { 46 | header: { 47 | padding: '0', 48 | }, 49 | modal: { 50 | top: '50px' 51 | }, 52 | gallery: { 53 | marginTop: '15px', 54 | display: 'flex', 55 | flexDirection: 'column', 56 | justifyContent: 'flex-start', 57 | alignItems: 'center', 58 | } 59 | } 60 | if (pageData.splash_image) { 61 | styles.header.background = `url(${pageData.splash_image.url})` 62 | styles.header.backgroundSize = 'cover' 63 | styles.header.backgroundPosition = 'center' 64 | } 65 | return ( 66 | 73 | 74 |
75 |
76 |
77 |

Check Out Our Work

78 |

{pageData.summary}

79 |
80 |
81 |
82 | {projectData.map(project => { 83 | return ( 84 | 91 | ) 92 | })} 93 |
94 | 95 | {this.state.selectedProject.title 96 | ? 97 | {this.state.selectedProject.title} 98 |

{this.state.selectedProject.metadata.date}

99 |
100 | : null 101 | } 102 | {this.state.selectedProject.title 103 | ? 104 | {this.state.selectedProject.metadata.description} 105 |
106 | {this.state.selectedProject.metadata.gallery.map(imageUrl => ( 107 | {this.state.selectedProject.title} 112 | ))} 113 |
114 |
115 | : null 116 | } 117 |
118 |
119 |
120 | ) 121 | } 122 | 123 | handleClose() { 124 | if (typeof window !== 'undefined') { 125 | window.location.href = window.location.protocol + window.location.pathname 126 | } 127 | } 128 | } 129 | 130 | export const query = graphql` 131 | query Projects { 132 | cosmicjsPages(slug: { eq: "projects" }) { 133 | metadata { 134 | splash_image { 135 | url 136 | } 137 | summary 138 | } 139 | } 140 | allCosmicjsProjects { 141 | edges { 142 | node { 143 | title 144 | metadata { 145 | date 146 | gallery 147 | image { 148 | url 149 | } 150 | summary 151 | description 152 | } 153 | } 154 | } 155 | } 156 | allCosmicjsConnects { 157 | edges { 158 | node { 159 | title 160 | metadata { 161 | url 162 | } 163 | } 164 | } 165 | } 166 | cosmicjsContacts(slug: {eq: "company-footer"}) { 167 | metadata { 168 | address1 169 | address2 170 | postal_code 171 | city 172 | region 173 | country_code 174 | email 175 | phone_number 176 | } 177 | } 178 | cosmicjsSettings(slug: { eq: "site-data" }) { 179 | metadata { 180 | site_title 181 | site_logo { 182 | url 183 | } 184 | } 185 | } 186 | } 187 | ` 188 | 189 | Projects.propTypes = { 190 | data: PropTypes.object.isRequired, 191 | } 192 | 193 | export default Projects -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Gatsby Agency Portfolio 4 | 5 |

6 |

7 | Gatsby Agency Portfolio 8 |

9 | 10 |

11 | 12 | View Demo 13 | 14 |

15 | 16 |

Portfolio client designed with creative agencies in mind.

17 | 18 | ## Getting Started 19 | 20 | This project uses Gatsby and has been boostrapped using the [Gatsby CLI](https://www.gatsbyjs.org/docs/gatsby-cli/) 21 | 22 | 1. **Install this source code.** 23 | 24 | Clone this directory to your local machine 25 | 26 | ```sh 27 | git clone https://github.com/cosmicjs/gatsby-agency-portfolio 28 | ``` 29 | 30 | Install project dependencies 31 | ```sh 32 | npm install 33 | ``` 34 | or 35 | ```sh 36 | yarn install 37 | ``` 38 | 39 | 2. **Intialize your bucket on Cosmic JS.** 40 | 41 | Click here to get started: [![Powered by Cosmic JS](https://s3-us-west-2.amazonaws.com/cosmicjs/51fe54d0-4f6e-11e9-9f32-8d001da69630-powered-by-cosmicjs.svg)](https://cosmicjs.com/add-bucket?import_bucket=5cbf745a10d5c22da1f9b3e2) 42 | 43 | You will need to create a file for configuring your local runtime environment 44 | 45 | ```sh 46 | cd gatsby-agency-portfolio/ 47 | touch .env 48 | ``` 49 | 50 | Add your environment variables 51 | ```sh 52 | # inside .env at project root 53 | COSMIC_READ_KEY=your-cosmic-js-read-key 54 | COSMIC_BUCKET_SLUG=your-cosmic-bucket-slug 55 | ``` 56 | 57 | 3. **Start developing.** 58 | 59 | start the development server. 60 | 61 | ```sh 62 | gatsby develop 63 | ``` 64 | 65 | 4. **Open the source code and start editing!** 66 | 67 | Your site is now running at `http://localhost:8000`! 68 | 69 | _Note: You'll also see a second link: _`http://localhost:8000/___graphql`_. This is a tool you can use to experiment with querying your data. Learn more about using this tool in the [Gatsby tutorial](https://www.gatsbyjs.org/tutorial/part-five/#introducing-graphiql)._ 70 | 71 | Open the `gatsby-agency-portfolio` directory in your code editor of choice and edit `src/pages/index.js`. Save your changes and the browser will update in real time! 72 | 73 | ## 🧐 What's inside? 74 | 75 | A quick look at the top-level files and directories you'll see in a Gatsby project. 76 | 77 | . 78 | ├── node_modules 79 | ├── src 80 | ├── .gitignore 81 | ├── .prettierrc 82 | ├── gatsby-browser.js 83 | ├── gatsby-config.js 84 | ├── gatsby-node.js 85 | ├── gatsby-ssr.js 86 | ├── LICENSE 87 | ├── package-lock.json 88 | ├── package.json 89 | └── README.md 90 | 91 | 1. **`/node_modules`**: This directory contains all of the modules of code that your project depends on (npm packages) are automatically installed. 92 | 93 | 2. **`/src`**: This directory will contain all of the code related to what you will see on the front-end of your site (what you see in the browser) such as your site header or a page template. `src` is a convention for “source code”. 94 | 95 | 3. **`.gitignore`**: This file tells git which files it should not track / not maintain a version history for. 96 | 97 | 4. **`.prettierrc`**: This is a configuration file for [Prettier](https://prettier.io/). Prettier is a tool to help keep the formatting of your code consistent. 98 | 99 | 5. **`gatsby-browser.js`**: This file is where Gatsby expects to find any usage of the [Gatsby browser APIs](https://www.gatsbyjs.org/docs/browser-apis/) (if any). These allow customization/extension of default Gatsby settings affecting the browser. 100 | 101 | 6. **`gatsby-config.js`**: This is the main configuration file for a Gatsby site. This is where you can specify information about your site (metadata) like the site title and description, which Gatsby plugins you’d like to include, etc. (Check out the [config docs](https://www.gatsbyjs.org/docs/gatsby-config/) for more detail). 102 | 103 | 7. **`gatsby-node.js`**: This file is where Gatsby expects to find any usage of the [Gatsby Node APIs](https://www.gatsbyjs.org/docs/node-apis/) (if any). These allow customization/extension of default Gatsby settings affecting pieces of the site build process. 104 | 105 | 8. **`gatsby-ssr.js`**: This file is where Gatsby expects to find any usage of the [Gatsby server-side rendering APIs](https://www.gatsbyjs.org/docs/ssr-apis/) (if any). These allow customization of default Gatsby settings affecting server-side rendering. 106 | 107 | 9. **`LICENSE`**: Gatsby is licensed under the MIT license. 108 | 109 | 10. **`package-lock.json`** (See `package.json` below, first). This is an automatically generated file based on the exact versions of your npm dependencies that were installed for your project. **(You won’t change this file directly).** 110 | 111 | 11. **`package.json`**: A manifest file for Node.js projects, which includes things like metadata (the project’s name, author, etc). This manifest is how npm knows which packages to install for your project. 112 | 113 | 12. **`README.md`**: A text file containing useful reference information about your project. 114 | 115 | ## 🎓 Learning Gatsby 116 | 117 | Looking for more guidance? Full documentation for Gatsby lives [on the website](https://www.gatsbyjs.org/). Here are some places to start: 118 | 119 | - **For most developers, we recommend starting with our [in-depth tutorial for creating a site with Gatsby](https://www.gatsbyjs.org/tutorial/).** It starts with zero assumptions about your level of ability and walks through every step of the process. 120 | 121 | - **To dive straight into code samples, head [to our documentation](https://www.gatsbyjs.org/docs/).** In particular, check out the _Guides_, _API Reference_, and _Advanced Tutorials_ sections in the sidebar. 122 | 123 | ## 💫 Deploy 124 | 125 | [![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/gatsbyjs/gatsby-starter-default) 126 | 127 | -------------------------------------------------------------------------------- /src/pages/about.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | import { graphql } from "gatsby" 4 | import { Progress } from 'rsuite' 5 | const { Line } = Progress 6 | 7 | import Layout from "../components/layout" 8 | import SEO from "../components/seo" 9 | 10 | class About extends React.Component { 11 | render() { 12 | const pageData = this.props.data.cosmicjsPages.metadata 13 | const peopleData = this.props.data.allCosmicjsPeople.edges 14 | const skillData = this.props.data.allCosmicjsSkills.edges 15 | const siteData = this.props.data.cosmicjsSettings.metadata 16 | const contactData = this.props.data.cosmicjsContacts.metadata 17 | const connectData = this.props.data.allCosmicjsConnects.edges 18 | let headerBreakpoint 19 | if (typeof window !== 'undefined') { 20 | headerBreakpoint = window.innerHeight / 3 21 | } 22 | const styles = { 23 | pageHeader: { 24 | padding: '0', 25 | }, 26 | summary: { 27 | width: '25%', 28 | maxWidth: '300px', 29 | paddingRight: '50px', 30 | margin: '0 20px', 31 | textAlign: 'right', 32 | fontSize: '1.5rem', 33 | borderRight: 'thin solid black' 34 | }, 35 | description: { 36 | width: '40%', 37 | marginRight: '30px', 38 | fontSize: '1.0rem' 39 | }, 40 | skills: { 41 | maxWidth: '1000px', 42 | padding: '0 15px', 43 | marginLeft: 'auto', 44 | marginRight: 'auto' 45 | }, 46 | skillDetails: { 47 | width: '90%', 48 | marginTop: '20px', 49 | display: 'flex', 50 | flexDirection: 'row', 51 | justifyContent: 'center', 52 | alignItems: 'center', 53 | }, 54 | skillName: { 55 | width: '200px', 56 | marginRight: '50px', 57 | borderRight: 'thin solid black', 58 | }, 59 | skillDescription: { 60 | maxWidth: '300px', 61 | }, 62 | person: { 63 | width: '25%', 64 | padding: '10px', 65 | display: 'flex', 66 | flexDirection: 'column', 67 | justifyContent: 'center', 68 | alignItems: 'center', 69 | textDecoration: 'none' 70 | }, 71 | personName: { 72 | marginTop: '0', 73 | color: 'black', 74 | fontSize: '1rem' 75 | }, 76 | personTitle: { 77 | color: 'grey', 78 | fontSize: '0.8rem', 79 | } 80 | } 81 | if (pageData.splash_image) { 82 | styles.pageHeader.background = `url(${pageData.splash_image.url})` 83 | styles.pageHeader.backgroundSize = 'cover' 84 | styles.pageHeader.backgroundPosition = 'center' 85 | } 86 | 87 | return ( 88 | 95 | 96 |
97 |
98 |
99 |

Who We Are

100 | {pageData.splash_phrase 101 | ?

{pageData.splash_phrase}

102 | : null 103 | } 104 |
105 |
106 |
107 |

{pageData.intro_summary}

108 |

{pageData.intro_description}

109 |
110 |
111 | {skillData.map(skill => ( 112 |
113 |
114 |

{skill.node.title}

115 |

{skill.node.metadata.description}

116 |
117 | 122 |
123 | ))} 124 |
125 |
126 |
127 | {peopleData.map(person => ( 128 |
129 |
139 |
{person.node.title}
140 |
{person.node.metadata.job_title}
141 |
142 | ))} 143 |
144 |
145 |
146 |
147 | ) 148 | } 149 | } 150 | 151 | export const query = graphql` 152 | query About { 153 | cosmicjsPages(slug: { eq: "about" }) { 154 | metadata { 155 | splash_image { 156 | url 157 | } 158 | splash_phrase 159 | intro_description 160 | intro_summary 161 | } 162 | } 163 | allCosmicjsPeople { 164 | edges { 165 | node { 166 | title 167 | metadata { 168 | image { 169 | url 170 | } 171 | job_title 172 | } 173 | } 174 | } 175 | } 176 | allCosmicjsConnects { 177 | edges { 178 | node { 179 | title 180 | metadata { 181 | url 182 | } 183 | } 184 | } 185 | } 186 | allCosmicjsSkills { 187 | edges { 188 | node { 189 | title 190 | metadata { 191 | progress 192 | description 193 | } 194 | } 195 | } 196 | } 197 | cosmicjsContacts(slug: {eq: "company-footer"}) { 198 | metadata { 199 | address1 200 | address2 201 | postal_code 202 | city 203 | region 204 | country_code 205 | email 206 | phone_number 207 | } 208 | } 209 | cosmicjsSettings(slug: { eq: "site-data" }) { 210 | metadata { 211 | site_title 212 | site_logo { 213 | url 214 | } 215 | } 216 | } 217 | } 218 | ` 219 | 220 | About.propTypes = { 221 | data: PropTypes.object, 222 | pageContext: PropTypes.object.isRequired, 223 | } 224 | 225 | export default About -------------------------------------------------------------------------------- /src/pages/work.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from 'prop-types' 3 | import { graphql } from "gatsby" 4 | 5 | import { Icon, IconButton } from 'rsuite' 6 | import Layout from "../components/layout" 7 | import SEO from "../components/seo" 8 | 9 | class Work extends React.Component { 10 | constructor() { 11 | super() 12 | this.state = { 13 | activeIndex: null 14 | } 15 | this.handleServiceClick = this.handleServiceClick.bind(this) 16 | } 17 | 18 | render() { 19 | const pageData = this.props.data.cosmicjsPages.metadata 20 | const serviceData = this.props.data.allCosmicjsServices.edges 21 | const clientData = this.props.data.allCosmicjsClients.edges 22 | const contactData = this.props.data.cosmicjsContacts.metadata 23 | const connectData = this.props.data.allCosmicjsConnects.edges 24 | const siteData = this.props.data.cosmicjsSettings.metadata 25 | let headerBreakpoint 26 | if (typeof window !== 'undefined') { 27 | headerBreakpoint = window.innerHeight / 3 28 | } 29 | const styles = { 30 | pageHeader: { 31 | padding: '0', 32 | }, 33 | header: { 34 | display: 'flex', 35 | flexDirection: 'row', 36 | justifyContent: 'center', 37 | alignItems: 'center', 38 | }, 39 | headerText: { 40 | fontSize: '2.5rem', 41 | padding: '20px', 42 | borderBottom: 'thin solid black', 43 | }, 44 | serviceList: { 45 | width: '80vw', 46 | flexDirection: 'row', 47 | justifyContent: 'center', 48 | flexWrap: 'wrap', 49 | }, 50 | clientList: { 51 | width: '70%', 52 | margin: '0 auto', 53 | display: 'flex', 54 | flexDirection: 'row', 55 | justifyContent: 'center', 56 | alignItems: 'center', 57 | flexWrap: 'wrap' 58 | }, 59 | clientItem: { 60 | width: '150px', 61 | height: '150px', 62 | margin: '20px', 63 | display: 'flex', 64 | flexDirection: 'column', 65 | alignItems: 'center', 66 | textDecoration: 'none', 67 | color: 'black' 68 | }, 69 | clientImage: { 70 | width: '75%', 71 | margin: '10px auto', 72 | }, 73 | serviceContainer: (i) => { 74 | if (this.state.activeIndex === i) { 75 | return { 76 | height: 'auto', 77 | width: "25%", 78 | display: 'flex', 79 | flexDirection: 'row', 80 | justifyContent: 'center', 81 | cursor: 'pointer', 82 | boxShadow: '0 0 2px gray', 83 | } 84 | } else { 85 | return { 86 | height: '200px', 87 | width: "25%", 88 | display: 'flex', 89 | flexDirection: 'row', 90 | justifyContent: 'center', 91 | cursor: 'pointer', 92 | } 93 | } 94 | }, 95 | serviceExtra: { 96 | margin: '30px auto', 97 | display: 'flex', 98 | flexDirection: 'column', 99 | justifyContent: 'space-between', 100 | alignItems: 'center', 101 | }, 102 | serviceDetails: { 103 | padding: '15px', 104 | display: 'flex', 105 | flexDirection: 'column', 106 | justifyContent: 'flex-start', 107 | alignItems: 'flex-start', 108 | }, 109 | summary: { 110 | width: '20%', 111 | maxWidth: '300px', 112 | paddingRight: '50px', 113 | margin: '0 20px', 114 | textAlign: 'right', 115 | fontSize: '1.5rem', 116 | borderRight: 'thin solid black' 117 | }, 118 | description: { 119 | width: '40%', 120 | marginRight: '30px', 121 | fontSize: '1.0rem' 122 | }, 123 | detailsName: { 124 | fontSize: '1.3rem', 125 | }, 126 | detailsDesc: { 127 | fontSize: '0.9rem', 128 | }, 129 | } 130 | if (pageData.splash_image) { 131 | styles.pageHeader.background = `url(${pageData.splash_image.url})` 132 | styles.pageHeader.backgroundSize = 'cover' 133 | styles.pageHeader.backgroundPosition = 'center' 134 | } 135 | return ( 136 | 143 | 144 |
145 |
146 |
147 |

What We Do

148 | {pageData.splash_phrase 149 | ?

{pageData.splash_phrase}

150 | : null 151 | } 152 |
153 |
154 |
155 |

{pageData.intro_summary}

156 |

{pageData.intro_description}

157 |
158 |
159 | {serviceData.map(service => ( 160 |
165 |
166 | {service.node.metadata.icon ? this.handleServiceClick(serviceData.indexOf(service))} /> : null} 167 |
this.handleServiceClick(serviceData.indexOf(service))}>{service.node.title}
168 |

this.handleServiceClick(serviceData.indexOf(service))}>{service.node.metadata.summary}

169 | {this.state.activeIndex === serviceData.indexOf(service) 170 | ?
171 |

{service.node.metadata.description}

172 | } 175 | onClick={() => this.handleServiceClick(null)} 176 | /> 177 |
178 | : null 179 | } 180 |
181 |
182 | ))} 183 |
184 |
185 |
186 |

Our Clients

187 |
188 |
189 | {clientData.map(client => ( 190 | 191 |

{client.node.title}

192 | {client.node.title} 193 |
194 | ))} 195 |
196 |
197 |
198 |
199 | ) 200 | } 201 | 202 | handleServiceClick(index) { 203 | this.setState({ activeIndex: index }) 204 | } 205 | } 206 | 207 | export const query = graphql` 208 | query Work { 209 | cosmicjsPages(slug: { eq: "work" }) { 210 | metadata { 211 | splash_image { 212 | url 213 | } 214 | splash_phrase 215 | intro_summary 216 | intro_description 217 | } 218 | } 219 | allCosmicjsServices { 220 | edges { 221 | node { 222 | title 223 | metadata { 224 | icon 225 | summary 226 | description 227 | } 228 | } 229 | } 230 | } 231 | allCosmicjsClients { 232 | edges { 233 | node { 234 | title 235 | metadata { 236 | url 237 | image { 238 | url 239 | } 240 | } 241 | } 242 | } 243 | } 244 | allCosmicjsConnects { 245 | edges { 246 | node { 247 | title 248 | metadata { 249 | url 250 | } 251 | } 252 | } 253 | } 254 | cosmicjsContacts(slug: {eq: "company-footer"}) { 255 | metadata { 256 | address1 257 | address2 258 | postal_code 259 | city 260 | region 261 | country_code 262 | email 263 | phone_number 264 | } 265 | } 266 | cosmicjsSettings(slug: { eq: "site-data" }) { 267 | metadata { 268 | site_title 269 | site_logo { 270 | url 271 | } 272 | } 273 | } 274 | } 275 | ` 276 | 277 | Work.propTypes = { 278 | data: PropTypes.object, 279 | } 280 | 281 | export default Work 282 | -------------------------------------------------------------------------------- /src/pages/index.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import PropTypes from "prop-types" 3 | import { Link, graphql } from "gatsby" 4 | import { Animation, Icon, Input, Button, Message } from 'rsuite' 5 | const { Fade, Collapse } = Animation 6 | 7 | import 'rsuite/dist/styles/rsuite.min.css' 8 | import Layout from "../components/layout" 9 | import SEO from "../components/seo" 10 | import ProjectDisplay from '../components/projectDisplay.js' 11 | 12 | // Home Page 13 | class IndexPage extends React.Component { 14 | constructor() { 15 | super() 16 | this.state = { 17 | workHeight: 0, 18 | showWork: false, 19 | peopleHeight: 0, 20 | showPeople: false, 21 | contactHeight: 0, 22 | showContact: false, 23 | userName: '', 24 | userEmail: '', 25 | userMessage: '', 26 | messageSubject: '', 27 | messageError: false, 28 | } 29 | this.updateDimensions = this.updateDimensions.bind(this) 30 | this.handleScroll = this.handleScroll.bind(this) 31 | this.handleContactForm = this.handleContactForm.bind(this) 32 | this.handleInput = this.handleInput.bind(this) 33 | } 34 | 35 | componentDidMount() { 36 | const workHeight = this.workElement.clientHeight 37 | const peopleHeight = this.peopleElement.clientHeight 38 | const contactHeight = this.contactElement.clientHeight 39 | this.setState({ workHeight, peopleHeight, contactHeight }) 40 | window.addEventListener('scroll', this.handleScroll) 41 | window.addEventListener("resize", this.updateDimensions) 42 | } 43 | componentDidUpdate() { 44 | if (this.state.messageError) { 45 | window.setTimeout(() => this.setState({ messageError: false }), 3000) 46 | } 47 | } 48 | componentWillUnmount() { 49 | window.removeEventListener('scroll', this.handleScroll) 50 | window.removeEventListener("resize", this.updateDimensions) 51 | } 52 | 53 | render() { 54 | const pageData = this.props.data.cosmicjsPages.metadata 55 | const siteData = this.props.data.cosmicjsSettings.metadata 56 | const contactData = this.props.data.cosmicjsContacts.metadata 57 | const connectData = this.props.data.allCosmicjsConnects.edges 58 | const peopleData = this.props.data.allCosmicjsPeople.edges 59 | const serviceData = this.props.data.allCosmicjsServices.edges 60 | const projectData = this.props.data.allCosmicjsProjects.edges 61 | let headerBreakpoint 62 | if (typeof window !== 'undefined') { 63 | headerBreakpoint = window.innerHeight - 125 64 | } 65 | const styles = { 66 | splash: { 67 | background: `#000000`, 68 | display: 'flex', 69 | flexDirection: 'column', 70 | justifyContent: 'center', 71 | alignItems: 'flex-start', 72 | }, 73 | splashPhrase: { 74 | width: '70%', 75 | paddingLeft: '20%', 76 | color: '#ffffff', 77 | }, 78 | work: { 79 | display: 'flex', 80 | flexDirection: 'column', 81 | justifyContent: 'flex-start', 82 | alignItems: 'flex-start', 83 | }, 84 | header: { 85 | display: 'flex', 86 | flexDirection: 'row', 87 | justifyContent: 'flex-start', 88 | alignItems: 'center', 89 | }, 90 | title: { 91 | paddingRight: '50px', 92 | marginRight: '100px', 93 | borderRight: 'thin solid black' 94 | }, 95 | description: { 96 | maxWidth: '400px', 97 | fontSize: '1.25rem', 98 | margin: '0', 99 | }, 100 | contactForm: { 101 | display: 'flex', 102 | flexDirection: 'column', 103 | justifyContent: 'center', 104 | alignItems: 'center', 105 | }, 106 | service: { 107 | height: '250px', 108 | width: '200px', 109 | margin: '50px', 110 | paddingTop: '20px', 111 | display: 'flex', 112 | flexDirection: 'column', 113 | justifyContent: 'flex-start', 114 | alignItems: 'flex-start', 115 | overflowX: 'auto', 116 | color: 'black', 117 | }, 118 | serviceName: { 119 | fontSize: '1.2rem', 120 | }, 121 | serviceDescription: { 122 | fontSize: '0.9rem', 123 | color: '#a9a9a9', 124 | }, 125 | person: { 126 | width: '25%', 127 | padding: '10px', 128 | display: 'flex', 129 | flexDirection: 'column', 130 | justifyContent: 'center', 131 | alignItems: 'center', 132 | textDecoration: 'none' 133 | }, 134 | personName: { 135 | marginTop: '0', 136 | color: 'black', 137 | fontSize: '1rem' 138 | }, 139 | personTitle: { 140 | color: 'grey', 141 | fontSize: '0.8rem', 142 | } 143 | } 144 | if (pageData.splash_image) { 145 | styles.splash.background = `url(${pageData.splash_image.url})` 146 | styles.splash.backgroundSize = `cover` 147 | styles.splash.backgroundRepeat = 'no-repeat' 148 | styles.splash.backgroundPosition = 'center' 149 | } 150 | return ( 151 | 158 | 159 |
160 | {pageData.splash_phrase 161 | ?
162 |

{pageData.splash_phrase}

163 |
164 | : null 165 | } 166 |
167 |
{ this.workElement = el }} 169 | style={styles.work} 170 | className="section-container content work" 171 | > 172 | 173 |
174 |
175 |

What We Do

176 |

{pageData.service_description}

177 |
178 |
179 | {serviceData.map(service => ( 180 | 181 | 182 |
{service.node.title}
183 |

{service.node.metadata.summary}

184 | 185 | ))} 186 |
187 |
188 | {projectData.map(project => ( 189 | 195 | ))} 196 |
197 |
198 |
199 |
200 |
{ this.peopleElement = el }} 202 | className="section-container content people" 203 | > 204 | 205 |
206 |
207 |

Who We Are

208 |

{pageData.people_description}

209 |
210 |
211 | {peopleData.map(person => { 212 | return ( 213 | 214 |
224 |
{person.node.title}
225 |
{person.node.metadata.job_title}
226 | 227 | ) 228 | })} 229 |
230 |
231 | 232 |
233 |
{ this.contactElement = el }} 235 | name="contact" 236 | className="section-container content bottom contact" 237 | > 238 | 239 |
240 |
241 |
242 |

Contact Us

243 |

Fill out the form below if you would like to get a hold of us.

244 |
245 |
246 | 247 | 248 | 249 |
250 | 251 | 252 |
253 | 254 | 262 | 265 |
266 |
267 | 268 |
269 |
270 | ) 271 | } 272 | 273 | updateDimensions() { 274 | this.setState({ 275 | workHeight: this.workElement.clientHeight, 276 | peopleHeight: this.peopleElement.clientHeight, 277 | contactHeight: this.contactElement.clientHeight, 278 | }) 279 | } 280 | 281 | handleScroll() { 282 | if (window.scrollY >= (window.innerHeight / 3) + 100) { 283 | this.setState({ showWork: true }) 284 | } else { 285 | this.setState({ showWork: false }) 286 | } 287 | if (window.scrollY >= ((window.innerHeight + this.state.workHeight) - (window.innerHeight / 3))) { 288 | this.setState({ showPeople: true, showWork: false }) 289 | } else { 290 | this.setState({ showPeople: false }) 291 | } 292 | if (window.scrollY >= ((window.innerHeight + this.state.workHeight + this.state.peopleHeight) - (window.innerHeight / 3))) { 293 | this.setState({ showContact: true, showPeople: false }) 294 | } else { 295 | this.setState({ showContact: false }) 296 | } 297 | } 298 | 299 | handleContactForm(e) { 300 | e.preventDefault() 301 | if (!this.state.userName || !this.state.userEmail || !this.state.messageSubject || !this.state.userMessage) { 302 | this.setState({ messageError: true }) 303 | } else { 304 | window.location.href = ` 305 | mailto:${this.props.data.cosmicjsPages.metadata.contact_email} 306 | ?subject=${this.state.messageSubject} 307 | &body=Name :: ${this.state.userName}%0D%0AEmail :: ${this.state.userEmail}%0D%0ASent From :: ${window.location.href},%0D%0A%0D%0A${this.state.userMessage}` 308 | } 309 | } 310 | 311 | handleInput(value, e) { 312 | const { name } = e.target 313 | this.setState({ [name]: value }) 314 | } 315 | } 316 | 317 | IndexPage.propTypes = { 318 | data: PropTypes.object, 319 | } 320 | 321 | export const query = graphql` 322 | query Index { 323 | cosmicjsPages(slug: { eq: "home" }) { 324 | metadata { 325 | splash_image { 326 | url 327 | } 328 | splash_phrase 329 | contact_email 330 | service_description 331 | people_description 332 | } 333 | } 334 | allCosmicjsPeople { 335 | edges { 336 | node { 337 | title 338 | metadata { 339 | image { 340 | url 341 | } 342 | job_title 343 | } 344 | } 345 | } 346 | } 347 | allCosmicjsServices { 348 | edges { 349 | node { 350 | title 351 | metadata { 352 | icon 353 | description 354 | summary 355 | } 356 | } 357 | } 358 | } 359 | allCosmicjsProjects { 360 | edges { 361 | node { 362 | title 363 | metadata { 364 | date 365 | image { 366 | url 367 | } 368 | gallery 369 | summary 370 | description 371 | } 372 | } 373 | } 374 | } 375 | allCosmicjsConnects { 376 | edges { 377 | node { 378 | title 379 | metadata { 380 | url 381 | } 382 | } 383 | } 384 | } 385 | cosmicjsContacts(slug: {eq: "company-footer"}) { 386 | metadata { 387 | address1 388 | address2 389 | postal_code 390 | city 391 | region 392 | country_code 393 | email 394 | phone_number 395 | } 396 | } 397 | cosmicjsSettings(slug: { eq: "site-data" }) { 398 | metadata { 399 | site_title 400 | site_logo { 401 | url 402 | } 403 | } 404 | } 405 | } 406 | ` 407 | 408 | 409 | export default IndexPage 410 | -------------------------------------------------------------------------------- /src/components/layout.scss: -------------------------------------------------------------------------------- 1 | html { 2 | font-family: sans-serif; 3 | -ms-text-size-adjust: 100%; 4 | -webkit-text-size-adjust: 100%; 5 | } 6 | body { 7 | margin: 0; 8 | -webkit-font-smoothing: antialiased; 9 | -moz-osx-font-smoothing: grayscale; 10 | } 11 | article, 12 | aside, 13 | details, 14 | figcaption, 15 | figure, 16 | footer, 17 | header, 18 | main, 19 | menu, 20 | nav, 21 | section, 22 | summary { 23 | display: block; 24 | } 25 | audio, 26 | canvas, 27 | progress, 28 | video { 29 | display: inline-block; 30 | } 31 | audio:not([controls]) { 32 | display: none; 33 | height: 0; 34 | } 35 | progress { 36 | vertical-align: baseline; 37 | } 38 | [hidden], 39 | template { 40 | display: none; 41 | } 42 | a { 43 | background-color: transparent; 44 | -webkit-text-decoration-skip: objects; 45 | } 46 | a:active, 47 | a:hover { 48 | outline-width: 0; 49 | } 50 | abbr[title] { 51 | border-bottom: none; 52 | text-decoration: underline; 53 | text-decoration: underline dotted; 54 | } 55 | b, 56 | strong { 57 | font-weight: inherit; 58 | font-weight: bolder; 59 | } 60 | dfn { 61 | font-style: italic; 62 | } 63 | h1 { 64 | font-size: 2em; 65 | margin: 0.67em 0; 66 | } 67 | mark { 68 | background-color: #ff0; 69 | color: #000; 70 | } 71 | small { 72 | font-size: 80%; 73 | } 74 | sub, 75 | sup { 76 | font-size: 75%; 77 | line-height: 0; 78 | position: relative; 79 | vertical-align: baseline; 80 | } 81 | sub { 82 | bottom: -0.25em; 83 | } 84 | sup { 85 | top: -0.5em; 86 | } 87 | img { 88 | border-style: none; 89 | } 90 | svg:not(:root) { 91 | overflow: hidden; 92 | } 93 | code, 94 | kbd, 95 | pre, 96 | samp { 97 | font-family: monospace, monospace; 98 | font-size: 1em; 99 | } 100 | figure { 101 | margin: 1em 40px; 102 | } 103 | hr { 104 | box-sizing: content-box; 105 | height: 0; 106 | overflow: visible; 107 | } 108 | button, 109 | input, 110 | optgroup, 111 | select, 112 | textarea { 113 | font: inherit; 114 | margin: 0; 115 | } 116 | optgroup { 117 | font-weight: 700; 118 | } 119 | button, 120 | input { 121 | overflow: visible; 122 | } 123 | button, 124 | select { 125 | text-transform: none; 126 | } 127 | [type="reset"], 128 | [type="submit"], 129 | button, 130 | html [type="button"] { 131 | -webkit-appearance: button; 132 | } 133 | [type="button"]::-moz-focus-inner, 134 | [type="reset"]::-moz-focus-inner, 135 | [type="submit"]::-moz-focus-inner, 136 | button::-moz-focus-inner { 137 | border-style: none; 138 | padding: 0; 139 | } 140 | [type="button"]:-moz-focusring, 141 | [type="reset"]:-moz-focusring, 142 | [type="submit"]:-moz-focusring, 143 | button:-moz-focusring { 144 | outline: 1px dotted ButtonText; 145 | } 146 | fieldset { 147 | border: 1px solid silver; 148 | margin: 0 2px; 149 | padding: 0.35em 0.625em 0.75em; 150 | } 151 | legend { 152 | box-sizing: border-box; 153 | color: inherit; 154 | display: table; 155 | max-width: 100%; 156 | padding: 0; 157 | white-space: normal; 158 | } 159 | textarea { 160 | overflow: auto; 161 | } 162 | [type="checkbox"], 163 | [type="radio"] { 164 | box-sizing: border-box; 165 | padding: 0; 166 | } 167 | [type="number"]::-webkit-inner-spin-button, 168 | [type="number"]::-webkit-outer-spin-button { 169 | height: auto; 170 | } 171 | [type="search"] { 172 | -webkit-appearance: textfield; 173 | outline-offset: -2px; 174 | } 175 | [type="search"]::-webkit-search-cancel-button, 176 | [type="search"]::-webkit-search-decoration { 177 | -webkit-appearance: none; 178 | } 179 | ::-webkit-input-placeholder { 180 | color: inherit; 181 | opacity: 0.54; 182 | } 183 | ::-webkit-file-upload-button { 184 | -webkit-appearance: button; 185 | font: inherit; 186 | } 187 | html { 188 | font: 112.5%/1.45em georgia, serif; 189 | box-sizing: border-box; 190 | overflow-y: scroll; 191 | } 192 | * { 193 | box-sizing: inherit; 194 | } 195 | *:before { 196 | box-sizing: inherit; 197 | } 198 | *:after { 199 | box-sizing: inherit; 200 | } 201 | body { 202 | color: hsla(0, 0%, 0%, 0.8); 203 | // font-family: georgia, serif; 204 | // font-weight: normal; 205 | word-wrap: break-word; 206 | font-kerning: normal; 207 | -moz-font-feature-settings: "kern", "liga", "clig", "calt"; 208 | -ms-font-feature-settings: "kern", "liga", "clig", "calt"; 209 | -webkit-font-feature-settings: "kern", "liga", "clig", "calt"; 210 | font-feature-settings: "kern", "liga", "clig", "calt"; 211 | } 212 | img { 213 | max-width: 100%; 214 | margin-left: 0; 215 | margin-right: 0; 216 | margin-top: 0; 217 | padding-bottom: 0; 218 | padding-left: 0; 219 | padding-right: 0; 220 | padding-top: 0; 221 | margin-bottom: 1.45rem; 222 | } 223 | h1 { 224 | margin-left: 0; 225 | margin-right: 0; 226 | margin-top: 0; 227 | padding-bottom: 0; 228 | padding-left: 0; 229 | padding-right: 0; 230 | padding-top: 0; 231 | margin-bottom: 1.45rem; 232 | color: inherit; 233 | // font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 234 | // Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 235 | // font-weight: bold; 236 | text-rendering: optimizeLegibility; 237 | font-size: 2.25rem; 238 | line-height: 1.1; 239 | } 240 | h2 { 241 | margin-left: 0; 242 | margin-right: 0; 243 | margin-top: 0; 244 | padding-bottom: 0; 245 | padding-left: 0; 246 | padding-right: 0; 247 | padding-top: 0; 248 | margin-bottom: 1.45rem; 249 | color: inherit; 250 | // font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 251 | // Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 252 | // font-weight: bold; 253 | text-rendering: optimizeLegibility; 254 | font-size: 1.62671rem; 255 | line-height: 1.1; 256 | } 257 | h3 { 258 | margin-left: 0; 259 | margin-right: 0; 260 | margin-top: 0; 261 | padding-bottom: 0; 262 | padding-left: 0; 263 | padding-right: 0; 264 | padding-top: 0; 265 | margin-bottom: 1.45rem; 266 | color: inherit; 267 | // font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 268 | // Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 269 | // font-weight: bold; 270 | text-rendering: optimizeLegibility; 271 | font-size: 1.38316rem; 272 | line-height: 1.1; 273 | } 274 | h4 { 275 | margin-left: 0; 276 | margin-right: 0; 277 | margin-top: 0; 278 | padding-bottom: 0; 279 | padding-left: 0; 280 | padding-right: 0; 281 | padding-top: 0; 282 | margin-bottom: 1.45rem; 283 | color: inherit; 284 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 285 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 286 | font-weight: bold; 287 | text-rendering: optimizeLegibility; 288 | font-size: 1rem; 289 | line-height: 1.1; 290 | } 291 | h5 { 292 | margin-left: 0; 293 | margin-right: 0; 294 | margin-top: 0; 295 | padding-bottom: 0; 296 | padding-left: 0; 297 | padding-right: 0; 298 | padding-top: 0; 299 | margin-bottom: 1.45rem; 300 | color: inherit; 301 | // font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 302 | // Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 303 | // font-weight: bold; 304 | text-rendering: optimizeLegibility; 305 | font-size: 0.85028rem; 306 | line-height: 1.1; 307 | } 308 | h6 { 309 | margin-left: 0; 310 | margin-right: 0; 311 | margin-top: 0; 312 | padding-bottom: 0; 313 | padding-left: 0; 314 | padding-right: 0; 315 | padding-top: 0; 316 | margin-bottom: 1.45rem; 317 | color: inherit; 318 | // font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 319 | // Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 320 | // font-weight: bold; 321 | text-rendering: optimizeLegibility; 322 | font-size: 0.78405rem; 323 | line-height: 1.1; 324 | } 325 | hgroup { 326 | margin-left: 0; 327 | margin-right: 0; 328 | margin-top: 0; 329 | padding-bottom: 0; 330 | padding-left: 0; 331 | padding-right: 0; 332 | padding-top: 0; 333 | margin-bottom: 1.45rem; 334 | } 335 | ul { 336 | margin-left: 1.45rem; 337 | margin-right: 0; 338 | margin-top: 0; 339 | padding-bottom: 0; 340 | padding-left: 0; 341 | padding-right: 0; 342 | padding-top: 0; 343 | margin-bottom: 1.45rem; 344 | list-style-position: outside; 345 | list-style-image: none; 346 | } 347 | ol { 348 | margin-left: 1.45rem; 349 | margin-right: 0; 350 | margin-top: 0; 351 | padding-bottom: 0; 352 | padding-left: 0; 353 | padding-right: 0; 354 | padding-top: 0; 355 | margin-bottom: 1.45rem; 356 | list-style-position: outside; 357 | list-style-image: none; 358 | } 359 | dl { 360 | margin-left: 0; 361 | margin-right: 0; 362 | margin-top: 0; 363 | padding-bottom: 0; 364 | padding-left: 0; 365 | padding-right: 0; 366 | padding-top: 0; 367 | margin-bottom: 1.45rem; 368 | } 369 | dd { 370 | margin-left: 0; 371 | margin-right: 0; 372 | margin-top: 0; 373 | padding-bottom: 0; 374 | padding-left: 0; 375 | padding-right: 0; 376 | padding-top: 0; 377 | margin-bottom: 1.45rem; 378 | } 379 | p { 380 | margin-left: 0; 381 | margin-right: 0; 382 | margin-top: 0; 383 | padding-bottom: 0; 384 | padding-left: 0; 385 | padding-right: 0; 386 | padding-top: 0; 387 | margin-bottom: 1.45rem; 388 | } 389 | figure { 390 | margin-left: 0; 391 | margin-right: 0; 392 | margin-top: 0; 393 | padding-bottom: 0; 394 | padding-left: 0; 395 | padding-right: 0; 396 | padding-top: 0; 397 | margin-bottom: 1.45rem; 398 | } 399 | pre { 400 | margin-left: 0; 401 | margin-right: 0; 402 | margin-top: 0; 403 | margin-bottom: 1.45rem; 404 | font-size: 0.85rem; 405 | line-height: 1.42; 406 | background: hsla(0, 0%, 0%, 0.04); 407 | border-radius: 3px; 408 | overflow: auto; 409 | word-wrap: normal; 410 | padding: 1.45rem; 411 | } 412 | table { 413 | margin-left: 0; 414 | margin-right: 0; 415 | margin-top: 0; 416 | padding-bottom: 0; 417 | padding-left: 0; 418 | padding-right: 0; 419 | padding-top: 0; 420 | margin-bottom: 1.45rem; 421 | font-size: 1rem; 422 | line-height: 1.45rem; 423 | border-collapse: collapse; 424 | width: 100%; 425 | } 426 | fieldset { 427 | margin-left: 0; 428 | margin-right: 0; 429 | margin-top: 0; 430 | padding-bottom: 0; 431 | padding-left: 0; 432 | padding-right: 0; 433 | padding-top: 0; 434 | margin-bottom: 1.45rem; 435 | } 436 | blockquote { 437 | margin-left: 1.45rem; 438 | margin-right: 1.45rem; 439 | margin-top: 0; 440 | padding-bottom: 0; 441 | padding-left: 0; 442 | padding-right: 0; 443 | padding-top: 0; 444 | margin-bottom: 1.45rem; 445 | } 446 | form { 447 | margin-left: 0; 448 | margin-right: 0; 449 | margin-top: 0; 450 | padding-bottom: 0; 451 | padding-left: 0; 452 | padding-right: 0; 453 | padding-top: 0; 454 | margin-bottom: 1.45rem; 455 | } 456 | noscript { 457 | margin-left: 0; 458 | margin-right: 0; 459 | margin-top: 0; 460 | padding-bottom: 0; 461 | padding-left: 0; 462 | padding-right: 0; 463 | padding-top: 0; 464 | margin-bottom: 1.45rem; 465 | } 466 | iframe { 467 | margin-left: 0; 468 | margin-right: 0; 469 | margin-top: 0; 470 | padding-bottom: 0; 471 | padding-left: 0; 472 | padding-right: 0; 473 | padding-top: 0; 474 | margin-bottom: 1.45rem; 475 | } 476 | hr { 477 | margin-left: 0; 478 | margin-right: 0; 479 | margin-top: 0; 480 | padding-bottom: 0; 481 | padding-left: 0; 482 | padding-right: 0; 483 | padding-top: 0; 484 | margin-bottom: calc(1.45rem - 1px); 485 | background: hsla(0, 0%, 0%, 0.2); 486 | border: none; 487 | height: 1px; 488 | } 489 | address { 490 | margin-left: 0; 491 | margin-right: 0; 492 | margin-top: 0; 493 | padding-bottom: 0; 494 | padding-left: 0; 495 | padding-right: 0; 496 | padding-top: 0; 497 | margin-bottom: 1.45rem; 498 | } 499 | b { 500 | font-weight: bold; 501 | } 502 | strong { 503 | font-weight: bold; 504 | } 505 | dt { 506 | font-weight: bold; 507 | } 508 | th { 509 | font-weight: bold; 510 | } 511 | li { 512 | margin-bottom: calc(1.45rem / 2); 513 | } 514 | ol li { 515 | padding-left: 0; 516 | } 517 | ul li { 518 | padding-left: 0; 519 | } 520 | li > ol { 521 | margin-left: 1.45rem; 522 | margin-bottom: calc(1.45rem / 2); 523 | margin-top: calc(1.45rem / 2); 524 | } 525 | li > ul { 526 | margin-left: 1.45rem; 527 | margin-bottom: calc(1.45rem / 2); 528 | margin-top: calc(1.45rem / 2); 529 | } 530 | blockquote *:last-child { 531 | margin-bottom: 0; 532 | } 533 | li *:last-child { 534 | margin-bottom: 0; 535 | } 536 | p *:last-child { 537 | margin-bottom: 0; 538 | } 539 | li > p { 540 | margin-bottom: calc(1.45rem / 2); 541 | } 542 | code { 543 | font-size: 0.85rem; 544 | line-height: 1.45rem; 545 | } 546 | kbd { 547 | font-size: 0.85rem; 548 | line-height: 1.45rem; 549 | } 550 | samp { 551 | font-size: 0.85rem; 552 | line-height: 1.45rem; 553 | } 554 | abbr { 555 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); 556 | cursor: help; 557 | } 558 | acronym { 559 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); 560 | cursor: help; 561 | } 562 | abbr[title] { 563 | border-bottom: 1px dotted hsla(0, 0%, 0%, 0.5); 564 | cursor: help; 565 | text-decoration: none; 566 | } 567 | thead { 568 | text-align: left; 569 | } 570 | td, 571 | th { 572 | text-align: left; 573 | border-bottom: 1px solid hsla(0, 0%, 0%, 0.12); 574 | font-feature-settings: "tnum"; 575 | -moz-font-feature-settings: "tnum"; 576 | -ms-font-feature-settings: "tnum"; 577 | -webkit-font-feature-settings: "tnum"; 578 | padding-left: 0.96667rem; 579 | padding-right: 0.96667rem; 580 | padding-top: 0.725rem; 581 | padding-bottom: calc(0.725rem - 1px); 582 | } 583 | th:first-child, 584 | td:first-child { 585 | padding-left: 0; 586 | } 587 | th:last-child, 588 | td:last-child { 589 | padding-right: 0; 590 | } 591 | tt, 592 | code { 593 | background-color: hsla(0, 0%, 0%, 0.04); 594 | border-radius: 3px; 595 | font-family: "SFMono-Regular", Consolas, "Roboto Mono", "Droid Sans Mono", 596 | "Liberation Mono", Menlo, Courier, monospace; 597 | padding: 0; 598 | padding-top: 0.2em; 599 | padding-bottom: 0.2em; 600 | } 601 | pre code { 602 | background: none; 603 | line-height: 1.42; 604 | } 605 | code:before, 606 | code:after, 607 | tt:before, 608 | tt:after { 609 | letter-spacing: -0.2em; 610 | content: " "; 611 | } 612 | pre code:before, 613 | pre code:after, 614 | pre tt:before, 615 | pre tt:after { 616 | content: ""; 617 | } 618 | .section-container { 619 | width: 100%; 620 | min-height: 100vh; 621 | margin-bottom: 100px; 622 | display: flex; 623 | flex-direction: column; 624 | justify-content: center; 625 | 626 | input, textarea, button { 627 | margin: 15px 0 0 15px; 628 | } 629 | } 630 | .section-container.medium { 631 | min-height: 400px; 632 | margin-left: auto; 633 | margin-right: auto; 634 | } 635 | .section-container.short { 636 | padding-top: 30px; 637 | min-height: 200px; 638 | } 639 | .section-container.row{ 640 | flex-direction: row; 641 | justify-content: center; 642 | align-items: center; 643 | } 644 | .section-container.bottom { 645 | min-height: 60vh; 646 | max-height: 60vh; 647 | } 648 | .content { 649 | max-width: 1000px; 650 | margin-left: auto; 651 | margin-right: auto; 652 | } 653 | .page-container { 654 | width: 100%; 655 | min-height: calc(100vh - 100px); 656 | } 657 | .page-header { 658 | height: 400px; 659 | margin: 0 auto !important; 660 | background-color: #000000; 661 | display: flex; 662 | flex-direction: column; 663 | justify-content: center; 664 | 665 | h3 { 666 | margin: 0; 667 | font-size: 300%; 668 | text-align: center; 669 | } 670 | } 671 | .section-wrapper { 672 | padding: 20px; 673 | width: 100%; 674 | } 675 | .wrapper-content { 676 | width: 100%; 677 | min-height: 30%; 678 | display: flex; 679 | flex-direction: row; 680 | justify-content: flex-start; 681 | align-items: center; 682 | flex-wrap: wrap; 683 | } 684 | .wrapper-content.services { 685 | justify-content: center; 686 | } 687 | .wrapper-content.projects { 688 | width: 75vw; 689 | height: auto; 690 | margin-left: calc(-37.5vw + 480px); 691 | justify-content: center; 692 | } 693 | .section-title { 694 | font-size: 2.5rem; 695 | margin: 50px; 696 | } 697 | .page-header-description { 698 | font-size: 1rem; 699 | width: 50%; 700 | max-width: 600px; 701 | text-align: center; 702 | } 703 | .header-filter { 704 | background-color: rgba(0,0,0,0.6); 705 | color: white; 706 | height: 100%; 707 | display: flex; 708 | flex-direction: column; 709 | justify-content: center; 710 | align-items: center; 711 | } 712 | 713 | .service-link { 714 | .rs-icon { 715 | margin-bottom: 20px; 716 | } 717 | } 718 | 719 | .project-gallery { 720 | max-width: 1300px; 721 | margin: 50px auto; 722 | display: flex; 723 | flex-direction: row; 724 | justify-content: center; 725 | align-items: center; 726 | flex-wrap: wrap; 727 | } 728 | 729 | .rs-navbar-header { 730 | h1 { 731 | margin-top: 20px; 732 | } 733 | } 734 | .rs-nav-item { 735 | margin: 0; 736 | text-shadow: 0px 0px 0.7px white; 737 | } 738 | .rs-nav-item-content { 739 | font-size: 1rem !important; 740 | color: #777777 !important; 741 | } 742 | .rs-nav-item.active span { 743 | color: #34c3ff; 744 | } 745 | 746 | @media only screen and (max-width: 480px) { 747 | html { 748 | font-size: 100%; 749 | } 750 | } 751 | --------------------------------------------------------------------------------