feat(page): add favycon home page (#29)

This commit is contained in:
Rui Saraiva 2020-04-12 21:25:55 +01:00 committed by GitHub
parent a22002beb7
commit 3adb9bf9fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 255 additions and 67 deletions

View File

@ -0,0 +1,29 @@
@import '../../styles/variables.scss';
.root {
position: relative;
width: 100%;
}
.image {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
font-family: 'object-fit: cover; object-position: center;', sans-serif;
object-fit: cover;
object-position: center;
}
.placeholder {
composes: image;
transition: opacity 0.2s linear 0.2s;
}
.normal {
composes: image;
transition: opacity 0.2s linear;
}

View File

@ -0,0 +1,54 @@
import React, { useRef, useEffect } from 'react'
import { LazyImageFull, ImageState } from 'react-lazy-images'
import objectFitImages from 'object-fit-images'
import styles from './index.module.scss'
type LazyImageProps = {
src: string
srcRetina: string
srcPlaceholder: string
alt: string
aspectRatio: string
}
const LazyImage = ({ src, srcRetina, srcPlaceholder, alt, aspectRatio }: LazyImageProps) => {
const [widthString, heightString] = aspectRatio.split('/')
const width = parseInt(widthString)
const height = parseInt(heightString)
const imgRef = useRef<HTMLImageElement>(null)
useEffect(() => {
if (imgRef.current) {
objectFitImages(imgRef.current)
}
}, [imgRef])
return (
<LazyImageFull src={src} srcSet={`${src} 1x, ${srcRetina} 2x`} alt={alt}>
{({ imageProps, imageState, ref }) => {
const loaded = imageState === ImageState.LoadSuccess
return (
<div className={styles.root} ref={ref} style={{ paddingBottom: `${(height / width) * 100 + '%'}` }}>
<img
className={styles.placeholder}
src={srcPlaceholder}
alt={imageProps.alt}
style={{ opacity: loaded ? 0 : 1 }}
/>
<img
ref={imgRef}
className={styles.normal}
{...imageProps}
alt={imageProps.alt}
style={{ opacity: loaded ? 1 : 0 }}
/>
</div>
)
}}
</LazyImageFull>
)
}
export { LazyImage }

View File

@ -28,6 +28,16 @@
.footer {
font-size: $font-size-footer;
line-height: $line-height-footer;
a {
color: inherit;
&:focus,
&:active,
&:hover {
color: inherit;
}
}
}
.superscript {

View File

@ -43,6 +43,7 @@
"classnames": "2.2.6",
"multer": "1.4.2",
"next": "9.3.4",
"object-fit-images": "3.2.4",
"preact": "10.4.0",
"preact-render-to-string": "5.1.6",
"preact-ssr-prepass": "1.0.1",
@ -50,6 +51,7 @@
"react": "16.13.1",
"react-dom": "16.13.1",
"react-dropzone": "10.2.2",
"react-lazy-images": "1.1.0",
"sharp": "0.25.2",
"use-dark-mode": "2.3.1"
},
@ -71,6 +73,7 @@
"@types/classnames": "2.2.10",
"@types/multer": "1.4.2",
"@types/node": "13.11.1",
"@types/object-fit-images": "3.2.0",
"@types/react": "16.9.34",
"@types/sharp": "0.24.0",
"@typescript-eslint/eslint-plugin": "2.27.0",

View File

@ -1,27 +0,0 @@
import React from 'react'
import { NextPage } from 'next'
import { BaseLayout } from 'components/base-layout'
import { Typography } from 'components/typography'
import { SEO } from 'components/seo'
import { ToolTitle } from 'components/tool-title'
const Appycon: NextPage = () => (
<BaseLayout>
<SEO title="Appycon" description="Appycon page description" />
<main>
<ToolTitle>Appycon</ToolTitle>
<Typography variant="largeBody" weight="medium">
A small online tool to help you generate your favicon in all the sizes and formats you need. <br />
<br />
Just drag &amp; drop an image and you will then get a downloadable file alongside some documentation on how to
add the favicons.
</Typography>
<hr />
<Typography variant="footer" weight="semiBold" color="gray">
Created by <u>4 people</u> on their 2020s worldwide quarantine. Background image from <u>Unsplash</u>.
</Typography>
</main>
</BaseLayout>
)
export default Appycon

View File

@ -1,30 +0,0 @@
import React from 'react'
import { NextPage } from 'next'
import { BaseLayout } from 'components/base-layout'
import { Typography } from 'components/typography'
import { SEO } from 'components/seo'
import { ToolTitle } from 'components/tool-title'
const Favycon: NextPage = () => (
<BaseLayout>
<SEO
title="Favycon"
description="A small online tool to help you generate your favicon in all the sizes and formats you need."
/>
<main>
<ToolTitle>Favycon</ToolTitle>
<Typography variant="largeBody" weight="medium">
A small online tool to help you generate your favicon in all the sizes and formats you need. <br />
<br />
Just drag &amp; drop an image and you will then get a downloadable file alongside some documentation on how to
add the favicons.
</Typography>
<hr />
<Typography variant="footer" weight="semiBold" color="gray">
Created by <u>4 people</u> on their 2020s worldwide quarantine. Background image from <u>Unsplash</u>.
</Typography>
</main>
</BaseLayout>
)
export default Favycon

56
pages/index.module.scss Normal file
View File

@ -0,0 +1,56 @@
@import '../styles/variables.scss';
.container {
display: flex;
align-items: flex-start;
justify-content: space-between;
width: 100%;
max-width: 960px;
padding: 52px 20px;
margin: 0 auto;
}
.info {
width: 100%;
max-width: 350px;
}
.firstParagraph {
margin-top: 8px;
}
.secondParagraph {
margin-top: 16px;
margin-bottom: 60px;
}
.dragAndDrop {
position: relative;
display: flex;
align-items: flex-start;
justify-content: center;
width: 100%;
max-width: 540px;
padding: 41px 0 38px;
}
.background {
position: absolute;
top: 10px;
right: 0;
left: 0;
z-index: -1;
width: 100%;
overflow: hidden;
border-radius: 8px;
transform: rotate(2deg);
}
.image {
position: absolute;
top: 57px;
right: 15px;
width: 184px;
height: 108px;
transform: translate(100%, -100%);
}

View File

@ -1,17 +1,79 @@
import React from 'react'
import { NextPage } from 'next'
import useDarkMode from 'use-dark-mode'
import { LazyImage } from 'components/lazy-image'
import { BaseLayout } from 'components/base-layout'
import { Typography } from 'components/typography'
import { SEO } from 'components/seo'
import { ToolTitle } from 'components/tool-title'
import { DragAndDrop } from 'components/drag-and-drop'
const Home: NextPage = () => (
<BaseLayout>
<SEO title="Home" description="Home page description" />
<main>
<ToolTitle>Favycon</ToolTitle>
<ToolTitle>Appycon</ToolTitle>
</main>
</BaseLayout>
)
import styles from './index.module.scss'
const getRandomNumber = (min = 1, max = 3) => Math.floor(Math.random() * max) + min
const unsplashImagesUrls = [
'https://unsplash.com/photos/F573ZRbKOEw',
'https://unsplash.com/photos/k0JNJRbrJAs',
'https://unsplash.com/photos/f9oQZOk9vnk',
]
const Home: NextPage = () => {
const { value: isDark } = useDarkMode(false)
const backgroundId = getRandomNumber()
const onDrop = (acceptedFiles: File[]) => {
console.log('acceptedFiles[0]', acceptedFiles[0])
}
return (
<BaseLayout>
<SEO
title="Favycon"
description="A small online tool to help you generate your favicon in all the sizes and formats you need."
/>
<main className={styles.container}>
<div className={styles.info}>
<ToolTitle>Favycon</ToolTitle>
<Typography variant="largeBody" weight="medium" className={styles.firstParagraph}>
A small online tool to help you generate your favicon in all the sizes and formats you need.
</Typography>
<Typography variant="largeBody" weight="medium" className={styles.secondParagraph}>
Just drag &amp; drop an image and you will then get a downloadable file alongside some documentation on how
to add the favicons.
</Typography>
<hr className={styles.lastParagraph} />
<Typography variant="footer" weight="semiBold" color="gray">
Created by <a href="/#">4 people</a> on their 2020s worldwide quarantine. Background image from{' '}
<a href={unsplashImagesUrls[backgroundId - 1]} target="_blank" rel="noopener noreferrer">
Unsplash
</a>
.
</Typography>
</div>
<div className={styles.dragAndDrop}>
<div className={styles.background}>
<LazyImage
src={`/images/unsplash-${backgroundId}@1x.jpg`}
srcRetina={`/images/unsplash-${backgroundId}@2x.jpg`}
srcPlaceholder={`/images/unsplash-${backgroundId}@placeholder.jpg`}
alt="Unsplash"
aspectRatio="540/354"
/>
</div>
<DragAndDrop onDrop={onDrop} />
<div className={styles.image}>
<LazyImage
src={`/images/dnd-${isDark ? 'dark' : 'light'}@1x.png`}
srcRetina={`/images/dnd-${isDark ? 'dark' : 'light'}@2x.png`}
srcPlaceholder={`/images/dnd-${isDark ? 'dark' : 'light'}@1x.png`}
alt="Drag and drop here!"
aspectRatio="184/108"
/>
</div>
</div>
</main>
</BaseLayout>
)
}
export default Home

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 795 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 858 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@ -1203,7 +1203,7 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.9.2"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.9.2.tgz#d90df0583a3a252f09aaa619665367bae518db06"
integrity sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==
@ -2444,6 +2444,11 @@
resolved "https://registry.yarnpkg.com/@types/npmlog/-/npmlog-4.1.2.tgz#d070fe6a6b78755d1092a3dc492d34c3d8f871c4"
integrity sha512-4QQmOF5KlwfxJ5IGXFIudkeLCdMABz03RcUXu+LCb24zmln8QW6aDjuGl4d4XPVLf2j+FnjelHTP7dvceAFbhA==
"@types/object-fit-images@3.2.0":
version "3.2.0"
resolved "https://registry.yarnpkg.com/@types/object-fit-images/-/object-fit-images-3.2.0.tgz#ffa0b3243ade3b89a2b12a08e92dbbea75b825f4"
integrity sha512-ordonpqL1HiYEHDIGxDo/MvyDvGZiNmPpw9bYxys7TXPcCN5WBejOR1Mj/KPCPyjMeaXyLQu7JP5tVi4GBRoWA==
"@types/parse-json@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
@ -10321,6 +10326,11 @@ object-copy@^0.1.0:
define-property "^0.2.5"
kind-of "^3.0.3"
object-fit-images@3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/object-fit-images/-/object-fit-images-3.2.4.tgz#6c299d38fdf207746e5d2d46c2877f6f25d15b52"
integrity sha512-G+7LzpYfTfqUyrZlfrou/PLLLAPNC52FTy5y1CBywX+1/FkxIloOyQXBmZ3Zxa2AWO+lMF0JTuvqbr7G5e5CWg==
object-inspect@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67"
@ -11682,6 +11692,14 @@ react-inspector@^4.0.0:
is-dom "^1.0.9"
prop-types "^15.6.1"
react-intersection-observer@^6.1.0:
version "6.4.2"
resolved "https://registry.yarnpkg.com/react-intersection-observer/-/react-intersection-observer-6.4.2.tgz#a061add707c37ea14e1308c77c2e286719347928"
integrity sha512-gL6YrkhniA0tIbyDbUterzBwKh61vHR520rsKULel5T37gG4YP07wnWI3WoqOcKK5bKAu0PZB2FHD7/OjawN+w==
dependencies:
"@babel/runtime" "^7.2.0"
invariant "^2.2.4"
react-is@16.8.6:
version "16.8.6"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
@ -11692,6 +11710,14 @@ react-is@^16.7.0, react-is@^16.8.1:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-lazy-images@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/react-lazy-images/-/react-lazy-images-1.1.0.tgz#c865445c96e568a6249db03a2bb2dccd49cb6f50"
integrity sha512-h5DHFhkMJyh2qsDl3hXWu6d+On10FsgHtRJ+BH7xjgsFOvsqaii9CEwEESqPJrrAiHo1qrN1LgzrV8X3zctHKA==
dependencies:
react-intersection-observer "^6.1.0"
unionize "^2.1.2"
react-lifecycles-compat@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
@ -14150,6 +14176,11 @@ union-value@^1.0.0:
is-extendable "^0.1.1"
set-value "^2.0.1"
unionize@^2.1.2:
version "2.2.0"
resolved "https://registry.yarnpkg.com/unionize/-/unionize-2.2.0.tgz#ce88635aa0793f28ab617abeac36172ba0aeb7bc"
integrity sha512-lHXiL6LPVuRYBGCLOdUd4GMHoAGqM0HtYHAZcA6pUEiwN1nk+LEYlh8bud7saeL0bkFntJzCPEPVVJeFm3Cqsg==
uniq@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"