diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..51523ed --- /dev/null +++ b/TODO.md @@ -0,0 +1,25 @@ +- Update to latest React +- Package a local version of Gatsby with hooks support +- Switch to SVG emoji heart + +```jsx +import React, { useState } from 'react' + +const handleSubmit = (value, mutation) => { + return ev => { + ev.preventDefault() + } + + // use value +} + +function() { + const [value, setValue] = useState('') + + return ( +
+ setValue(ev.target.value)} /> +
+ ) +} +``` diff --git a/client/src/components/canvas.js b/client/src/components/canvas.js index 8867e55..5a170b7 100644 --- a/client/src/components/canvas.js +++ b/client/src/components/canvas.js @@ -49,6 +49,8 @@ export default class Canvas extends Component { context.clearRect(0, 0, this.canvas.width, this.canvas.height) } + positionInScaledCanvas = points => points.map(point => point / 4) + render() { const { children, render = children } = this.props const { context } = this.state @@ -58,6 +60,7 @@ export default class Canvas extends Component { ? render({ ...this.state, clear: this.clear, + getPosition: this.positionInScaledCanvas, }) : null} diff --git a/client/src/components/footer.js b/client/src/components/footer.js index b8bfcac..532e618 100644 --- a/client/src/components/footer.js +++ b/client/src/components/footer.js @@ -1,16 +1,39 @@ import React from 'react' import styled from 'react-emotion' +import { FaGithub } from 'react-icons/fa' + +import Link from './outbound-link' import { position } from '../style' const Container = styled.footer` + display: flex; + justify-content: space-between; + align-items: center; box-sizing: border-box; background-color: #fffaf5; + border-top: 2px solid #c51104; width: 100%; padding: 1rem 0.5rem; ${position.absolute({ bottom: true })} ` -export default function Footer({ children }) { - return {children} +const GithubIcon = styled(FaGithub)` + font-size: 24px; +` + +export default function Footer() { + return ( + + + + + + #buildwithgatsby + + + ) } diff --git a/client/src/components/heart-canvas.js b/client/src/components/heart-canvas.js new file mode 100644 index 0000000..2934833 --- /dev/null +++ b/client/src/components/heart-canvas.js @@ -0,0 +1,29 @@ +import React from 'react' +import Canvas from './canvas' + +function HeartCanvas() { + return ( + + {({ context, x, y }) => { + const NUM_ROWS = Math.ceil(Math.sqrt(x)) + const blockSize = Math.ceil(x / NUM_ROWS) + + for (let i = 0; i < NUM_ROWS; i++) { + const x = i * blockSize + const numCols = Math.ceil(y / blockSize) + for (let j = 0; j < numCols; j++) { + const y = j * blockSize + const fontSize = Math.ceil(Math.sqrt(y / 2.5)) + context.font = `${fontSize}px sans-serif` + context.fillStyle = `rgba(255, 255, 255, ${Math.random()})` + context.fillText('❤', x / 2, y / 2) + } + } + + return null + }} + + ) +} + +export default HeartCanvas diff --git a/client/src/components/heart.js b/client/src/components/heart.js index 1b3102f..29955ed 100644 --- a/client/src/components/heart.js +++ b/client/src/components/heart.js @@ -1,23 +1,28 @@ import React from 'react' -import styled from 'react-emotion' +import styled, { css } from 'react-emotion' import { PULSE_ANIMATION } from '../style' const Container = styled.span` display: inline-block; - animation: 2s infinite ${PULSE_ANIMATION} - cubic-bezier(0.455, 0.03, 0.515, 0.955); - transition: 2s ease-in-out; - - :hover { - animation: none; - } + ${props => + props.animate && + css` + animation: 2s infinite ${PULSE_ANIMATION} + cubic-bezier(0.455, 0.03, 0.515, 0.955); + `} ` -export default function Heart() { +function Heart({ animate }) { return ( - + ❤️ ) } + +Heart.defaultProps = { + animate: true, +} + +export default Heart diff --git a/client/src/components/index.js b/client/src/components/index.js index 3a7f75b..7082875 100644 --- a/client/src/components/index.js +++ b/client/src/components/index.js @@ -1,3 +1,6 @@ export { default as Canvas } from './canvas' export { default as Heart } from './heart' +export { default as HeartCanvas } from './heart-canvas' export { default as Footer } from './footer' +export { default as LoveCanvas } from './love-canvas' +export { default as OutboundLink } from './outbound-link' diff --git a/client/src/components/love-canvas.js b/client/src/components/love-canvas.js new file mode 100644 index 0000000..06237af --- /dev/null +++ b/client/src/components/love-canvas.js @@ -0,0 +1,82 @@ +import React from 'react' +import styled from 'react-emotion' +import PropTypes from 'prop-types' + +import Canvas from './canvas' +import Heart from './heart' + +const Container = styled.div` + font-family: monospace; + font-size: 10vw; +` + +const Empty = () => ( + + {`{...`} + + {`}`} + +) + +/* + * TODO: implement fill algorithm + */ +function Love({ items }) { + if (items.length === 0) { + return + } + + const total = items.reduce((count, item) => { + return count + item.count + }, 0) + + return ( + { + const { x, y, context } = canvasArgs + + const gridSize = Math.ceil(Math.sqrt(items.length)) + const clone = items.slice(0) + + for (let i = 0; i < gridSize; i++) { + const blockSize = x / gridSize + const xPos = (i / gridSize) * x + + for (let j = 0; j < gridSize; j++) { + const yPos = (j / gridSize) * y + + const item = clone.shift() + + if (item) { + context.fillStyle = 'red' + context.fillRect(xPos / 2, yPos / 2, blockSize / 2, y / 2) + context.fillStyle = 'black' + context.fillText( + item.name, + (xPos + blockSize) / 4, + (yPos + blockSize) / 2 + ) + } + } + } + + return null + }} + /> + ) +} + +Love.defaultProps = { + items: [], +} + +Love.propTypes = { + items: PropTypes.arrayOf( + PropTypes.shape({ + count: PropTypes.number, + name: PropTypes.string, + }) + ), +} + +export default Love diff --git a/client/src/components/outbound-link.js b/client/src/components/outbound-link.js new file mode 100644 index 0000000..577b16d --- /dev/null +++ b/client/src/components/outbound-link.js @@ -0,0 +1,14 @@ +import React from 'react' +import styled from 'react-emotion' + +const Link = styled.a` + text-decoration: none; + color: inherit; +` + +Link.defaultProps = { + target: '_blank', + rel: 'noopener noreferrer', +} + +export default Link diff --git a/client/src/layouts/index.js b/client/src/layouts/index.js index a91f89a..15b3ac8 100644 --- a/client/src/layouts/index.js +++ b/client/src/layouts/index.js @@ -24,8 +24,16 @@ const Layout = ({ children }) => ( diff --git a/client/src/pages/index.js b/client/src/pages/index.js index 51a28e3..d1ad993 100644 --- a/client/src/pages/index.js +++ b/client/src/pages/index.js @@ -5,7 +5,7 @@ import { gql } from 'apollo-boost' import { Mutation } from 'react-apollo' import { navigate } from 'gatsby' -import { Canvas, Heart, Footer } from '../components' +import { HeartCanvas, Heart, Footer } from '../components' import { mediaQuery, position } from '../style' const Container = styled.div` @@ -24,23 +24,24 @@ const Container = styled.div` const Header = styled.header` box-sizing: border-box; background-color: #fffaf5; + border-bottom: 2px solid #c51104; width: 100%; padding: 1rem 0.25rem; ${position.absolute({ top: true })} ` -const Message = styled.p` - margin: 0; - padding: 0; - text-align: center; -` - -const Title = styled.h1` - margin: 0; - font-family: monospace; - font-size: 72px; - text-align: center; -` +const Title = styled.h1({ + margin: 0, + fontFamily: 'monospace', + textAlign: 'center', + fontSize: 40, + [mediaQuery('medium')]: { + fontSize: 48, + }, + [mediaQuery('large')]: { + fontSize: 60, + }, +}) const Form = styled.form({ width: '100%', @@ -58,9 +59,11 @@ const Explanation = styled.h2({ padding: 0, color: 'white', textAlign: 'center', - padding: '0.5rem 0', + padding: '0.5rem', margin: '0.5rem 0', - border: '2px solid white', + lineHeight: 1.5, + border: '4px solid #fffaf5', + backgroundColor: 'black', borderLeftWidth: 0, borderRightWidth: 0, fontSize: 16, @@ -111,6 +114,13 @@ Button.defaultProps = { type: 'submit', } +const MediumUp = styled.span({ + display: 'none', + [mediaQuery('medium')]: { + display: 'inline-block', + }, +}) + const handleSubmit = sendLove => { return ev => { ev.preventDefault() @@ -131,27 +141,7 @@ function Index() { `} children={sendLove => ( - - {({ context, x, y }) => { - const NUM_ROWS = 10 // x > 768 ? 25 : 15; - const blockSize = Math.ceil(x / NUM_ROWS) - const grid = new Array(NUM_ROWS) - .fill(undefined) - .map((_, index) => - new Array(Math.ceil(y / blockSize)) - .fill(undefined) - .map((_, yIndex) => [index * blockSize, yIndex * blockSize]) - ) - grid.forEach(row => { - row.forEach(([x, y]) => { - context.font = `${y / 35}px sans-serif` - context.fillText('❤️', x / 2, y / 2) - }) - }) - - return null - }} - +
{`{...`} @@ -161,19 +151,20 @@ function Index() { </Header> <Form onSubmit={handleSubmit(sendLove)}> <InputContainer> - <Input /> + <Input required={true} /> <Button> <MdSend /> </Button> </InputContainer> <Explanation> - What do you love? What fuels your fire? What are you passionate - about? Share it! + What do you love?{` `} + <MediumUp> + What fuels your fire? What are you passionate about? + </MediumUp>{' '} + Share it! </Explanation> </Form> - <Footer> - <Message>#buildwithgatsby</Message> - </Footer> + <Footer /> </Container> )} /> diff --git a/client/src/pages/love.js b/client/src/pages/love.js index b8824d5..eb5660a 100644 --- a/client/src/pages/love.js +++ b/client/src/pages/love.js @@ -1,6 +1,8 @@ import React from 'react' import styled from 'react-emotion' +import { LoveCanvas } from '../components' + const Container = styled.div` display: flex; flex-direction: column; @@ -9,7 +11,6 @@ const Container = styled.div` height: 100vh; width: 100vw; - background-color: #fe251b; overflow: hidden; position: relative; ` @@ -17,12 +18,37 @@ const Container = styled.div` /* * TODO: implement query */ -function Love() { - return ( - <Container> - <h1 css={{ color: 'white' }}>These are the results.</h1> - </Container> - ) +class Love extends React.Component { + state = { + something: false, + } + + render() { + return ( + <Container> + <LoveCanvas + items={[ + { + name: 'asdf', + count: 10, + }, + { + name: 'werr', + count: 10, + }, + { + name: 'hahah', + count: 10, + }, + { + name: 'sup', + count: 10, + }, + ]} + /> + </Container> + ) + } } export default Love diff --git a/netlify.toml b/netlify.toml index 5387a2f..67a1c70 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,4 +1,3 @@ [build] - base = "client" - command = "yarn build" + command = "cd client && yarn build" publish = "client/public"