mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-11 16:26:20 +00:00
[RFC] Add Three Homepage Sections (#1112)
This commit is contained in:
51
src/shared/prerendered-app/Intro/SlideOnScroll/index.tsx
Normal file
51
src/shared/prerendered-app/Intro/SlideOnScroll/index.tsx
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import { h, Component, RenderableProps } from 'preact';
|
||||||
|
|
||||||
|
interface Props {}
|
||||||
|
interface State {}
|
||||||
|
|
||||||
|
export default class SlideOnScroll extends Component<Props, State> {
|
||||||
|
private observer?: IntersectionObserver;
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
||||||
|
|
||||||
|
const base = this.base as HTMLElement;
|
||||||
|
let wasOutOfView = false;
|
||||||
|
|
||||||
|
this.observer = new IntersectionObserver(
|
||||||
|
(entries, observer) => {
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (!entry.isIntersecting) {
|
||||||
|
wasOutOfView = true;
|
||||||
|
base.style.opacity = '0';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only transition in if the element was at some point out of view.
|
||||||
|
if (wasOutOfView) {
|
||||||
|
base.style.opacity = '';
|
||||||
|
base.animate(
|
||||||
|
{ offset: 0, opacity: '0', transform: 'translateY(40px)' },
|
||||||
|
{ duration: 300, easing: 'ease' },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
observer.unobserve(entry.target);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ threshold: 0.2 },
|
||||||
|
);
|
||||||
|
|
||||||
|
this.observer.observe(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
// Have to manually disconnect due to memory leaks in browsers.
|
||||||
|
// One day we'll be able to remove this, and the private property.
|
||||||
|
// https://twitter.com/jaffathecake/status/1405437361643790337
|
||||||
|
this.observer!.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
render({ children }: RenderableProps<Props>) {
|
||||||
|
return <div>{children}</div>;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg width="498" height="333" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M401.17 125.52C387.072 53.923 324.253.173 248.787.173c-59.916 0-111.954 34.035-137.869 83.841C48.513 90.655 0 143.574 0 207.7c0 68.692 55.77 124.516 124.394 124.516h269.519c57.221 0 103.662-46.486 103.662-103.763 0-54.787-42.502-99.198-96.405-102.933z" fill="#91D3FF" fill-opacity=".3"/><path d="M187.247 121.321l-3.987-3.987-3.481 4.434c-11.519 14.67-18.366 33.15-18.366 53.242 0 48.003 38.882 86.885 86.885 86.885 20.091 0 38.572-6.848 53.242-18.366l4.434-3.482-3.987-3.986-114.74-114.74zM309.348 228.7l3.987 3.986 3.481-4.434c11.519-14.669 18.366-33.15 18.366-53.242 0-48.002-38.882-86.884-86.884-86.884-20.092 0-38.573 6.847-53.242 18.365l-4.435 3.482 3.987 3.986L309.348 228.7zm-158.406-53.69c0-53.739 43.617-97.355 97.356-97.355 53.738 0 97.355 43.616 97.355 97.355 0 53.739-43.617 97.356-97.355 97.356-53.739 0-97.356-43.617-97.356-97.356z" fill="#FF3385" stroke="#FF3385" stroke-width="10"/></svg>
|
||||||
|
After Width: | Height: | Size: 991 B |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 5.2 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 5.4 KiB |
@@ -10,12 +10,16 @@ import deviceScreen from 'url:./imgs/demos/demo-device-screen.png';
|
|||||||
import largePhotoIcon from 'url:./imgs/demos/icon-demo-large-photo.jpg';
|
import largePhotoIcon from 'url:./imgs/demos/icon-demo-large-photo.jpg';
|
||||||
import artworkIcon from 'url:./imgs/demos/icon-demo-artwork.jpg';
|
import artworkIcon from 'url:./imgs/demos/icon-demo-artwork.jpg';
|
||||||
import deviceScreenIcon from 'url:./imgs/demos/icon-demo-device-screen.jpg';
|
import deviceScreenIcon from 'url:./imgs/demos/icon-demo-device-screen.jpg';
|
||||||
|
import smallSectionAsset from 'url:./imgs/info-content/small.svg';
|
||||||
|
import simpleSectionAsset from 'url:./imgs/info-content/simple.svg';
|
||||||
|
import secureSectionAsset from 'url:./imgs/info-content/secure.svg';
|
||||||
import logoIcon from 'url:./imgs/demos/icon-demo-logo.png';
|
import logoIcon from 'url:./imgs/demos/icon-demo-logo.png';
|
||||||
import logoWithText from 'url:./imgs/logo-with-text.svg';
|
import logoWithText from 'url:./imgs/logo-with-text.svg';
|
||||||
import * as style from './style.css';
|
import * as style from './style.css';
|
||||||
import type SnackBarElement from 'shared/custom-els/snack-bar';
|
import type SnackBarElement from 'shared/custom-els/snack-bar';
|
||||||
import 'shared/custom-els/snack-bar';
|
import 'shared/custom-els/snack-bar';
|
||||||
import { startBlobs } from './blob-anim/meta';
|
import { startBlobs } from './blob-anim/meta';
|
||||||
|
import SlideOnScroll from './SlideOnScroll';
|
||||||
|
|
||||||
const demos = [
|
const demos = [
|
||||||
{
|
{
|
||||||
@@ -336,37 +340,125 @@ export default class Intro extends Component<Props, State> {
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class={style.footer}>
|
|
||||||
|
<div class={style.bottomWave}>
|
||||||
<svg viewBox="0 0 1920 79" class={style.topWave}>
|
<svg viewBox="0 0 1920 79" class={style.topWave}>
|
||||||
<path
|
<path
|
||||||
d="M0 59l64-11c64-11 192-34 320-43s256-5 384 4 256 23 384 34 256 21 384 14 256-30 320-41l64-11v94H0z"
|
d="M0 59l64-11c64-11 192-34 320-43s256-5 384 4 256 23 384 34 256 21 384 14 256-30 320-41l64-11v94H0z"
|
||||||
class={style.footerWave}
|
class={style.infoWave}
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
<div class={style.contentPadding}>
|
|
||||||
<footer class={style.footerItems}>
|
|
||||||
<a
|
|
||||||
class={style.footerLink}
|
|
||||||
href="https://github.com/GoogleChromeLabs/squoosh/blob/dev/README.md#privacy"
|
|
||||||
>
|
|
||||||
Privacy
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
class={style.footerLink}
|
|
||||||
href="https://github.com/GoogleChromeLabs/squoosh/tree/dev/cli"
|
|
||||||
>
|
|
||||||
Squoosh CLI
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
class={style.footerLinkWithLogo}
|
|
||||||
href="https://github.com/GoogleChromeLabs/squoosh"
|
|
||||||
>
|
|
||||||
<img src={githubLogo} alt="" width="10" height="10" />
|
|
||||||
Source on Github
|
|
||||||
</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<section class={style.info}>
|
||||||
|
<div class={style.infoContainer}>
|
||||||
|
<SlideOnScroll>
|
||||||
|
<div class={style.infoContent}>
|
||||||
|
<div class={style.infoTextWrapper}>
|
||||||
|
<h2 class={style.infoTitle}>Small</h2>
|
||||||
|
<p class={style.infoCaption}>
|
||||||
|
Smaller images mean faster load times. Squoosh can reduce
|
||||||
|
file size and maintain high quality.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class={style.infoImgWrapper}>
|
||||||
|
<img
|
||||||
|
class={style.infoImg}
|
||||||
|
src={smallSectionAsset}
|
||||||
|
alt="silhouette of a large 1.4 megabyte image shrunk into a smaller 80 kilobyte image"
|
||||||
|
width="536"
|
||||||
|
height="522"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SlideOnScroll>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class={style.info}>
|
||||||
|
<div class={style.infoContainer}>
|
||||||
|
<SlideOnScroll>
|
||||||
|
<div class={style.infoContent}>
|
||||||
|
<div class={style.infoTextWrapper}>
|
||||||
|
<h2 class={style.infoTitle}>Simple</h2>
|
||||||
|
<p class={style.infoCaption}>
|
||||||
|
Open your image, inspect the differences, then save
|
||||||
|
instantly. Feeling adventurous? Adjust the settings for even
|
||||||
|
smaller files.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class={style.infoImgWrapper}>
|
||||||
|
<img
|
||||||
|
class={style.infoImg}
|
||||||
|
src={simpleSectionAsset}
|
||||||
|
alt="grid of multiple shrunk images displaying various options"
|
||||||
|
width="538"
|
||||||
|
height="384"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SlideOnScroll>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class={style.info}>
|
||||||
|
<div class={style.infoContainer}>
|
||||||
|
<SlideOnScroll>
|
||||||
|
<div class={style.infoContent}>
|
||||||
|
<div class={style.infoTextWrapper}>
|
||||||
|
<h2 class={style.infoTitle}>Secure</h2>
|
||||||
|
<p class={style.infoCaption}>
|
||||||
|
Worried about privacy? Images never leave your device since
|
||||||
|
Squoosh does all the work locally.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class={style.infoImgWrapper}>
|
||||||
|
<img
|
||||||
|
class={style.infoImg}
|
||||||
|
src={secureSectionAsset}
|
||||||
|
alt="silhouette of a cloud with a 'no' symbol on top"
|
||||||
|
width="498"
|
||||||
|
height="333"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</SlideOnScroll>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<footer class={style.footer}>
|
||||||
|
<div class={style.footerContainer}>
|
||||||
|
<svg viewBox="0 0 1920 79" class={style.topWave}>
|
||||||
|
<path
|
||||||
|
d="M0 59l64-11c64-11 192-34 320-43s256-5 384 4 256 23 384 34 256 21 384 14 256-30 320-41l64-11v94H0z"
|
||||||
|
class={style.footerWave}
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
<div class={style.footerPadding}>
|
||||||
|
<footer class={style.footerItems}>
|
||||||
|
<a
|
||||||
|
class={style.footerLink}
|
||||||
|
href="https://github.com/GoogleChromeLabs/squoosh/blob/dev/README.md#privacy"
|
||||||
|
>
|
||||||
|
Privacy
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
class={style.footerLink}
|
||||||
|
href="https://github.com/GoogleChromeLabs/squoosh/tree/dev/cli"
|
||||||
|
>
|
||||||
|
Squoosh CLI
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
class={style.footerLinkWithLogo}
|
||||||
|
href="https://github.com/GoogleChromeLabs/squoosh"
|
||||||
|
>
|
||||||
|
<img src={githubLogo} alt="" width="10" height="10" />
|
||||||
|
Source on Github
|
||||||
|
</a>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
{beforeInstallEvent && (
|
{beforeInstallEvent && (
|
||||||
<button class={style.installBtn} onClick={this.onInstallClick}>
|
<button class={style.installBtn} onClick={this.onInstallClick}>
|
||||||
Install
|
Install
|
||||||
|
|||||||
@@ -118,7 +118,114 @@
|
|||||||
fill: var(--light-blue);
|
fill: var(--light-blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bottom-wave {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
background: var(--white);
|
||||||
|
position: relative;
|
||||||
|
padding: 5em 2em;
|
||||||
|
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
padding: 5em 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-container {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-content {
|
||||||
|
display: grid;
|
||||||
|
align-items: center;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
gap: 1em;
|
||||||
|
|
||||||
|
grid-template-areas:
|
||||||
|
'text'
|
||||||
|
'img';
|
||||||
|
|
||||||
|
@media (min-width: 712px) {
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
grid-template-areas: 'text img';
|
||||||
|
|
||||||
|
.info:nth-child(even) & {
|
||||||
|
grid-template-areas: 'img text';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-title {
|
||||||
|
color: var(--pink);
|
||||||
|
font-size: 3em;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-caption {
|
||||||
|
font-size: 1.5em;
|
||||||
|
line-height: 1.75;
|
||||||
|
margin: 1em 0 0.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-link {
|
||||||
|
font-size: 1.25em;
|
||||||
|
text-underline-offset: 0.25em;
|
||||||
|
color: var(--off-black);
|
||||||
|
transition: color 400ms ease-in-out;
|
||||||
|
margin-top: 1em;
|
||||||
|
&:hover {
|
||||||
|
color: var(--dim-blue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-text-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column wrap;
|
||||||
|
max-width: 27em;
|
||||||
|
justify-self: center;
|
||||||
|
grid-area: text;
|
||||||
|
|
||||||
|
@media (min-width: 712px) {
|
||||||
|
justify-self: start;
|
||||||
|
.info:nth-child(even) & {
|
||||||
|
text-align: right;
|
||||||
|
justify-self: end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-img-wrapper {
|
||||||
|
grid-area: img;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-img {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
max-width: 400px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
margin: 0 0 0 auto;
|
||||||
|
|
||||||
|
.info:nth-child(even) & {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-wave {
|
||||||
|
fill: var(--white);
|
||||||
|
}
|
||||||
|
|
||||||
.footer {
|
.footer {
|
||||||
|
background: var(--white);
|
||||||
|
padding-top: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
background: var(--light-gray);
|
background: var(--light-gray);
|
||||||
}
|
}
|
||||||
@@ -128,7 +235,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.content-padding {
|
.content-padding {
|
||||||
padding: 2rem;
|
padding: 2em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-padding {
|
||||||
|
padding: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-items {
|
.footer-items {
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ const Index: FunctionalComponent<Props> = () => (
|
|||||||
<link rel="shortcut icon" href={favicon} />
|
<link rel="shortcut icon" href={favicon} />
|
||||||
<meta name="theme-color" content="#ff3385" />
|
<meta name="theme-color" content="#ff3385" />
|
||||||
<link rel="manifest" href="/manifest.json" />
|
<link rel="manifest" href="/manifest.json" />
|
||||||
|
<link rel="canonical" href={siteOrigin} />
|
||||||
<style
|
<style
|
||||||
dangerouslySetInnerHTML={{ __html: escapeStyleScriptContent(baseCss) }}
|
dangerouslySetInnerHTML={{ __html: escapeStyleScriptContent(baseCss) }}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": "./generic-tsconfig.json",
|
"extends": "./generic-tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"lib": ["esnext", "dom"],
|
"lib": ["esnext", "dom", "dom.iterable"],
|
||||||
"types": ["node"]
|
"types": ["node"]
|
||||||
},
|
},
|
||||||
"include": ["src/shared/**/*", "src/static-build/**/*"]
|
"include": ["src/shared/**/*", "src/static-build/**/*"]
|
||||||
|
|||||||
Reference in New Issue
Block a user