├── .eslintrc ├── .firebaserc ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── firebase.json ├── package-lock.json ├── package.json ├── preact.config.js └── src ├── assets ├── favicon.ico ├── icons │ ├── android-chrome-192x192.png │ ├── android-chrome-256x256.png │ ├── android-chrome-512x512.png │ ├── apple-touch-icon-120x120.png │ ├── apple-touch-icon-152x152.png │ ├── apple-touch-icon-180x180.png │ ├── apple-touch-icon-60x60.png │ ├── apple-touch-icon-76x76.png │ ├── apple-touch-icon.png │ ├── browserconfig.xml │ ├── mstile-150x150.png │ ├── safari-pinned-tab.svg │ └── site.webmanifest └── scripts │ └── analytics.js ├── components ├── card-scroll │ ├── card-scroll.component.js │ ├── card-scroll.style.js │ └── index.js ├── card │ ├── card.component.js │ ├── card.style.js │ └── index.js ├── footer │ ├── footer.component.js │ ├── footer.style.js │ └── index.js ├── header │ ├── header.component.js │ ├── header.style.js │ └── index.js ├── hero │ ├── hero.component.js │ ├── hero.style.js │ └── index.js ├── index.js ├── section │ ├── index.js │ ├── section.component.js │ └── section.style.js ├── sub-hero │ ├── index.js │ ├── sub-hero.component.js │ └── sub-hero.style.js ├── switch │ ├── index.js │ ├── switch.component.js │ └── switch.style.js └── tooltip │ ├── index.js │ ├── tooltip.component.js │ └── tooltip.style.js ├── core ├── colors.js └── index.js ├── extract-critical.js ├── icons ├── change-colors.js ├── check.js ├── code.js ├── framework.js ├── icon-wrapper │ ├── icon-wrapper.component.js │ └── index.js ├── index.js ├── laptop.js ├── list.js ├── logo.js ├── package.js └── terminal.js ├── index.html ├── index.js ├── manifest.json ├── shared ├── index.js ├── shared.style.js └── spacing.style.js ├── template.js └── tools ├── index.js └── types.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint-config-synacor", 3 | "rules": { 4 | "indent": ["error", 2], 5 | "react/jsx-indent-props": [4, "space"], 6 | "brace-style": [2, "1tbs"] 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "progressive-tooling" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /build 3 | /*.log 4 | *.DS_Store 5 | .idea/ 6 | stats.json -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "8.11" 4 | 5 | branches: 6 | only: 7 | - master 8 | 9 | before_script: 10 | - npm install -g preact-cli 11 | 12 | script: 13 | - npm run build 14 | 15 | after_success: 16 | - firebase deploy --token $FIREBASE_TOKEN 17 | 18 | notifications: 19 | email: 20 | on_failure: change -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributions 2 | 3 | We'd love to accept any PRs, suggestions, issues, or contributions to this project! There are just a few small things you need to do first. 4 | 5 | ## Contributor License Agreement 6 | 7 | Contributions to this project must be accompanied by a Contributor License Agreement. You (or your employer) retain the copyright to your contribution; this simply gives us permission to use and redistribute your contributions as part of the project. Head over to to see your current agreements on file or to sign a new one. 8 | 9 | You generally only need to submit a CLA once, so if you've already submitted one (even if it was for a different project), you probably don't need to do it again. 10 | 11 | ## What should I contribute? 12 | 13 | Once you've submitted a CLA, please feel free to put up a PR adding any third-party tools to the `src/tools/index.json` file. If you would like to modify anything else with the site (including adding newer tool categories), please put up an issue first so we can chat about it! 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2018 Google Inc. 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Progressive Tooling 4 | 5 |

6 | 7 |

8 | View App 9 |

