From da2d34e8cff9e8fc2e90a62eaa34e154cab3230b Mon Sep 17 00:00:00 2001 From: Nick Maher Date: Thu, 4 May 2017 13:47:51 +0100 Subject: [PATCH 1/2] Add Map `Control` and `ControlGroup` components --- components/Icon/Icon.css | 2 ++ components/Icon/icons.js | 4 +++ components/Icon/icons/icon-minus.svg | 12 +++++++ components/Icon/icons/icon-plus.svg | 12 +++++++ components/Map/Control/Control.css | 26 +++++++++++++++ components/Map/Control/Control.js | 20 ++++++++++++ components/Map/Control/Control.test.js | 9 ++++++ components/Map/Control/ControlIcon.css | 6 ++++ components/Map/Control/ControlIcon.js | 6 ++++ components/Map/Control/Controls.story.js | 16 ++++++++++ components/Map/Control/icons.js | 9 ++++++ components/Map/Control/icons/icon-minus.svg | 12 +++++++ components/Map/Control/icons/icon-plus.svg | 12 +++++++ components/Map/ControlGroup/ControlGroup.css | 32 +++++++++++++++++++ components/Map/ControlGroup/ControlGroup.js | 21 ++++++++++++ .../Map/ControlGroup/ControlGroup.story.js | 17 ++++++++++ .../Map/ControlGroup/ControlGroup.test.js | 13 ++++++++ 17 files changed, 229 insertions(+) create mode 100644 components/Icon/icons/icon-minus.svg create mode 100644 components/Icon/icons/icon-plus.svg create mode 100644 components/Map/Control/Control.css create mode 100644 components/Map/Control/Control.js create mode 100644 components/Map/Control/Control.test.js create mode 100644 components/Map/Control/ControlIcon.css create mode 100644 components/Map/Control/ControlIcon.js create mode 100644 components/Map/Control/Controls.story.js create mode 100644 components/Map/Control/icons.js create mode 100644 components/Map/Control/icons/icon-minus.svg create mode 100644 components/Map/Control/icons/icon-plus.svg create mode 100644 components/Map/ControlGroup/ControlGroup.css create mode 100644 components/Map/ControlGroup/ControlGroup.js create mode 100644 components/Map/ControlGroup/ControlGroup.story.js create mode 100644 components/Map/ControlGroup/ControlGroup.test.js diff --git a/components/Icon/Icon.css b/components/Icon/Icon.css index 75dfc9043..6a25d3724 100644 --- a/components/Icon/Icon.css +++ b/components/Icon/Icon.css @@ -46,7 +46,9 @@ .facebook svg, .filter svg, .map svg, +.minus svg, .pintrest svg, +.plus svg, .radio svg, .search svg, .tick svg, diff --git a/components/Icon/icons.js b/components/Icon/icons.js index e34f26d70..7fe673a6e 100644 --- a/components/Icon/icons.js +++ b/components/Icon/icons.js @@ -26,11 +26,13 @@ import globe from './icons/icon-globe.svg'; import location from './icons/icon-location.svg'; import manage from './icons/icon-manage.svg'; import map from './icons/icon-map.svg'; +import minus from './icons/icon-minus.svg'; import notification from './icons/icon-notification.svg'; import percentage from './icons/icon-percentage.svg'; import pintrest from './icons/icon-pintrest.svg'; import play from './icons/icon-play.svg'; import playC from './icons/icon-play-c.svg'; +import plus from './icons/icon-plus.svg'; import radio from './icons/icon-radio.svg'; import search from './icons/icon-search.svg'; import shield from './icons/icon-shield.svg'; @@ -78,10 +80,12 @@ export default { location: svgClean(location), manage: svgClean(manage), map: svgClean(map), + minus: svgClean(minus), notification: svgClean(notification), percentage: svgClean(percentage), pintrest: svgClean(pintrest), play: svgClean(play), + plus: svgClean(plus), radio: svgClean(radio), search: svgClean(search), shield: svgClean(shield), diff --git a/components/Icon/icons/icon-minus.svg b/components/Icon/icons/icon-minus.svg new file mode 100644 index 000000000..0ef853858 --- /dev/null +++ b/components/Icon/icons/icon-minus.svg @@ -0,0 +1,12 @@ + + + + Artboard Copy + Created with Sketch. + + + + + + + \ No newline at end of file diff --git a/components/Icon/icons/icon-plus.svg b/components/Icon/icons/icon-plus.svg new file mode 100644 index 000000000..9c2b0ffb4 --- /dev/null +++ b/components/Icon/icons/icon-plus.svg @@ -0,0 +1,12 @@ + + + + Artboard + Created with Sketch. + + + + + + + \ No newline at end of file diff --git a/components/Map/Control/Control.css b/components/Map/Control/Control.css new file mode 100644 index 000000000..d6db7fa5f --- /dev/null +++ b/components/Map/Control/Control.css @@ -0,0 +1,26 @@ +.root { + background: var(--color-white); + border-color: var(--color-greyLighter); + border-radius: 2px; + border-style: solid; + border-width: 1px; + color: var(--color-grey); + cursor: pointer; + display: inline-block; + font-family: var(--font-avenir); + font-size: var(--fontsize-small-i); + font-weight: 700; + line-height: 1; + padding: var(--size-sm-ii); + text-decoration: none; + text-transform: uppercase; +} + +.root svg { + vertical-align: top; +} + +.root:hover { + background: var(--color-greyLightest); + color: var(--color-greyDark); +} \ No newline at end of file diff --git a/components/Map/Control/Control.js b/components/Map/Control/Control.js new file mode 100644 index 000000000..5399c716f --- /dev/null +++ b/components/Map/Control/Control.js @@ -0,0 +1,20 @@ +import React, { PropTypes } from 'react'; +import cx from 'classnames'; + +import css from './Control.css'; + +const Control = ({ className, children, ...rest }) => ( + +); + +Control.propTypes = { + className: PropTypes.string, + children: PropTypes.node.isRequired, +}; + +export default Control; \ No newline at end of file diff --git a/components/Map/Control/Control.test.js b/components/Map/Control/Control.test.js new file mode 100644 index 000000000..a44d3f659 --- /dev/null +++ b/components/Map/Control/Control.test.js @@ -0,0 +1,9 @@ +import React from 'react'; +import { render } from 'react-dom'; + +import Control from './Control'; + +it('renders without crashing', () => { + const div = document.createElement('div'); + render(button, div); +}); \ No newline at end of file diff --git a/components/Map/Control/ControlIcon.css b/components/Map/Control/ControlIcon.css new file mode 100644 index 000000000..1bb517e45 --- /dev/null +++ b/components/Map/Control/ControlIcon.css @@ -0,0 +1,6 @@ +.minus svg, +.plus svg { + stroke: transparent; + fill: currentColor; + stroke-linecap: round; +} \ No newline at end of file diff --git a/components/Map/Control/ControlIcon.js b/components/Map/Control/ControlIcon.js new file mode 100644 index 000000000..5071fe51d --- /dev/null +++ b/components/Map/Control/ControlIcon.js @@ -0,0 +1,6 @@ +import iconHelper from '../../Icon/iconHelper'; + +import icons from './icons'; +import css from './ControlIcon.css'; + +export default iconHelper(icons, css); \ No newline at end of file diff --git a/components/Map/Control/Controls.story.js b/components/Map/Control/Controls.story.js new file mode 100644 index 000000000..02b9afd68 --- /dev/null +++ b/components/Map/Control/Controls.story.js @@ -0,0 +1,16 @@ +import React from 'react'; +import { storiesOf, action } from '@kadira/storybook'; +import ControlIcon from './ControlIcon'; +import Control from './Control'; + +storiesOf('Map Control', module) +.add('Control', () => ( + + + +)) +.add('Control with text', () => ( + + Just Text + +)); \ No newline at end of file diff --git a/components/Map/Control/icons.js b/components/Map/Control/icons.js new file mode 100644 index 000000000..cc6750f7f --- /dev/null +++ b/components/Map/Control/icons.js @@ -0,0 +1,9 @@ +import svgClean from '../../../utils/svgClean/svgClean'; + +import minus from './icons/icon-minus.svg'; +import plus from './icons/icon-plus.svg'; + +export default { + minus: svgClean(minus), + plus: svgClean(plus), +}; \ No newline at end of file diff --git a/components/Map/Control/icons/icon-minus.svg b/components/Map/Control/icons/icon-minus.svg new file mode 100644 index 000000000..d5d9fdbee --- /dev/null +++ b/components/Map/Control/icons/icon-minus.svg @@ -0,0 +1,12 @@ + + + + icon_minus_16px + Created with Sketch. + + + + + + + \ No newline at end of file diff --git a/components/Map/Control/icons/icon-plus.svg b/components/Map/Control/icons/icon-plus.svg new file mode 100644 index 000000000..4d9eb1d44 --- /dev/null +++ b/components/Map/Control/icons/icon-plus.svg @@ -0,0 +1,12 @@ + + + + icon_plus_16px + Created with Sketch. + + + + + + + \ No newline at end of file diff --git a/components/Map/ControlGroup/ControlGroup.css b/components/Map/ControlGroup/ControlGroup.css new file mode 100644 index 000000000..c36ebb243 --- /dev/null +++ b/components/Map/ControlGroup/ControlGroup.css @@ -0,0 +1,32 @@ +.control { + border-radius: 0; + border-top-width: 0; + border-bottom-width: 0; + display: block +} + +.control:first-child { + border-top-width: 1px; + border-top-left-radius: 2px; + border-top-right-radius: 2px; +} + +.control:last-child { + border-bottom-width: 1px; + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; +} + +.control + .control { + padding-top: 0; +} + +.control + .control:before { + content: ''; + display: block; + border-top: 1px solid var(--color-greyLighter); + padding-bottom: calc(var(--size-sm-ii) - 1px); + box-sizing: border-box; + margin-left: calc(var(--size-sm-iv) * -1); + margin-right: calc(var(--size-sm-iv) * -1); +} \ No newline at end of file diff --git a/components/Map/ControlGroup/ControlGroup.js b/components/Map/ControlGroup/ControlGroup.js new file mode 100644 index 000000000..876192acf --- /dev/null +++ b/components/Map/ControlGroup/ControlGroup.js @@ -0,0 +1,21 @@ +import React, { Children, cloneElement, PropTypes } from 'react'; +import cx from 'classnames'; + +import css from './ControlGroup.css'; + +const ControlGroup = ({ children, className }) => ( +
+ { Children.map(children, child => + cloneElement(child, { + className: cx(css.control, child.props.className), + }) + ) } +
+); + +ControlGroup.propTypes = { + className: PropTypes.string, + children: PropTypes.node.isRequired, +}; + +export default ControlGroup; \ No newline at end of file diff --git a/components/Map/ControlGroup/ControlGroup.story.js b/components/Map/ControlGroup/ControlGroup.story.js new file mode 100644 index 000000000..70aa6b69d --- /dev/null +++ b/components/Map/ControlGroup/ControlGroup.story.js @@ -0,0 +1,17 @@ +import React from 'react'; +import { storiesOf, action } from '@kadira/storybook'; +import ControlIcon from '../Control/ControlIcon'; +import Control from '../Control/Control'; +import ControlGroup from './ControlGroup'; + +storiesOf('Map Control', module) +.add('ControlGroup', () => ( + + + + + + + + +)); \ No newline at end of file diff --git a/components/Map/ControlGroup/ControlGroup.test.js b/components/Map/ControlGroup/ControlGroup.test.js new file mode 100644 index 000000000..87f85d092 --- /dev/null +++ b/components/Map/ControlGroup/ControlGroup.test.js @@ -0,0 +1,13 @@ +import React from 'react'; +import { render } from 'react-dom'; + +import ControlGroup from './ControlGroup'; + +it('renders without crashing', () => { + const div = document.createElement('div'); + render( + + + , + div); +}); \ No newline at end of file From 1ec5e64e16ba4a4a541abac15029a2894017d01d Mon Sep 17 00:00:00 2001 From: Nick Maher Date: Fri, 5 May 2017 15:56:27 +0100 Subject: [PATCH 2/2] Add `ControlLayer` component to for use with `Map` components --- components/Map/BaseMap.css | 1 + components/Map/ControlLayer/ControlLayer.css | 13 ++++ components/Map/ControlLayer/ControlLayer.js | 66 +++++++++++++++++++ .../Map/ControlLayer/ControlLayer.story.js | 14 ++++ 4 files changed, 94 insertions(+) create mode 100644 components/Map/ControlLayer/ControlLayer.css create mode 100644 components/Map/ControlLayer/ControlLayer.js create mode 100644 components/Map/ControlLayer/ControlLayer.story.js diff --git a/components/Map/BaseMap.css b/components/Map/BaseMap.css index e5c0204bf..fb9e96b3c 100644 --- a/components/Map/BaseMap.css +++ b/components/Map/BaseMap.css @@ -1,5 +1,6 @@ .root, .map { height: 100%; + width: 100%; } .map { diff --git a/components/Map/ControlLayer/ControlLayer.css b/components/Map/ControlLayer/ControlLayer.css new file mode 100644 index 000000000..8b1611fb1 --- /dev/null +++ b/components/Map/ControlLayer/ControlLayer.css @@ -0,0 +1,13 @@ +.root { + width: 100%; + height: 100%; + position: relative; +} + +.controlGroup { + position: absolute; + bottom: 0; + left: 0; + margin: var(--size-regular); + z-index: var(--z-mapControls); +} \ No newline at end of file diff --git a/components/Map/ControlLayer/ControlLayer.js b/components/Map/ControlLayer/ControlLayer.js new file mode 100644 index 000000000..4e3d975d8 --- /dev/null +++ b/components/Map/ControlLayer/ControlLayer.js @@ -0,0 +1,66 @@ +import React, { PropTypes, Component, cloneElement } from 'react'; +import cx from 'classnames'; + +import Control from '../Control/Control'; +import ControlGroup from '../ControlGroup/ControlGroup'; +import ControlIcon from '../Control/ControlIcon'; + +import css from './ControlLayer.css'; + +import { DEFAULT_ZOOM } from '../../../constants/mapbox'; + +export default class ControlLayer extends Component { + static propTypes = { + className: PropTypes.string, + controlGroupClassName: PropTypes.string, + children: PropTypes.element.isRequired, + }; + + constructor(props) { + super(props); + const { children: { zoom } } = props; + + this.state = { + zoom: zoom || DEFAULT_ZOOM, + }; + } + + handleZoomOut = () => { + this.setState(({ zoom }) => ({ zoom: zoom - 1 })); + }; + + handleZoomIn = () => { + this.setState(({ zoom }) => ({ zoom: zoom + 1 })); + }; + + handleMoveEnd = (...args) => { + const { children: child } = this.props; + const { onMoveEnd: childOnMoveEnd } = child.props; + const { zoom } = args[1]; + + this.setState({ zoom }); + if (typeof childOnMoveEnd === 'function') childOnMoveEnd(...args); + }; + + render() { + const { children: child, className, controlGroupClassName } = this.props; + const { zoom } = this.state; + + return ( +
+ + + + + + + + + { cloneElement(child, { + zoom, + onMoveEnd: this.handleMoveEnd, + }) } +
+ ); + } +} \ No newline at end of file diff --git a/components/Map/ControlLayer/ControlLayer.story.js b/components/Map/ControlLayer/ControlLayer.story.js new file mode 100644 index 000000000..31cca875b --- /dev/null +++ b/components/Map/ControlLayer/ControlLayer.story.js @@ -0,0 +1,14 @@ +import React from 'react'; +import { storiesOf } from '@kadira/storybook'; + +import ControlLayer from './ControlLayer'; +import BaseMap from '../BaseMap'; + +storiesOf('Map Control Layer', module) + .add('Default', () => ( +
+ + + +
+ )); \ No newline at end of file