From 65e155f9c6ddf9633f3e158545d3345484d65444 Mon Sep 17 00:00:00 2001 From: Frank Sauerburger <frank@sauerburger.com> Date: Tue, 26 Mar 2019 12:18:49 +0100 Subject: [PATCH] Style most components --- app/components/App.jsx | 11 ++- app/components/InputPanel.jsx | 17 +++- app/components/OutputPanel.jsx | 15 +++- app/components/RouteTile.jsx | 65 +++++++++++++-- app/helpers/index.js | 7 ++ app/reducers/index.js | 8 +- app/styles/application.css | 6 +- package-lock.json | 139 +++++++++++++++++++++++++++++++-- package.json | 3 +- 9 files changed, 243 insertions(+), 28 deletions(-) diff --git a/app/components/App.jsx b/app/components/App.jsx index 21d6274..5627eab 100644 --- a/app/components/App.jsx +++ b/app/components/App.jsx @@ -1,12 +1,19 @@ import React from 'react' import OutputPanel from './../containers/OutputPanel' import InputPanel from './../containers/InputPanel' +import styled from 'styled-components' +const Div = styled.div` + @media only screen and (min-width: 820px) { + display: grid; + grid-template-columns: 1fr 1fr; + } +` const App = () => ( - <div> + <Div> <InputPanel /> <OutputPanel /> - </div> + </Div> ) export default App diff --git a/app/components/InputPanel.jsx b/app/components/InputPanel.jsx index b59a6b6..b05a8f0 100644 --- a/app/components/InputPanel.jsx +++ b/app/components/InputPanel.jsx @@ -1,18 +1,27 @@ -import React from 'react'; +import React from 'react' import PropTypes from 'prop-types' import RouteTile from './RouteTile' +import styled from 'styled-components' + +const Div = styled.div` + background-color: #fff; + margin: 1em; + border: 1px solid #ccc; + padding: 1em; +` const InputPanel = ({routes, onAdd, onDelete, onClear, onUpdate}) => ( - <div> + <Div> {routes.map((stops, i) => ( <RouteTile + title={"Route " + (i+1)} onDelete={() => onDelete(i)} onClear={() => onClear(i)} onAdd={(url) => onUpdate(i, url)} key={i} stops={stops} /> ))} - <RouteTile onAdd={onAdd} stops={[]} /> - </div> + <RouteTile title={"Route " + (routes.length+1)} onAdd={onAdd} stops={[]} /> + </Div> ) InputPanel.propTypes = { diff --git a/app/components/OutputPanel.jsx b/app/components/OutputPanel.jsx index 2572612..e9263df 100644 --- a/app/components/OutputPanel.jsx +++ b/app/components/OutputPanel.jsx @@ -2,12 +2,19 @@ import React from 'react' import PropTypes from 'prop-types' import RouteTile from './RouteTile' import { buildUrl } from '../helpers' +import styled from 'styled-components' + +const Div = styled.div` + background-color: #fff; + margin: 1em; + padding: 1em; + border: 1px solid #ccc; +` const OutputPanel = ({stops}) => ( - <div> - <h2>Complete Route</h2> - <RouteTile url={buildUrl(stops)} stops={stops} /> - </div> + <Div> + <RouteTile title="Complete Route" url={buildUrl(stops)} stops={stops} /> + </Div> ) OutputPanel.propTypes = { diff --git a/app/components/RouteTile.jsx b/app/components/RouteTile.jsx index 4881fca..e2afc3c 100644 --- a/app/components/RouteTile.jsx +++ b/app/components/RouteTile.jsx @@ -1,11 +1,56 @@ import React from 'react' import PropTypes from 'prop-types' +import styled from 'styled-components' -const RouteTile = ({stops, onAdd, url, onDelete, onClear}) => { +const Button = styled.input` + color: #fff; + background-color: #0e2f43; + border: none; + font-size: 24px; + line-height: 34px; + height: 34px; + padding: 0; + width: 34px; + margin: 1px; + + &:hover { + background-color: #2d8891; + } +` + +const TextField = styled.input` + color: #000; + background-color: #eee; + border: none; + font-size: 24px; + line-height: 34px; + height: 34px; + padding: 0; + text-align: center; + width: 10em; + margin: 1px; + box-sizing: border-box; + + + &:focus { + border: 1px solid #2d8891; + } +` + +const Div = styled.div` + border: 1px dotted #aaa; + background-color: #eee; + font-family: monospace; + padding: 1em; +` + +const RouteTile = ({title, stops, onAdd, url, onDelete, onClear}) => { let input + let output return stops.length == 0 && url === undefined ? <div> + <h2>{title}</h2> <form onSubmit={(e) => { e.preventDefault() if (input.value.trim() == "") { @@ -14,15 +59,22 @@ const RouteTile = ({stops, onAdd, url, onDelete, onClear}) => { onAdd(input.value.trim()) input.value = "" }}> - <input type="text" ref={node => {input = node}} /> - <input type="submit" value="+" /> + <TextField type="text" placeholder="Add link to route" ref={node => {input = node}} /> + <Button type="submit" value="+" /> </form> </div> : <div> - { url === undefined && <input onClick={onDelete} type="button" value="-" /> } - { url === undefined && <input onClick={onClear} type="button" value="🖉" /> } - { url !== undefined && <div className="url">{url}</div> } + <h2>{title}</h2> + { url === undefined && <Button style={{float: 'right'}} onClick={onDelete} type="button" value="🗙" /> } + { url === undefined && <Button style={{float: 'right'}} onClick={onClear} type="button" value="🖉" /> } + { url !== undefined && <Div + onClick={(e) => { + var range = document.createRange(); + range.selectNode(e.currentTarget); + window.getSelection().removeAllRanges(); + window.getSelection().addRange(range); + }} className="url">{url}</Div> } <ul> {stops.map((stop, i) => ( <li key={i}>{stop}</li> @@ -37,6 +89,7 @@ RouteTile.propTypes = { onAdd: PropTypes.func, onDelete: PropTypes.func, onClear: PropTypes.func, + title: PropTypes.string.isRequired, } export default RouteTile diff --git a/app/helpers/index.js b/app/helpers/index.js index 2ba3434..c1b0986 100644 --- a/app/helpers/index.js +++ b/app/helpers/index.js @@ -25,3 +25,10 @@ export const buildUrl = (stops) => { } return "https://www.google.com/maps/dir/" + stops.join("/") + "/" } + +export const dropTail = (array) => { + while (array.length > 0 && array.slice(-1)[0].length == 0) { + array.pop() + } + return array +} diff --git a/app/reducers/index.js b/app/reducers/index.js index a5a227d..ce6d723 100644 --- a/app/reducers/index.js +++ b/app/reducers/index.js @@ -1,5 +1,5 @@ import * as at from '../actions/actionTypes' -import { extractStops } from '../helpers' +import { extractStops, dropTail } from '../helpers' const initialState = { @@ -12,13 +12,13 @@ const reducer = (state = initialState, action) => { return {routes: state.routes.concat([extractStops(action.payload)])} case at.DELETE_ROUTE: - return {routes: state.routes.filter((v, i) => i != action.payload)} + return {routes: dropTail(state.routes.filter((v, i) => i != action.payload))} case at.CLEAR_ROUTE: - return {routes: state.routes.map((v, i) => i == action.payload ? [] : v)} + return {routes: dropTail(state.routes.map((v, i) => i == action.payload ? [] : v))} case at.UPDATE_URL: - return {routes: state.routes.map((v, i) => i == action.payload.index ? extractStops(action.payload.url) : v)} + return {routes: dropTail(state.routes.map((v, i) => i == action.payload.index ? extractStops(action.payload.url) : v))} default: return state diff --git a/app/styles/application.css b/app/styles/application.css index 88eab34..881569e 100644 --- a/app/styles/application.css +++ b/app/styles/application.css @@ -21,8 +21,11 @@ header h1 { margin: 0.8em auto 0.4em; } -header { +h1, h2 { font-family: "Suprema", sans-serif; +} + +header { border-top: 1px solid #0e2f43; margin: 0px; background-color: #0e2f43; @@ -34,6 +37,7 @@ main { margin: 0px auto 5em; padding: 0em 1em; text-align: justify; + position: relative; } @media only screen and (min-width: 820px) { diff --git a/package-lock.json b/package-lock.json index 56f0aa9..615c2c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,57 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/helper-annotate-as-pure": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", + "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/types": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.0.tgz", + "integrity": "sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA==", + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.11", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" + } + } + }, + "@emotion/is-prop-valid": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.7.3.tgz", + "integrity": "sha512-uxJqm/sqwXw3YPA5GXX365OBcJGFtxUVkB6WyezqFHlNe9jqUWH5ur2O2M8dGBz61kn1g3ZBlzUunFQXQIClhA==", + "requires": { + "@emotion/memoize": "0.7.1" + } + }, + "@emotion/memoize": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.1.tgz", + "integrity": "sha512-Qv4LTqO11jepd5Qmlp3M1YEjBumoTHcHFdgPTQ+sFlIL5myi/7xu/POwP7IRu6odBdmLXdtIs1D6TuW6kbwbbg==" + }, + "@emotion/unitless": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.3.tgz", + "integrity": "sha512-4zAPlpDEh2VwXswwr/t8xGNDGg8RQiPxtxZ3qQEXyQsBV39ptTdESCjuBvGze1nLMVrxmTIKmnO/nAV8Tqjjzg==" + }, "accepts": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", @@ -512,6 +563,17 @@ "babel-runtime": "^6.22.0" } }, + "babel-plugin-styled-components": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.10.0.tgz", + "integrity": "sha512-sQVKG8irFXx14ZfaK1bBePirfkacl3j8nZwSZK+ZjsbnadRHKQTbhXbe/RB1vT6Vgkz45E+V95LBq4KqdhZUNw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-module-imports": "^7.0.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.10" + } + }, "babel-plugin-syntax-async-functions": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", @@ -533,8 +595,7 @@ "babel-plugin-syntax-jsx": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", - "dev": true + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" }, "babel-plugin-syntax-trailing-function-commas": { "version": "6.22.0", @@ -1723,6 +1784,11 @@ "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", "dev": true }, + "camelize": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", + "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + }, "caniuse-lite": { "version": "1.0.30000951", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000951.tgz", @@ -2447,6 +2513,21 @@ "randombytes": "^2.0.0" } }, + "css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=" + }, + "css-to-react-native": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-2.3.0.tgz", + "integrity": "sha512-IhR7bNIrCFwbJbKZOAjNDZdwpsbjTN6f1agXeELHDqg1wHPA8c2QLruttKOW7hgMGetkfraRJCIEMrptifBfVw==", + "requires": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^3.3.0" + } + }, "damerau-levenshtein": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz", @@ -3377,8 +3458,7 @@ "esutils": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" }, "etag": { "version": "1.8.1", @@ -4323,8 +4403,7 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "has-symbols": { "version": "1.0.0", @@ -5046,6 +5125,11 @@ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, + "memoize-one": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.0.0.tgz", + "integrity": "sha512-7g0+ejkOaI9w5x6LvQwmj68kUj6rxROywPSCqmclG/HBacmFnZqhVscQ8kovkn9FBCNJmOz6SY42+jnvZzDWdw==" + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -5732,6 +5816,11 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -7001,6 +7090,44 @@ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, + "styled-components": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-4.2.0.tgz", + "integrity": "sha512-L/LzkL3ZbBhqIVHdR7DbYujy4tqvTNRfc+4JWDCYyhTatI+8CRRQUmdaR0+ARl03DWsfKLhjewll5uNLrqrl4A==", + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@emotion/is-prop-valid": "^0.7.3", + "@emotion/unitless": "^0.7.0", + "babel-plugin-styled-components": ">= 1", + "css-to-react-native": "^2.2.2", + "memoize-one": "^5.0.0", + "prop-types": "^15.5.4", + "react-is": "^16.6.0", + "stylis": "^3.5.0", + "stylis-rule-sheet": "^0.0.10", + "supports-color": "^5.5.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "stylis": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-3.5.4.tgz", + "integrity": "sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q==" + }, + "stylis-rule-sheet": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz", + "integrity": "sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw==" + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", diff --git a/package.json b/package.json index d899e89..33f6457 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "react": "^16.2", "react-dom": "^16.2", "react-redux": "~5.0.6", - "redux": "~3.7.2" + "redux": "~3.7.2", + "styled-components": "^4.2.0" }, "devDependencies": { "auto-reload-brunch": "^2", -- GitLab