10 | 11 | ## What is this? 12 | 13 | A small application that shows a list of community-built, third-party tools that you can use to improve the performance of your webpages. 14 | 15 | ## What is this built with? 16 | 17 | - [preact-cli](https://github.com/developit/preact-cli) 18 | - [Emotion](https://emotion.sh/) for styling (with theming) 19 | - [Firebase](https://firebase.google.com/) for hosting 20 | 21 | ## Can I contribute? 22 | 23 | Of course you can! Contributions are always welcome. Please take a look at [CONTRIBUTING](./CONTRIBUTING.md). 24 | -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "build", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "progressive-tooling", 4 | "version": "0.0.0", 5 | "license": "MIT", 6 | "scripts": { 7 | "start": "if-env NODE_ENV=production && npm run -s serve || npm run -s dev", 8 | "build": "preact build --template src/index.html", 9 | "serve": "preact build --template src/index.html && preact serve", 10 | "dev": "preact watch --template src/index.html", 11 | "lint": "eslint src" 12 | }, 13 | "eslintConfig": { 14 | "extends": "eslint-config-synacor" 15 | }, 16 | "eslintIgnore": [ 17 | "build/*" 18 | ], 19 | "devDependencies": { 20 | "babel-plugin-emotion": "^9.1.2", 21 | "eslint": "^4.5.0", 22 | "eslint-config-synacor": "^1.1.0", 23 | "if-env": "^1.0.0", 24 | "preact-cli": "^2.0.0", 25 | "preact-cli-workbox-plugin": "^1.1.1" 26 | }, 27 | "dependencies": { 28 | "emotion": "^9.1.2", 29 | "emotion-theming": "^9.1.2", 30 | "preact": "^8.2.1", 31 | "preact-compat": "^3.17.0", 32 | "preact-emotion": "^9.1.2" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /preact.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | const { resolve } = require('path'); 18 | import { generateSw } from 'preact-cli-workbox-plugin'; 19 | 20 | /** 21 | * Function that mutates original webpack config. 22 | * Supports asynchronous changes when promise is returned. 23 | * 24 | * @param {object} config original webpack config. 25 | * @param {object} env options passed to CLI. 26 | * @param {WebpackConfigHelpers} helpers object with useful helpers when working with config. 27 | **/ 28 | export default function(config, env, helpers) { 29 | let { rule } = helpers.getLoadersByName(config, 'babel-loader')[0]; 30 | let babelConfig = rule.options; 31 | 32 | babelConfig.plugins.push('emotion'); 33 | 34 | config.resolve.alias.src = resolve(__dirname, 'src'); 35 | 36 | const workboxConfig = { 37 | include: [/\.html$/, /\.js$/, /\.css$/, /\.png$/] 38 | }; 39 | 40 | return generateSw(config, helpers, workboxConfig); 41 | } 42 | -------------------------------------------------------------------------------- /src/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/progressive-tooling/8d463bf94be3a974a1d03c6aac8747a59de5a065/src/assets/favicon.ico -------------------------------------------------------------------------------- /src/assets/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/progressive-tooling/8d463bf94be3a974a1d03c6aac8747a59de5a065/src/assets/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /src/assets/icons/android-chrome-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/progressive-tooling/8d463bf94be3a974a1d03c6aac8747a59de5a065/src/assets/icons/android-chrome-256x256.png -------------------------------------------------------------------------------- /src/assets/icons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/progressive-tooling/8d463bf94be3a974a1d03c6aac8747a59de5a065/src/assets/icons/android-chrome-512x512.png -------------------------------------------------------------------------------- /src/assets/icons/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/progressive-tooling/8d463bf94be3a974a1d03c6aac8747a59de5a065/src/assets/icons/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /src/assets/icons/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/progressive-tooling/8d463bf94be3a974a1d03c6aac8747a59de5a065/src/assets/icons/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /src/assets/icons/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/progressive-tooling/8d463bf94be3a974a1d03c6aac8747a59de5a065/src/assets/icons/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /src/assets/icons/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/progressive-tooling/8d463bf94be3a974a1d03c6aac8747a59de5a065/src/assets/icons/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /src/assets/icons/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/progressive-tooling/8d463bf94be3a974a1d03c6aac8747a59de5a065/src/assets/icons/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /src/assets/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/progressive-tooling/8d463bf94be3a974a1d03c6aac8747a59de5a065/src/assets/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /src/assets/icons/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #ffffff 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/assets/icons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GoogleChromeLabs/progressive-tooling/8d463bf94be3a974a1d03c6aac8747a59de5a065/src/assets/icons/mstile-150x150.png -------------------------------------------------------------------------------- /src/assets/icons/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 17 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/assets/icons/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "P-Tooling", 3 | "short_name": "P-Tooling", 4 | "icons": [ 5 | { 6 | "src": "/src/assets/icons/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | } 10 | ], 11 | "theme_color": "#8e44ad", 12 | "background_color": "#8e44ad", 13 | "display": "standalone" 14 | } 15 | -------------------------------------------------------------------------------- /src/assets/scripts/analytics.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | window.ga = 18 | window.ga || 19 | function() { 20 | (ga.q = ga.q || []).push(arguments); 21 | }; 22 | ga('create', 'UA-123528826-1', 'auto'); 23 | ga('set', 'transport', 'beacon'); 24 | ga('send', 'pageview'); 25 | -------------------------------------------------------------------------------- /src/components/card-scroll/card-scroll.component.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h } from 'preact'; 18 | 19 | import { Card } from 'src/components'; 20 | 21 | import { ScrollContainerDiv, ContainerDiv } from './card-scroll.style'; 22 | 23 | export const CardScroll = ({ tools, horizontalScroll }) => { 24 | const ContainerComponent = horizontalScroll 25 | ? ScrollContainerDiv 26 | : ContainerDiv; 27 | 28 | return ( 29 | 30 | {tools.map(({ title, description, link, type }) => ( 31 | 38 | ))} 39 | 40 | ); 41 | }; 42 | -------------------------------------------------------------------------------- /src/components/card-scroll/card-scroll.style.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import styled from 'preact-emotion'; 18 | 19 | import { forPhoneOnly } from 'src/shared'; 20 | 21 | export const ScrollContainerDiv = styled('div')` 22 | display: flex; 23 | overflow-x: scroll; 24 | overflow-y: hidden; 25 | min-width: 103%; 26 | -webkit-overflow-scrolling: touch; 27 | -webkit-scroll-snap-type: mandatory; 28 | scroll-snap-type: x mandatory; 29 | -webkit-scroll-snap-points-x: repeat(100%); 30 | scroll-snap-points-x: repeat(100%); 31 | padding: 0 0 30px 0; 32 | 33 | ${forPhoneOnly} { 34 | min-width: 110%; 35 | } 36 | `; 37 | 38 | export const ContainerDiv = styled('div')` 39 | display: flex; 40 | flex-direction: column; 41 | `; 42 | -------------------------------------------------------------------------------- /src/components/card-scroll/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | export { CardScroll } from './card-scroll.component'; 18 | -------------------------------------------------------------------------------- /src/components/card/card.component.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h, createElement } from 'preact'; 18 | import { withTheme } from 'emotion-theming'; 19 | 20 | import { 21 | CardContainerDiv, 22 | CardHeaderDiv, 23 | TitleA, 24 | ContentDiv, 25 | LinkA, 26 | InfoDiv, 27 | InfoIconsDiv, 28 | DescriptionDiv, 29 | InfoDivLarge 30 | } from './card.style'; 31 | 32 | import { 33 | CheckSvg, 34 | CodeSvg, 35 | FrameworkSvg, 36 | LaptopSvg, 37 | PackageSvg, 38 | TerminalSvg 39 | } from 'src/icons'; 40 | 41 | import { Tooltip } from '../tooltip'; 42 | 43 | const ICONS = { 44 | api: CodeSvg, 45 | CI: CheckSvg, 46 | CLI: TerminalSvg, 47 | dependency: PackageSvg, 48 | external: LaptopSvg, 49 | framework: FrameworkSvg 50 | }; 51 | 52 | const ICON_VIEW_BOX = { 53 | CLI: '0 0 15 16', 54 | dependency: '0 0 1000 900' 55 | }; 56 | 57 | const getIcons = ({ type, path, theme, fullCard, pointing }) => 58 | type.map(({ key, path, title }) => 59 | createElement( 60 | Tooltip, 61 | { key, title, pointing }, 62 | createElement( 63 | ICONS[path], 64 | { 65 | viewBox: ICON_VIEW_BOX[path], 66 | size: fullCard ? 40 : 25, 67 | color: theme 68 | }, 69 | null 70 | ) 71 | ) 72 | ); 73 | 74 | const CardComponent = ({ title, description, link, type, fullCard, theme }) => ( 75 | 76 | 77 | 78 | 79 | {title} 80 | 81 | 82 | {fullCard && {description}} 83 | 84 | {!fullCard && {description}} 85 | {fullCard && ( 86 | 87 | {getIcons({ 88 | type, 89 | fullCard, 90 | theme: theme.tertiary, 91 | pointing: 'top left' 92 | })} 93 | 94 | )} 95 | {!fullCard && ( 96 | 97 | 98 | {getIcons({ 99 | type, 100 | fullCard, 101 | theme: theme.tertiary, 102 | pointing: 'top right' 103 | })} 104 | 105 | 106 | View 107 | 108 | 109 | )} 110 | 111 | ); 112 | 113 | export const Card = withTheme(CardComponent); 114 | -------------------------------------------------------------------------------- /src/components/card/card.style.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import styled from 'preact-emotion'; 18 | 19 | import { 20 | forPhoneOnly, 21 | forTabletPortraitUp, 22 | forSmallDesktopUp, 23 | forDesktopUp, 24 | forLargeDesktopUp, 25 | growStyle 26 | } from 'src/shared'; 27 | 28 | export const cardsInViewportPhone = 1; 29 | export const cardsInViewportTablet = 2; 30 | export const cardsInViewportSmallDesktop = 3; 31 | export const cardsInViewportDesktop = 4; 32 | 33 | export const CardContainerDiv = styled('div')` 34 | background: ${props => props.theme.backgroundPrimary}; 35 | padding: 20px; 36 | margin: ${props => props.fullCard && '0 0 30px'}; 37 | border-radius: 5px; 38 | height: ${props => !props.fullCard && '200px'}; 39 | min-width: 400px; 40 | width: 400px; 41 | position: relative; 42 | border: 2px solid ${props => props.theme.backgroundSecondary}; 43 | display: ${props => props.fullCard && 'flex'}; 44 | justify-content: ${props => props.fullCard && 'space-between'}; 45 | align-items: ${props => props.fullCard && 'center'}; 46 | 47 | ${forPhoneOnly} { 48 | margin: ${props => !props.fullCard && '0 10px'}; 49 | height: ${props => !props.fullCard && '250px'}; 50 | min-width: ${props => 51 | !props.fullCard 52 | ? `calc(100vw - 7rem / ${cardsInViewportPhone})` 53 | : '100%'}; 54 | width: ${props => 55 | !props.fullCard 56 | ? `calc(100vw - 7rem / ${cardsInViewportPhone})` 57 | : '100%'}; 58 | display: flex; 59 | flex-direction: column; 60 | justify-content: space-between; 61 | align-items: center; 62 | } 63 | 64 | ${forTabletPortraitUp} { 65 | margin-right: ${props => !props.fullCard && '20px'}; 66 | min-width: ${props => 67 | !props.fullCard 68 | ? `calc((100vw - 6rem - 35px) / ${cardsInViewportTablet})` 69 | : '100%'}; 70 | width: ${props => 71 | !props.fullCard 72 | ? `calc((100vw - 6rem - 35px) / ${cardsInViewportTablet})` 73 | : '100%'}; 74 | } 75 | 76 | ${forSmallDesktopUp} { 77 | margin-right: ${props => !props.fullCard && '30px'}; 78 | min-width: ${props => 79 | !props.fullCard 80 | ? `calc((100vw - 6rem - 80px) / ${cardsInViewportSmallDesktop})` 81 | : '100%'}; 82 | width: ${props => 83 | !props.fullCard 84 | ? `calc((100vw - 6rem - 80px) / ${cardsInViewportSmallDesktop})` 85 | : '100%'}; 86 | } 87 | 88 | ${forDesktopUp} { 89 | margin-right: ${props => !props.fullCard && '30px'}; 90 | min-width: ${props => 91 | !props.fullCard 92 | ? `calc((100vw - 12rem - 110px) / ${cardsInViewportDesktop})` 93 | : '100%'}; 94 | width: ${props => 95 | !props.fullCard 96 | ? `calc((100vw - 12rem - 110px) / ${cardsInViewportDesktop})` 97 | : '100%'}; 98 | } 99 | 100 | ${forLargeDesktopUp} { 101 | margin-right: ${props => !props.fullCard && '30px'}; 102 | min-width: ${props => 103 | !props.fullCard 104 | ? `calc((100vw - 12rem - 160px) / ${cardsInViewportDesktop})` 105 | : '100%'}; 106 | width: ${props => 107 | !props.fullCard 108 | ? `calc((100vw - 12rem - 160px) / ${cardsInViewportDesktop})` 109 | : '100%'}; 110 | } 111 | `; 112 | 113 | export const DescriptionDiv = styled('div')` 114 | display: flex; 115 | flex-direction: column; 116 | `; 117 | 118 | export const CardHeaderDiv = styled('div')` 119 | align-items: center; 120 | display: flex; 121 | justify-content: flex-start; 122 | margin-bottom: ${props => (props.extraSpacing ? '20px' : '15px')}; 123 | 124 | ${forPhoneOnly} { 125 | justify-content: center; 126 | margin-bottom: 0; 127 | } 128 | `; 129 | 130 | export const TitleA = styled('a')` 131 | font-size: ${props => (props.large ? '24px' : '18px')}; 132 | margin: 0; 133 | font-weight: 600; 134 | color: ${props => props.theme.backgroundSecondary}; 135 | overflow-wrap: break-word; 136 | text-decoration: none; 137 | border-bottom: ${props => `2px solid ${props.theme.backgroundSecondary}`}; 138 | ${growStyle}; 139 | `; 140 | 141 | export const ContentDiv = styled('div')` 142 | font-size: ${props => (props.large ? '19px' : '16px')}; 143 | font-weight: 500; 144 | color: ${props => props.theme.primary}; 145 | 146 | ${forPhoneOnly} { 147 | text-align: center; 148 | } 149 | `; 150 | 151 | export const InfoDiv = styled('div')` 152 | width: 100%; 153 | display: flex; 154 | align-items: center; 155 | justify-content: space-between; 156 | 157 | ${forTabletPortraitUp} { 158 | position: absolute; 159 | width: 100%; 160 | bottom: 0; 161 | left: 0; 162 | padding: 15px; 163 | } 164 | `; 165 | 166 | export const IconsDiv = styled('div')` 167 | display: flex; 168 | align-items: center; 169 | `; 170 | 171 | export const InfoIconsDiv = styled(IconsDiv)` 172 | div { 173 | margin-right: 10px; 174 | } 175 | `; 176 | 177 | export const InfoDivLarge = styled(IconsDiv)` 178 | div { 179 | margin-left: 15px; 180 | } 181 | `; 182 | 183 | export const LinkA = styled('a')` 184 | background-color: ${props => props.theme.tertiary}; 185 | border: none; 186 | color: ${props => props.theme.secondary}; 187 | font-weight: 600; 188 | padding: 6px 12px; 189 | border-radius: 5px; 190 | text-align: center; 191 | -webkit-text-decoration: none; 192 | text-decoration: none; 193 | display: inline-block; 194 | font-size: 14px; 195 | bottom: 15px; 196 | right: 15px; 197 | cursor: pointer; 198 | ${growStyle} ${forPhoneOnly} { 199 | position: initial; 200 | width: 100px; 201 | } 202 | `; 203 | -------------------------------------------------------------------------------- /src/components/card/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | export { Card } from './card.component'; 18 | export { 19 | cardsInViewportPhone, 20 | cardsInViewportTablet, 21 | cardsInViewportSmallDesktop, 22 | cardsInViewportDesktop 23 | } from './card.style'; 24 | -------------------------------------------------------------------------------- /src/components/footer/footer.component.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h } from 'preact'; 18 | 19 | import { FooterDiv, LinkA } from './footer.style'; 20 | 21 | export const Footer = () => ( 22 | 23 | 28 | Show this project some ❤ 29 | 30 | 31 | ); 32 | -------------------------------------------------------------------------------- /src/components/footer/footer.style.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import styled from 'preact-emotion'; 18 | 19 | import { forPhoneOnly, growStyle } from 'src/shared'; 20 | 21 | export const FooterDiv = styled('div')` 22 | display: flex; 23 | justify-content: center; 24 | align-items: center; 25 | height: 90px; 26 | background-color: ${props => props.theme.backgroundSecondary}; 27 | border-top: 1px solid ${props => props.theme.primary}; 28 | 29 | ${forPhoneOnly} { 30 | height: 70px; 31 | } 32 | `; 33 | 34 | export const LinkA = styled('a')` 35 | font-size: 16px; 36 | font-weight: 600; 37 | color: ${props => props.theme.secondary}; 38 | text-decoration: none; 39 | ${growStyle} ${forPhoneOnly} { 40 | font-size: 14px; 41 | } 42 | `; 43 | -------------------------------------------------------------------------------- /src/components/footer/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | export { Footer } from './footer.component'; 18 | -------------------------------------------------------------------------------- /src/components/header/header.component.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h } from 'preact'; 18 | import { withTheme } from 'emotion-theming'; 19 | 20 | import { Switch } from 'src/components'; 21 | import { ListSvg } from 'src/icons'; 22 | 23 | import { 24 | HeaderDiv, 25 | SwitchContainerDiv, 26 | ListSwitchControlDiv, 27 | ChangeColorSwitchControlDiv, 28 | ChangeColorsSvgContainer 29 | } from './header.style'; 30 | import { ChangeColorsSvg } from '../../icons'; 31 | 32 | const HeaderComponent = ({ 33 | theme, 34 | listChecked, 35 | themeChecked, 36 | onListChange, 37 | onThemeChange 38 | }) => ( 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | ); 54 | 55 | export const Header = withTheme(HeaderComponent); 56 | -------------------------------------------------------------------------------- /src/components/header/header.style.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import styled from 'preact-emotion'; 18 | 19 | import { forPhoneOnly, forTabletPortraitOnly } from 'src/shared'; 20 | 21 | export const HeaderDiv = styled('div')` 22 | display: flex; 23 | justify-content: flex-end; 24 | align-items: center; 25 | height: 70px; 26 | background-color: ${props => props.theme.backgroundSecondary}; 27 | border-bottom: 1px solid ${props => props.theme.secondary}; 28 | padding: 0 30px; 29 | position: fixed; 30 | width: 100%; 31 | z-index: 100; 32 | top: 0; 33 | 34 | ${forPhoneOnly} { 35 | height: 65px; 36 | padding: 0 20px; 37 | } 38 | `; 39 | 40 | export const SwitchContainerDiv = styled('div')` 41 | display: flex; 42 | `; 43 | 44 | export const ListSwitchControlDiv = styled('div')` 45 | display: flex; 46 | align-items: center; 47 | margin-right: 30px; 48 | 49 | ${forPhoneOnly} { 50 | display: none; 51 | } 52 | 53 | ${forTabletPortraitOnly} { 54 | display: none; 55 | } 56 | `; 57 | 58 | export const ChangeColorSwitchControlDiv = styled('div')` 59 | display: flex; 60 | align-items: center; 61 | `; 62 | 63 | export const ChangeColorsSvgContainer = styled('span')` 64 | display: flex; 65 | 66 | ${forPhoneOnly} { 67 | display: none; 68 | } 69 | `; 70 | -------------------------------------------------------------------------------- /src/components/header/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | export { Header } from './header.component'; 18 | -------------------------------------------------------------------------------- /src/components/hero/hero.component.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h } from 'preact'; 18 | import { withTheme } from 'emotion-theming'; 19 | 20 | import { 21 | ContainerDiv, 22 | TitleH1, 23 | LogoContainerDiv, 24 | DescriptionP 25 | } from './hero.style'; 26 | import { LogoSvg } from 'src/icons'; 27 | 28 | const HeroComponent = ({ 29 | theme, 30 | backgroundColor = theme.backgroundPrimary 31 | }) => ( 32 | 33 | 34 | 35 | Progressive Tooling 36 | 37 | 38 | A list of community-built, third-party tools that can be used to improve 39 | page performance 40 | 41 | 42 | ); 43 | 44 | export const Hero = withTheme(HeroComponent); 45 | -------------------------------------------------------------------------------- /src/components/hero/hero.style.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import styled from 'preact-emotion'; 18 | 19 | import { forPhoneOnly, containerStyle } from 'src/shared'; 20 | 21 | export const ContainerDiv = styled('div')` 22 | background-color: ${props => props.theme.backgroundSecondary}; 23 | border-bottom: ${props => 24 | props.theme.name === 'primary' 25 | ? `5px solid ${props.theme.border}` 26 | : `2px solid ${props.theme.border}`}; 27 | height: 70vh; 28 | margin-top: 70px; 29 | display: flex; 30 | flex-direction: column; 31 | justify-content: center; 32 | align-items: center; 33 | ${containerStyle}; 34 | 35 | ${forPhoneOnly} { 36 | margin-top: 65px; 37 | } 38 | `; 39 | 40 | export const LogoContainerDiv = styled('div')` 41 | display: flex; 42 | flex-direction: column; 43 | align-items: center; 44 | 45 | &:after { 46 | content: ''; 47 | display: block; 48 | margin: 20px auto; 49 | width: 50%; 50 | border-bottom: ${props => 51 | props.theme.name === 'primary' 52 | ? `2px solid ${props.theme.borderInverse}` 53 | : `5px solid ${props.theme.borderInverse}`}; 54 | } 55 | `; 56 | 57 | export const TitleH1 = styled('h1')` 58 | font-size: 42px; 59 | margin: 10px 0 20px; 60 | font-weight: 600; 61 | color: ${props => props.theme.logo}; 62 | 63 | ${forPhoneOnly} { 64 | font-size: 20px; 65 | margin-left: 5px; 66 | } 67 | `; 68 | 69 | export const DescriptionP = styled('p')` 70 | display: block; 71 | font-size: 20px; 72 | font-weight: 500; 73 | color: ${props => props.theme.primaryInverse}; 74 | line-height: 1.5; 75 | text-align: center; 76 | max-width: 600px; 77 | 78 | ${forPhoneOnly} { 79 | font-size: 16px; 80 | text-align: center; 81 | } 82 | `; 83 | -------------------------------------------------------------------------------- /src/components/hero/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | export { Hero } from './hero.component'; 18 | -------------------------------------------------------------------------------- /src/components/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | export { Card } from './card'; 18 | export { CardScroll } from './card-scroll'; 19 | export { Footer } from './footer'; 20 | export { Header } from './header'; 21 | export { Hero } from './hero'; 22 | export { Section } from './section'; 23 | export { SubHero } from './sub-hero'; 24 | export { Switch } from './switch'; 25 | export { Tooltip } from './tooltip'; 26 | -------------------------------------------------------------------------------- /src/components/section/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | export { Section } from './section.component'; 18 | -------------------------------------------------------------------------------- /src/components/section/section.component.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h } from 'preact'; 18 | import { withTheme } from 'emotion-theming'; 19 | 20 | import { 21 | ContainerSection, 22 | SectionHeadingH2, 23 | SectionSubHeadingP, 24 | ContentContainerDiv 25 | } from './section.style'; 26 | 27 | const SectionComponent = ({ 28 | theme, 29 | heading = '', 30 | subHeading = '', 31 | backgroundColor = theme.backgroundPrimary, 32 | children 33 | }) => ( 34 | 35 | {heading} 36 | {subHeading} 37 | {children} 38 | 39 | ); 40 | 41 | export const Section = withTheme(SectionComponent); 42 | -------------------------------------------------------------------------------- /src/components/section/section.style.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import styled from 'preact-emotion'; 18 | 19 | import { 20 | forPhoneOnly, 21 | forTabletPortraitUp, 22 | forTabletLandscapeUp, 23 | forDesktopUp, 24 | containerStyle 25 | } from 'src/shared'; 26 | 27 | export const ContainerSection = styled('section')` 28 | background-color: ${props => props.backgroundColor}; 29 | border-bottom: ${props => 30 | props.theme.name === 'primary' 31 | ? `5px solid ${props.theme.border}` 32 | : `2px solid ${props.theme.border}`}; 33 | ${containerStyle}; 34 | `; 35 | 36 | export const SectionHeadingH2 = styled('h2')` 37 | font-kerning: normal; 38 | display: block; 39 | margin-top: 0; 40 | margin-bottom: 0.5em; 41 | color: ${props => props.theme.primary}; 42 | line-height: 1.222; 43 | font-weight: 600; 44 | 45 | ${forPhoneOnly} { 46 | font-size: 22px; 47 | text-align: center; 48 | } 49 | 50 | ${forTabletPortraitUp} { 51 | font-size: 1.8rem; 52 | } 53 | 54 | ${forTabletLandscapeUp} { 55 | font-size: 2rem; 56 | } 57 | 58 | ${forDesktopUp} { 59 | width: 60%; 60 | } 61 | `; 62 | 63 | export const SectionSubHeadingP = styled('p')` 64 | margin-bottom: 0.83333em; 65 | display: block; 66 | font-size: 22px; 67 | margin-bottom: 0.9em; 68 | color: ${props => props.theme.primary}; 69 | line-height: 1.5; 70 | 71 | ${forPhoneOnly} { 72 | font-size: 16px; 73 | text-align: center; 74 | } 75 | 76 | ${forDesktopUp} { 77 | width: 60%; 78 | } 79 | `; 80 | 81 | export const ContentContainerDiv = styled('div')` 82 | margin-top: 6em; 83 | 84 | ${forPhoneOnly} { 85 | margin-top: 4em; 86 | } 87 | `; 88 | -------------------------------------------------------------------------------- /src/components/sub-hero/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | export { SubHero } from './sub-hero.component'; 18 | -------------------------------------------------------------------------------- /src/components/sub-hero/sub-hero.component.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h, createElement } from 'preact'; 18 | import { withTheme } from 'emotion-theming'; 19 | 20 | import { ContainerDiv, ToolTypeDiv, ToolTypeP } from './sub-hero.style'; 21 | import { 22 | CheckSvg, 23 | CodeSvg, 24 | FrameworkSvg, 25 | LaptopSvg, 26 | PackageSvg, 27 | TerminalSvg 28 | } from 'src/icons'; 29 | import TOOL_TYPES from 'src/tools/types'; 30 | 31 | const ICONS = { 32 | api: CodeSvg, 33 | CI: CheckSvg, 34 | CLI: TerminalSvg, 35 | dependency: PackageSvg, 36 | external: LaptopSvg, 37 | framework: FrameworkSvg 38 | }; 39 | 40 | const ICON_VIEW_BOX = { 41 | CLI: '0 0 14 16', 42 | dependency: '0 0 1000 900' 43 | }; 44 | 45 | const toolTypeIcon = ({ path, theme }) => { 46 | const element = ICONS[path]; 47 | const props = { 48 | viewBox: ICON_VIEW_BOX[path], 49 | size: 80, 50 | color: theme 51 | }; 52 | 53 | return createElement(element, props, null); 54 | }; 55 | 56 | const SubHeroComponent = ({ 57 | theme, 58 | backgroundColor = theme.backgroundPrimary 59 | }) => ( 60 | 61 | {Object.values(TOOL_TYPES).map(({ key, path, title }) => ( 62 | 63 | {toolTypeIcon({ theme: theme.tertiary, path })} 64 | {title} 65 | 66 | ))} 67 | 68 | ); 69 | 70 | export const SubHero = withTheme(SubHeroComponent); 71 | -------------------------------------------------------------------------------- /src/components/sub-hero/sub-hero.style.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import styled from 'preact-emotion'; 18 | 19 | import { 20 | containerStyle, 21 | forPhoneOnly, 22 | forTabletPortraitOnly, 23 | forTabletLandscapeOnly 24 | } from 'src/shared'; 25 | 26 | export const ContainerDiv = styled('div')` 27 | background-color: ${props => props.backgroundColor}; 28 | border-bottom: ${props => 29 | props.theme.name === 'primary' 30 | ? `5px solid ${props.theme.border}` 31 | : `2px solid ${props.theme.border}`}; 32 | display: flex; 33 | justify-content: space-around; 34 | ${containerStyle}; 35 | 36 | &:first-of-type { 37 | border-right: ${props => 38 | props.theme.name === 'primary' 39 | ? `5px solid ${props.theme.border}` 40 | : `2px solid ${props.theme.border}`}; 41 | } 42 | 43 | ${forPhoneOnly} { 44 | display: none; 45 | } 46 | `; 47 | 48 | export const ToolTypeDiv = styled('div')` 49 | display: flex; 50 | flex-direction: column; 51 | align-items: center; 52 | justify-content: space-around; 53 | min-height: 200px; 54 | max-width: 200px; 55 | 56 | ${forTabletPortraitOnly} { 57 | min-height: 150px; 58 | 59 | svg { 60 | width: 50px; 61 | height: 50px; 62 | } 63 | } 64 | 65 | ${forTabletLandscapeOnly} { 66 | min-height: 175px; 67 | 68 | svg { 69 | width: 60px; 70 | height: 60px; 71 | } 72 | } 73 | `; 74 | 75 | export const ToolTypeP = styled('p')` 76 | color: ${props => props.theme.primary}; 77 | font-size: 20px; 78 | font-weight: 500; 79 | margin: 0; 80 | text-align: center; 81 | 82 | ${forTabletPortraitOnly} { 83 | font-size: 16px; 84 | } 85 | 86 | ${forTabletLandscapeOnly} { 87 | font-size: 18px; 88 | } 89 | `; 90 | -------------------------------------------------------------------------------- /src/components/switch/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | export { Switch } from './switch.component'; 18 | -------------------------------------------------------------------------------- /src/components/switch/switch.component.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h } from 'preact'; 18 | 19 | import { SwitchLabel, SliderSpan, Input } from './switch.style'; 20 | 21 | export const Switch = ({ checked, onChange }) => ( 22 | 23 | 31 | 32 | 33 | ); 34 | -------------------------------------------------------------------------------- /src/components/switch/switch.style.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import styled from 'preact-emotion'; 18 | 19 | export const SwitchLabel = styled('label')` 20 | position: relative; 21 | display: inline-block; 22 | width: 46px; 23 | height: 26px; 24 | margin-left: 5px; 25 | 26 | &:input { 27 | display:none; 28 | } 29 | } 30 | `; 31 | 32 | export const SliderSpan = styled('span')` 33 | position: absolute; 34 | cursor: pointer; 35 | top: 0; 36 | left: 0; 37 | right: 0; 38 | bottom: 0; 39 | background-color: #ccc; 40 | -webkit-transition: 0.4s; 41 | transition: 0.4s; 42 | border-radius: 34px; 43 | 44 | &:before { 45 | position: absolute; 46 | content: ''; 47 | height: 18px; 48 | width: 18px; 49 | left: 4px; 50 | bottom: 4px; 51 | background-color: ${props => props.theme.tertiary}; 52 | -webkit-transition: 0.4s; 53 | transition: 0.4s; 54 | border-radius: 50%; 55 | } 56 | `; 57 | 58 | export const Input = styled('input')` 59 | &:checked { 60 | + ${SliderSpan} { 61 | background-color: ${props => props.theme.secondary}; 62 | 63 | &:before { 64 | -webkit-transform: translateX(18px); 65 | -ms-transform: translateX(18px); 66 | transform: translateX(18px); 67 | } 68 | } 69 | } 70 | 71 | &:focus { 72 | + ${SliderSpan} { 73 | box-shadow: 0 0 1px ${props => props.theme.secondary}; 74 | } 75 | } 76 | } 77 | `; 78 | -------------------------------------------------------------------------------- /src/components/tooltip/index.js: -------------------------------------------------------------------------------- 1 | export { Tooltip } from './tooltip.component'; 2 | -------------------------------------------------------------------------------- /src/components/tooltip/tooltip.component.js: -------------------------------------------------------------------------------- 1 | import { h, Component } from "preact"; 2 | import { withTheme } from "emotion-theming"; 3 | 4 | import { TooltipWrapper, TooltipSpan } from "./tooltip.style"; 5 | 6 | class TooltipComponent extends Component { 7 | state = { 8 | open: false 9 | }; 10 | 11 | toggleMouse = () => { 12 | this.setState({ open: !this.state.open }); 13 | }; 14 | 15 | render() { 16 | const { children, title, pointing = "top left" } = this.props; 17 | const { open } = this.state; 18 | 19 | return ( 20 | 24 | {open && {title}} 25 | {children} 26 | 27 | ); 28 | } 29 | } 30 | 31 | export const Tooltip = withTheme(TooltipComponent); -------------------------------------------------------------------------------- /src/components/tooltip/tooltip.style.js: -------------------------------------------------------------------------------- 1 | import styled, { css } from 'preact-emotion'; 2 | 3 | export const TooltipWrapper = styled('div')` 4 | position: relative; 5 | `; 6 | 7 | export const TooltipSpan = styled('span')` 8 | background: ${({ theme }) => `${theme.primary}80`}; 9 | border-radius: 5px; 10 | color: ${({ theme }) => theme.primaryInverse}; 11 | font-size: 12px; 12 | font-weight: bold; 13 | padding: 6px 12px; 14 | position: absolute; 15 | width: max-content; 16 | 17 | ${({ pointing }) => 18 | pointing === 'top left' && 19 | css` 20 | top: -30px; 21 | right: 0; 22 | `} 23 | 24 | ${({ pointing }) => 25 | pointing === 'top right' && 26 | css` 27 | top: -30px; 28 | left: 0; 29 | `} 30 | 31 | ${({ pointing }) => 32 | pointing === 'bottom left' && 33 | css` 34 | bottom: -30px; 35 | right: 0; 36 | `} 37 | 38 | ${({ pointing }) => 39 | pointing === 'bottom right' && 40 | css` 41 | bottom: -30px; 42 | left: 0; 43 | `} 44 | `; 45 | -------------------------------------------------------------------------------- /src/core/colors.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | export const colors = { 18 | purple: '#d70089', 19 | grey: '#FAFAFA', 20 | grey2: '#EBEBEB', 21 | black: '#000000', 22 | white: '#FFFFFF' 23 | }; 24 | -------------------------------------------------------------------------------- /src/core/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | export { colors } from './colors'; 18 | -------------------------------------------------------------------------------- /src/extract-critical.js: -------------------------------------------------------------------------------- 1 | import * as emotion from 'emotion'; 2 | 3 | // the same as import createExtractCritical from 'create-emotion-server/src/extract-critical'; 4 | // but without flow 5 | const createExtractCritical = (emotion) => (html) => { 6 | // parse out ids from html 7 | // reconstruct css/rules/cache to pass 8 | let RGX = new RegExp(`${emotion.caches.key}-([a-zA-Z0-9-]+)`, 'gm'); 9 | 10 | let o = { html, ids: [], css: '' }; 11 | let match; 12 | let ids = {}; 13 | while ((match = RGX.exec(html)) !== null) { 14 | // $FlowFixMe 15 | if (ids[match[1]] === undefined) { 16 | // $FlowFixMe 17 | ids[match[1]] = true; 18 | } 19 | } 20 | 21 | o.ids = Object.keys(emotion.caches.inserted).filter(id => { 22 | if ( 23 | (ids[id] === true || 24 | emotion.caches.registered[`${emotion.caches.key}-${id}`] === 25 | undefined) && 26 | emotion.caches.inserted[id] !== true 27 | ) { 28 | o.css += emotion.caches.inserted[id]; 29 | return true; 30 | } 31 | }); 32 | 33 | return o; 34 | }; 35 | 36 | export const extractCritical = createExtractCritical(emotion); 37 | -------------------------------------------------------------------------------- /src/icons/change-colors.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h } from 'preact'; 18 | 19 | import { IconWrapper } from './icon-wrapper'; 20 | 21 | export const ChangeColorsSvg = ({ color = '#000000' }) => ( 22 | 23 | 24 | 28 | 29 | ); 30 | -------------------------------------------------------------------------------- /src/icons/check.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h } from 'preact'; 18 | 19 | import { IconWrapper } from './icon-wrapper'; 20 | 21 | export const CheckSvg = ({ size = 45, color = '#000000' }) => ( 22 | 23 | 24 | 28 | 29 | ); 30 | -------------------------------------------------------------------------------- /src/icons/code.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h } from 'preact'; 18 | 19 | import { IconWrapper } from './icon-wrapper'; 20 | 21 | export const CodeSvg = ({ size, color = '#000000' }) => ( 22 | 23 | 24 | 25 | 29 | 30 | 31 | ); 32 | -------------------------------------------------------------------------------- /src/icons/framework.js: -------------------------------------------------------------------------------- 1 | import { h } from 'preact'; 2 | 3 | import { IconWrapper } from './icon-wrapper'; 4 | 5 | export const FrameworkSvg = ({ size, color = '#000000' }) => ( 6 | 7 | 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /src/icons/icon-wrapper/icon-wrapper.component.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h } from 'preact'; 18 | 19 | export const IconWrapper = ({ size, height, width, children, viewBox }) => ( 20 | 21 | {children} 22 | 23 | ); 24 | -------------------------------------------------------------------------------- /src/icons/icon-wrapper/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | export { IconWrapper } from './icon-wrapper.component'; 18 | -------------------------------------------------------------------------------- /src/icons/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | export { ChangeColorsSvg } from './change-colors'; 18 | export { CheckSvg } from './check'; 19 | export { CodeSvg } from './code'; 20 | export { FrameworkSvg } from './framework'; 21 | export { LaptopSvg } from './laptop'; 22 | export { ListSvg } from './list'; 23 | export { LogoSvg } from './logo'; 24 | export { PackageSvg } from './package'; 25 | export { TerminalSvg } from './terminal'; 26 | -------------------------------------------------------------------------------- /src/icons/laptop.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h } from 'preact'; 18 | 19 | import { IconWrapper } from './icon-wrapper'; 20 | 21 | export const LaptopSvg = ({ size, color = '#000000' }) => ( 22 | 23 | 24 | 25 | 29 | 30 | 31 | ); 32 | -------------------------------------------------------------------------------- /src/icons/list.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h } from 'preact'; 18 | 19 | import { IconWrapper } from './icon-wrapper'; 20 | 21 | export const ListSvg = ({ color = '#000000' }) => ( 22 | 23 | 27 | 28 | 29 | ); 30 | -------------------------------------------------------------------------------- /src/icons/logo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h } from 'preact'; 18 | 19 | import { IconWrapper } from './icon-wrapper'; 20 | 21 | export const LogoSvg = ({ size = 45, color = '#000000' }) => ( 22 | 23 | 24 | 28 | 29 | ); 30 | -------------------------------------------------------------------------------- /src/icons/package.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h } from 'preact'; 18 | 19 | import { IconWrapper } from './icon-wrapper'; 20 | 21 | export const PackageSvg = ({ size, viewBox, color = '#000000' }) => ( 22 | 23 | 27 | 28 | ); 29 | -------------------------------------------------------------------------------- /src/icons/terminal.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h } from 'preact'; 18 | 19 | import { IconWrapper } from './icon-wrapper'; 20 | 21 | export const TerminalSvg = ({ 22 | size, 23 | height, 24 | width, 25 | viewBox, 26 | color = '#000000' 27 | }) => ( 28 | 33 | 38 | 39 | ); 40 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Progressive Tooling 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | <% for (var chunk of webpack.chunks) { %> 64 | <% if (chunk.names.length === 1 && chunk.names[0] === 'polyfills') continue; %> 65 | <% for (var file of chunk.files) { %> 66 | <% if (file.match(/\.(js)$/)) { %> 67 | 68 | <% } else if (file.match(/manifest\.json$/)) { %> 69 | 70 | <% } %> 71 | <% } %> 72 | <% } %> 73 | 74 | 75 | 76 | <%= htmlWebpackPlugin.options.ssr({ 77 | url: '/' 78 | }) %> 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { h, render, Component } from 'preact'; 18 | import { renderToString } from 'preact-render-to-string'; 19 | import { injectGlobal, hydrate } from 'emotion'; 20 | import { ThemeProvider } from 'emotion-theming'; 21 | import { extractCritical } from './extract-critical'; 22 | import template from './template'; 23 | 24 | import { 25 | Header, 26 | Hero, 27 | SubHero, 28 | Section, 29 | CardScroll, 30 | Footer 31 | } from 'src/components'; 32 | import { colors } from 'src/core'; 33 | import tools from 'src/tools'; 34 | 35 | injectGlobal` 36 | html, 37 | body { 38 | display: block; 39 | width: 100%; 40 | padding: 0; 41 | margin: 0; 42 | background: #FFF; 43 | font-family: avenir next, avenir, helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif; 44 | font-weight: 400; 45 | color: #444; 46 | -webkit-font-smoothing: antialiased; 47 | -moz-osx-font-smoothing: grayscale; 48 | } 49 | 50 | * { 51 | box-sizing: border-box; 52 | } 53 | 54 | #app { 55 | width: 100%; 56 | } 57 | `; 58 | 59 | const primaryTheme = { 60 | name: 'primary', 61 | primary: colors.black, 62 | primaryInverse: colors.white, 63 | secondary: colors.white, 64 | tertiary: colors.purple, 65 | border: colors.grey2, 66 | borderInverse: colors.white, 67 | backgroundPrimary: colors.white, 68 | backgroundSecondary: colors.purple, 69 | logo: colors.white 70 | }; 71 | 72 | const secondaryTheme = { 73 | name: 'secondary', 74 | primary: colors.white, 75 | primaryInverse: colors.black, 76 | secondary: colors.purple, 77 | tertiary: colors.white, 78 | border: colors.white, 79 | borderInverse: colors.grey2, 80 | backgroundPrimary: colors.purple, 81 | backgroundSecondary: colors.white, 82 | logo: colors.purple 83 | }; 84 | 85 | class App extends Component { 86 | onListChange = () => { 87 | this.setState( 88 | { 89 | horizontalScroll: !this.state.horizontalScroll 90 | }, 91 | () => 92 | localStorage.setItem('horizontalScroll', this.state.horizontalScroll) 93 | ); 94 | }; 95 | 96 | onThemeChange = () => { 97 | this.setState( 98 | { 99 | theme: this.state.theme === 'primary' ? 'secondary' : 'primary' 100 | }, 101 | () => localStorage.setItem('theme', this.state.theme) 102 | ); 103 | }; 104 | 105 | constructor() { 106 | super(); 107 | 108 | if (typeof window !== 'undefined') { 109 | this.state = { 110 | theme: localStorage.getItem('theme') || 'primary', 111 | horizontalScroll: localStorage.getItem('horizontalScroll') 112 | ? JSON.parse(localStorage.getItem('horizontalScroll')) 113 | : window.innerWidth < 1200 114 | }; 115 | } else { 116 | this.state = { 117 | theme: 'primary', 118 | horizontalScroll: true 119 | }; 120 | } 121 | } 122 | 123 | renderSection(toolType, theme) { 124 | const { title, subtitle, tools } = toolType; 125 | const { horizontalScroll } = this.state; 126 | 127 | return ( 128 |
129 | 130 |
131 | ); 132 | } 133 | 134 | render() { 135 | const { theme, horizontalScroll } = this.state; 136 | 137 | return ( 138 | 141 |
142 |
148 | 149 | 150 | {Object.keys(tools).map(toolType => 151 | this.renderSection(tools[toolType], theme) 152 | )} 153 |
154 |
155 |
156 | ); 157 | } 158 | } 159 | 160 | const renderOnClient = () => { 161 | if (window.__EMOTION_CRITICAL_CSS_IDS__) { 162 | hydrate(window.__EMOTION_CRITICAL_CSS_IDS__); 163 | } 164 | 165 | render(, document.getElementById('root') || document.body, document.getElementById('app')); 166 | }; 167 | 168 | const renderOnServer = params => { 169 | const url = params.url || '/'; 170 | const { html, ids, css } = extractCritical(renderToString(h(App, { url }))); 171 | return template(html, ids, css); 172 | }; 173 | 174 | const renderingMethod = typeof window === 'undefined' ? renderOnServer : renderOnClient(); 175 | 176 | export default renderingMethod; 177 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Progressive Tooling", 3 | "short_name": "Prog Tooling", 4 | "start_url": "/", 5 | "display": "standalone", 6 | "orientation": "portrait", 7 | "theme_color": "#8E44AD", 8 | "background_color": "#8E44AD", 9 | "icons": [ 10 | { 11 | "src": "assets/icons/android-chrome-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image\/png" 14 | }, 15 | { 16 | "src": "assets/icons/android-chrome-256x256.png", 17 | "sizes": "256x256", 18 | "type": "image\/png" 19 | }, 20 | { 21 | "src": "assets/icons/android-chrome-512x512.png", 22 | "sizes": "512x512", 23 | "type": "image\/png" 24 | } 25 | ] 26 | } -------------------------------------------------------------------------------- /src/shared/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | export * from './shared.style'; 18 | export * from './spacing.style'; 19 | -------------------------------------------------------------------------------- /src/shared/shared.style.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | import { css } from 'emotion'; 18 | 19 | import { 20 | forPhoneOnly, 21 | forTabletPortraitUp, 22 | forTabletLandscapeUp, 23 | forDesktopUp, 24 | forLargeDesktopUp 25 | } from './spacing.style'; 26 | 27 | export const containerStyle = css` 28 | margin-left: auto; 29 | margin-right: auto; 30 | 31 | ${forPhoneOnly} { 32 | padding: 4rem 3rem; 33 | 34 | &:first-of-type { 35 | padding: 8rem 3rem 4rem; 36 | } 37 | } 38 | 39 | ${forTabletPortraitUp} { 40 | padding: 7rem 3rem; 41 | } 42 | 43 | ${forTabletLandscapeUp} { 44 | padding: 7rem 3rem; 45 | } 46 | 47 | ${forDesktopUp} { 48 | padding: 8rem 6rem; 49 | } 50 | 51 | ${forLargeDesktopUp} { 52 | padding: 8rem 8rem; 53 | } 54 | `; 55 | 56 | export const growStyle = css` 57 | -moz-osx-font-smoothing: grayscale; 58 | -webkit-backface-visibility: hidden; 59 | backface-visibility: hidden; 60 | -webkit-transform: translateZ(0); 61 | transform: translateZ(0); 62 | -webkit-transition: -webkit-transform .25s ease-out; 63 | transition: -webkit-transform .25s ease-out; 64 | transition: transform .25s ease-out; 65 | transition: transform .25s ease-out, -webkit-transform .25s ease-out; } 66 | 67 | &:hover { 68 | -webkit-transform: scale(1.1); 69 | transform: scale(1.1); 70 | } 71 | `; 72 | -------------------------------------------------------------------------------- /src/shared/spacing.style.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 | * use this file except in compliance with the License. You may obtain a copy of 6 | * the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | * License for the specific language governing permissions and limitations under 14 | * the License. 15 | */ 16 | 17 | export const forPhoneOnly = `@media (max-width: 599px)`; 18 | export const forTabletPortraitOnly = `@media (min-width: 600px) and (max-width: 899px)`; 19 | export const forTabletLandscapeOnly = `@media (min-width: 900px) and (max-width: 1023px)`; 20 | export const forSmallDesktopOnly = `@media (min-width: 1024px) and (max-width: 1199px)`; 21 | export const forDesktopOnly = `@media (min-width: 1200px) and (max-width: 1799px)`; 22 | 23 | export const forTabletPortraitUp = `@media (min-width: 600px)`; 24 | export const forTabletLandscapeUp = `@media (min-width: 900px)`; 25 | export const forSmallDesktopUp = `@media (min-width: 1024px)`; 26 | export const forDesktopUp = `@media (min-width: 1200px)`; 27 | export const forLargeDesktopUp = `@media (min-width: 1800px)`; 28 | -------------------------------------------------------------------------------- /src/template.js: -------------------------------------------------------------------------------- 1 | export default (html, ids, css) => ( 2 |
3 |