├── .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 |
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 |
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 |
11 | );
12 |
--------------------------------------------------------------------------------
/src/tools/index.js:
--------------------------------------------------------------------------------
1 | import TOOL_TYPES from './types';
2 |
3 | const { external, api, dep, ci, cli, framework } = TOOL_TYPES;
4 |
5 | export default {
6 | accessibility: {
7 | title: 'Accessibility',
8 | subtitle:
9 | 'Visualize, audit and test accessibility parameters in your project',
10 | tools: [
11 | {
12 | description: 'An accessibility visualization toolkit',
13 | link: 'https://github.com/Khan/tota11y',
14 | title: 'tota11y',
15 | type: [dep]
16 | },
17 | {
18 | description:
19 | "CSS file that provides warnings for possible risks and mistakes and can help evaluate a site's quality",
20 | link: 'https://github.com/ffoodd/a11y.css',
21 | title: 'a11y.css',
22 | type: [dep]
23 | },
24 | {
25 | description: 'Color combination contrast tester',
26 | link: 'https://colorable.jxnblk.com/',
27 | title: 'Colorable',
28 | type: [external]
29 | },
30 | {
31 | description: 'Automated accessibility testing using HTML CodeSniffer',
32 | link: 'https://github.com/pa11y/pa11y',
33 | title: 'Pa11y',
34 | type: [dep, cli]
35 | },
36 | {
37 | description:
38 | 'Warns about potential accessibility issues with your React elements',
39 | link: 'https://github.com/reactjs/react-a11y',
40 | title: 'React A11y',
41 | type: [dep, framework]
42 | },
43 | {
44 | description:
45 | 'A library of accessibility-related testing and utility code',
46 | link: 'https://github.com/GoogleChrome/accessibility-developer-tools',
47 | title: 'Accessibility Developer Tools',
48 | type: [dep]
49 | },
50 | {
51 | description:
52 | 'An automated accessibility testing tool which crawls and tests pages to produce detailed reports',
53 | link: 'https://github.com/liip/TheA11yMachine',
54 | title: 'TheA11yMachine',
55 | type: [cli]
56 | }
57 | ]
58 | },
59 | auditing: {
60 | title: 'Performance auditing',
61 | subtitle: 'Audit and test the performance of your web page',
62 | tools: [
63 | {
64 | description:
65 | 'Run tests on actual devices with different locations, browsers, and connection speeds',
66 | link: 'https://www.webpagetest.org/',
67 | title: 'WebPageTest',
68 | type: [external, api]
69 | },
70 | {
71 | description:
72 | 'An open-source auditing tool that you can use to test and improve your webpage',
73 | link: 'https://developers.google.com/web/tools/lighthouse/',
74 | title: 'Lighthouse',
75 | type: [external]
76 | },
77 | {
78 | description:
79 | 'Track and monitor performance of webpages during ongoing development',
80 | link: 'https://calibreapp.com/',
81 | title: 'Calibre',
82 | type: [external]
83 | },
84 | {
85 | description:
86 | 'A devtool for inspecting the performance of React Components',
87 | link: 'https://github.com/nitin42/react-perf-devtool',
88 | title: 'React Performance Devtool',
89 | type: [external, framework]
90 | },
91 | {
92 | description:
93 | 'A devtool for inspecting the performance of Vue Components',
94 | link: 'https://github.com/vue-perf-devtool/vue-perf-devtool#vue-performance-devtool',
95 | title: 'Vue Performance Devtool',
96 | type: [external, framework]
97 | },
98 | {
99 | description:
100 | 'Monitor web performance and how real users experience your site',
101 | link: 'https://speedcurve.com/',
102 | title: 'Speedcurve',
103 | type: [external]
104 | },
105 | {
106 | description:
107 | 'Simple web performance monitoring of real users on your site',
108 | link: 'https://requestmetrics.com/',
109 | title: 'Request Metrics',
110 | type: [external]
111 | },
112 | {
113 | description:
114 | 'Service by Netlify that rates your site based on its initial global load times and its security settings',
115 | link: 'https://testmysite.io/',
116 | title: 'Testmysite.io',
117 | type: [external]
118 | },
119 | {
120 | description:
121 | 'An easy way to measure site performance across devices powered by WebPageTest',
122 | link: 'https://testmysite.withgoogle.com/',
123 | title: 'Test My Site',
124 | type: [external]
125 | },
126 | {
127 | description:
128 | 'Get speed field data and suggestions for optimization improvements',
129 | link: 'https://developers.google.com/speed/pagespeed/insights/',
130 | title: 'PageSpeed Insights',
131 | type: [external, api]
132 | },
133 | {
134 | description:
135 | 'Compare your mobile site speed with 10 other domains as well as estimate your revenue impact',
136 | link: 'https://www.thinkwithgoogle.com/feature/mobile/',
137 | title: 'Speed Scorecard',
138 | type: [external]
139 | },
140 | {
141 | description:
142 | 'Generate a node map visualization of all third-party interactions',
143 | link: 'http://requestmap.webperf.tools/',
144 | title: 'Request Map Generator',
145 | type: [external]
146 | },
147 | {
148 | description:
149 | 'Linting tool that can help improve accessibility, speed and more by checking for best practices',
150 | link: 'https://webhint.io/',
151 | title: 'webhint',
152 | type: [external, cli]
153 | },
154 | {
155 | description: 'Progressive web metrics at your fingertipz',
156 | link: 'https://github.com/paulirish/pwmetrics',
157 | title: 'PWMetrics',
158 | type: [cli, ci]
159 | },
160 | {
161 | description: 'Google PageSpeed Reports sent directly to your inbox every week',
162 | link: 'https://pagespeedreports.proteusthemes.com/',
163 | title: 'PageSpeed Reports',
164 | type: [external]
165 | },
166 | {
167 | description: 'A tool for speed and SEO optimization checks and guides',
168 | link: 'https://varvy.com/',
169 | title: 'Varvy SEO tool and optimization guide',
170 | type: [external]
171 | }
172 | ]
173 | },
174 | 'bundle-analysis': {
175 | title: 'Bundle analysis',
176 | subtitle: 'Analyze and measure your bundle and package sizes',
177 | tools: [
178 | {
179 | description: 'Find the cost of adding a npm package to your bundle',
180 | link: 'https://bundlephobia.com/',
181 | title: 'Bundlephobia',
182 | type: [external]
183 | },
184 | {
185 | description:
186 | 'Visual Studio Code extension that displays the size of imported packages inline',
187 | link:
188 | 'https://marketplace.visualstudio.com/items?itemName=wix.vscode-import-cost',
189 | title: 'Import Cost',
190 | type: [external]
191 | },
192 | {
193 | description:
194 | 'Visualize the size of webpack output files with a treemap',
195 | link: 'https://www.npmjs.com/package/webpack-bundle-analyzer',
196 | title: 'Webpack Bundle Analyzer',
197 | type: [dep]
198 | },
199 | {
200 | description: 'Visualize the size of parcel output files with a treemap',
201 | link:
202 | 'https://github.com/gregtillbrook/parcel-plugin-bundle-visualiser',
203 | title: 'Parcel Plugin Bundle Analyzer',
204 | type: [dep]
205 | },
206 | {
207 | description: 'CLI dashboard for your webpack dev server',
208 | link: 'https://github.com/FormidableLabs/webpack-dashboard',
209 | title: 'Webpack Dashboard',
210 | type: [cli]
211 | },
212 | {
213 | description: 'Electron Desktop GUI for Webpack Dashboard',
214 | link: 'https://github.com/FormidableLabs/electron-webpack-dashboard',
215 | title: 'Electron Webpack Dashboard',
216 | type: [cli]
217 | },
218 | {
219 | description: 'An intelligent browser-based Webpack dashboard',
220 | link: 'https://github.com/zouhir/jarvis',
221 | title: 'Jarvis',
222 | type: [dep]
223 | },
224 | {
225 | description: 'An online visualization tool for webpack bundles',
226 | link: 'https://chrisbateman.github.io/webpack-visualizer',
227 | title: 'Webpack Visualizer',
228 | type: [external]
229 | },
230 | {
231 | description: 'Analyze and debug code bloat through source maps',
232 | link: 'https://github.com/danvk/source-map-explorer',
233 | title: 'Source Map Explorer',
234 | type: [cli]
235 | },
236 | {
237 | description:
238 | 'Tool to help you find source code duplication across your javascript chunks/splits',
239 | link: 'https://github.com/samccone/bundle-buddy',
240 | title: 'Bundle Buddy',
241 | type: [cli]
242 | },
243 | {
244 | description:
245 | 'Tool for monitoring webpack optimization metrics through the development process',
246 | link: 'https://github.com/webpackmonitor/webpackmonitor',
247 | title: 'Webpack Monitor',
248 | type: [dep]
249 | },
250 | {
251 | description: 'Interactive pie chart for webpack stats',
252 | link: 'https://github.com/alexkuz/webpack-chart',
253 | title: 'Webpack Chart',
254 | type: [external]
255 | }
256 | ]
257 | },
258 | 'bundle-budgets': {
259 | title: 'Bundle budgeting',
260 | subtitle: 'Set up budgets to keep your bundle sizes in check',
261 | tools: [
262 | {
263 | description: 'Keep an eye on your bundle size through a CI hook',
264 | link: 'https://github.com/siddharthkp/bundlesize',
265 | title: 'Bundlesize',
266 | type: [dep, ci]
267 | },
268 | {
269 | description:
270 | 'Prevent library bloat by having error checks when including large dependencies',
271 | link: 'https://github.com/ai/size-limit',
272 | title: 'size-limit',
273 | type: [dep]
274 | },
275 | {
276 | description:
277 | 'Automatically track the size of your build artifacts with a CircleCI integration',
278 | link: 'https://buildsize.org/',
279 | title: 'BuildSize',
280 | type: [ci]
281 | }
282 | ]
283 | },
284 | 'image-optimization': {
285 | title: 'Image optimization',
286 | subtitle: 'Optimize and compress images',
287 | tools: [
288 | {
289 | description: 'A Github Action that automatically compresses JPEGs, PNGs and WebPs in Pull Requests',
290 | link: 'https://github.com/calibreapp/image-actions/',
291 | title: 'image-actions',
292 | type: [ci, cli, external]
293 | },
294 | {
295 | description: 'Minify images seamlessly',
296 | link: 'https://github.com/imagemin/imagemin',
297 | title: 'ImageMin',
298 | type: [dep, cli, external]
299 | },
300 | {
301 | description:
302 | 'Reduce JPEG file sizes while retaining quality and compatibility',
303 | link: 'https://github.com/mozilla/mozjpeg',
304 | title: 'MozJPEG',
305 | type: [dep]
306 | },
307 | {
308 | description:
309 | 'Save disk space & bandwidth by compressing images without losing quality',
310 | link: 'https://imageoptim.com/api',
311 | title: 'ImageOptim',
312 | type: [api, external]
313 | },
314 | {
315 | description:
316 | 'A GUI tool for losslessly optimizing PNG and JPG files',
317 | link: 'https://trimage.org/',
318 | title: 'Trimage',
319 | type: [cli, external]
320 | },
321 | {
322 | description:
323 | 'A free tool for optimizing JPEG and PNG files',
324 | link: 'https://tinyjpg.com/',
325 | title: 'TinyJPG',
326 | type: [external, api]
327 | }
328 | ]
329 | },
330 | 'video-optimization': {
331 | title: 'Video optimization',
332 | subtitle: 'Optimize and compress videos',
333 | tools: [
334 | {
335 | description: 'Convert videos from live sources and resize them on the fly',
336 | link: 'https://www.ffmpeg.org/ffmpeg.html',
337 | title: 'ffmpeg',
338 | type: [cli]
339 | }
340 | ]
341 | },
342 | 'lazy-loading': {
343 | title: 'Lazy loading',
344 | subtitle:
345 | 'Asynchronously load elements (DOM nodes, images, components or routes) when needed',
346 | tools: [
347 | {
348 | description:
349 | 'Higher order component for loading components with dynamic imports',
350 | link: 'https://github.com/jamiebuilds/react-loadable',
351 | title: 'React Loadable',
352 | type: [dep]
353 | },
354 | {
355 | description: 'A fast, flexible, and small image lazy loader',
356 | link: 'https://github.com/malchata/yall.js',
357 | title: 'yall.js',
358 | type: [dep]
359 | },
360 | {
361 | description:
362 | 'High performance and SEO friendly lazy loader for images, iframes and more',
363 | link: 'https://github.com/aFarkas/lazysizes',
364 | title: 'Lazysizes',
365 | type: [dep]
366 | },
367 | {
368 | description:
369 | 'Detect if a DOM element intersects with another element such as the document viewport',
370 | link:
371 | 'https://developers.google.com/web/updates/2016/04/intersectionobserver',
372 | title: 'Intersection Observer',
373 | type: [api]
374 | },
375 | {
376 | description:
377 | 'Split bundles for lazy loading using entry points or dynamic imports',
378 | link: 'https://webpack.js.org/guides/code-splitting/',
379 | title: 'webpack',
380 | type: [dep]
381 | },
382 | {
383 | description:
384 | 'Use dynamic imports to split application code into separate bundles',
385 | link: 'https://parceljs.org/code_splitting.html',
386 | title: 'Parcel',
387 | type: [dep]
388 | }
389 | ]
390 | },
391 | 'service-worker': {
392 | title: 'Service Worker',
393 | subtitle:
394 | 'Cache static or dynamic assets for offline support using service workers',
395 | tools: [
396 | {
397 | description: 'Set of tools that simplify process of caching assets',
398 | link: 'https://developers.google.com/web/tools/workbox/',
399 | title: 'Workbox',
400 | type: [dep, cli]
401 | },
402 | {
403 | description:
404 | "Tiny JavaScript library that makes sure your users can always access your site's content",
405 | link: 'https://github.com/TalAter/UpUp',
406 | title: 'UpUp',
407 | type: [dep]
408 | },
409 | {
410 | description:
411 | 'A webpack plugin that uses ServiceWorker (and AppCache) to provide an offline experience',
412 | link: 'https://github.com/NekR/offline-plugin',
413 | title: 'Offline Plugin',
414 | type: [dep]
415 | },
416 | {
417 | description:
418 | 'Node module to generate a ServiceWorker that will precache specific resources',
419 | link: 'https://github.com/GoogleChromeLabs/sw-precache',
420 | title: 'Service Worker Precache',
421 | type: [dep, cli]
422 | },
423 | {
424 | description:
425 | 'Collection of service worker tools for offlining runtime requests',
426 | link: 'https://github.com/GoogleChromeLabs/sw-toolbox',
427 | title: 'Service Worker Toolbox',
428 | type: [dep]
429 | }
430 | ]
431 | },
432 | fouc: {
433 | title: 'Flash of invisible/unstyled text',
434 | subtitle:
435 | 'Tools to minimize unstyled/invisible text rendered to the web page while external styles are still being fetched',
436 | tools: [
437 | {
438 | description:
439 | 'Minimize flash of unstyled text by comparing between a fallback and an intended font',
440 | link: 'https://meowni.ca/font-style-matcher/',
441 | title: 'Font style matcher',
442 | type: [external]
443 | },
444 | {
445 | description:
446 | 'Track download progress and define lazy loading behavior of font faces',
447 | link:
448 | 'https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization#the_font_loading_api',
449 | title: 'CSS Font Loading',
450 | type: [api]
451 | },
452 | {
453 | description:
454 | 'Control how a font is displayed while it is still being fetched',
455 | link: 'https://developers.google.com/web/updates/2016/02/font-display',
456 | title: 'font-display',
457 | type: [api]
458 | },
459 | {
460 | description: 'A fast and simple web font loader',
461 | link: 'https://fontfaceobserver.com/',
462 | title: 'Font Face Observer',
463 | type: [dep]
464 | }
465 | ]
466 | },
467 | ssr: {
468 | title: 'Server-side rendering/pre-rendering',
469 | subtitle: 'Send down static HTML to improve perceived load times and SEO',
470 | tools: [
471 | {
472 | description: 'Universal javascript support for Angular',
473 | link: 'https://github.com/angular/universal',
474 | title: 'Angular Universal',
475 | type: [cli]
476 | },
477 | {
478 | description:
479 | 'Zero-configuration framework-agnostic static prerendering for SPAs',
480 | link: 'https://github.com/stereobooster/react-snap',
481 | title: 'react-snap',
482 | type: [dep]
483 | },
484 | {
485 | description:
486 | 'React.js server-side rendering optimization with component memoization and templatization',
487 | link: 'https://github.com/walmartlabs/react-ssr-optimization',
488 | title: 'react-ssr-optimization',
489 | type: [dep]
490 | },
491 | {
492 | description: 'Create a Preact PWA quickly with built-in pre-rendering',
493 | link: 'https://github.com/developit/preact-cli',
494 | title: 'preact-cli',
495 | type: [cli]
496 | },
497 | {
498 | description:
499 | 'Add server-side rendering capabilities to a web server using Headless Chrome',
500 | link: 'https://developers.google.com/web/tools/puppeteer/articles/ssr',
501 | title: 'Puppeteer',
502 | type: [dep]
503 | }
504 | ]
505 | },
506 | 'data-analytics': {
507 | title: 'Data Analytics',
508 | subtitle: 'Tools that use analytics or machine learning models to improve user experience',
509 | tools: [
510 | {
511 | description: 'Libraries and tools for enabling data-driven user-experiences on the web',
512 | link: 'https://github.com/guess-js/guess',
513 | title: 'Guess.js',
514 | type: [dep]
515 | }
516 | ]
517 | }
518 | };
519 |
--------------------------------------------------------------------------------
/src/tools/types.js:
--------------------------------------------------------------------------------
1 | export default {
2 | external: { key: 'external', path: 'external', title: 'Website/GUI' },
3 | dep: { key: 'dep', path: 'dependency', title: 'Package' },
4 | ci: { key: 'ci', path: 'CI', title: 'CI' },
5 | cli: { key: 'cli', path: 'CLI', title: 'CLI' },
6 | api: { key: 'api', path: 'api', title: 'API (Web/Server)' },
7 | framework: { key: 'framework', path: 'framework', title: 'Framework' }
8 | };
9 |
--------------------------------------------------------------------------------