Skip to content

Commit

Permalink
Merge pull request #261 from NGMarmaduke/map-controlls
Browse files Browse the repository at this point in the history
Add Map `Control` and `ControlGroup` components
  • Loading branch information
NGMarmaduke authored May 8, 2017
2 parents 1a5bba6 + 1ec5e64 commit f891451
Show file tree
Hide file tree
Showing 21 changed files with 323 additions and 0 deletions.
2 changes: 2 additions & 0 deletions components/Icon/Icon.css
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@
.facebook svg,
.filter svg,
.map svg,
.minus svg,
.pintrest svg,
.plus svg,
.radio svg,
.search svg,
.tick svg,
Expand Down
4 changes: 4 additions & 0 deletions components/Icon/icons.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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),
Expand Down
12 changes: 12 additions & 0 deletions components/Icon/icons/icon-minus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions components/Icon/icons/icon-plus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions components/Map/BaseMap.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.root, .map {
height: 100%;
width: 100%;
}

.map {
Expand Down
26 changes: 26 additions & 0 deletions components/Map/Control/Control.css
Original file line number Diff line number Diff line change
@@ -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);
}
20 changes: 20 additions & 0 deletions components/Map/Control/Control.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React, { PropTypes } from 'react';
import cx from 'classnames';

import css from './Control.css';

const Control = ({ className, children, ...rest }) => (
<button
className={ cx(css.root, className) }
{ ...rest }
>
{ children }
</button>
);

Control.propTypes = {
className: PropTypes.string,
children: PropTypes.node.isRequired,
};

export default Control;
9 changes: 9 additions & 0 deletions components/Map/Control/Control.test.js
Original file line number Diff line number Diff line change
@@ -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(<Control>button</Control>, div);
});
6 changes: 6 additions & 0 deletions components/Map/Control/ControlIcon.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.minus svg,
.plus svg {
stroke: transparent;
fill: currentColor;
stroke-linecap: round;
}
6 changes: 6 additions & 0 deletions components/Map/Control/ControlIcon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import iconHelper from '../../Icon/iconHelper';

import icons from './icons';
import css from './ControlIcon.css';

export default iconHelper(icons, css);
16 changes: 16 additions & 0 deletions components/Map/Control/Controls.story.js
Original file line number Diff line number Diff line change
@@ -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', () => (
<Control onClick={ action('click') }>
<ControlIcon name="plus" />
</Control>
))
.add('Control with text', () => (
<Control onClick={ action('click') }>
Just Text
</Control>
));
9 changes: 9 additions & 0 deletions components/Map/Control/icons.js
Original file line number Diff line number Diff line change
@@ -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),
};
12 changes: 12 additions & 0 deletions components/Map/Control/icons/icon-minus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions components/Map/Control/icons/icon-plus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions components/Map/ControlGroup/ControlGroup.css
Original file line number Diff line number Diff line change
@@ -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);
}
21 changes: 21 additions & 0 deletions components/Map/ControlGroup/ControlGroup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React, { Children, cloneElement, PropTypes } from 'react';
import cx from 'classnames';

import css from './ControlGroup.css';

const ControlGroup = ({ children, className }) => (
<div className={ cx(css.root, css.controlGroup, className) }>
{ Children.map(children, child =>
cloneElement(child, {
className: cx(css.control, child.props.className),
})
) }
</div>
);

ControlGroup.propTypes = {
className: PropTypes.string,
children: PropTypes.node.isRequired,
};

export default ControlGroup;
17 changes: 17 additions & 0 deletions components/Map/ControlGroup/ControlGroup.story.js
Original file line number Diff line number Diff line change
@@ -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', () => (
<ControlGroup>
<Control onClick={ action('click plus') }>
<ControlIcon name="plus" />
</Control>
<Control onClick={ action('click minus') }>
<ControlIcon name="minus" />
</Control>
</ControlGroup>
));
13 changes: 13 additions & 0 deletions components/Map/ControlGroup/ControlGroup.test.js
Original file line number Diff line number Diff line change
@@ -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(
<ControlGroup>
<button>child</button>
</ControlGroup>,
div);
});
13 changes: 13 additions & 0 deletions components/Map/ControlLayer/ControlLayer.css
Original file line number Diff line number Diff line change
@@ -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);
}
66 changes: 66 additions & 0 deletions components/Map/ControlLayer/ControlLayer.js
Original file line number Diff line number Diff line change
@@ -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 (
<div className={ cx(css.root, className) }>
<ControlGroup className={ cx(css.controlGroup, controlGroupClassName) }>
<Control onClick={ this.handleZoomIn }>
<ControlIcon name="plus" />
</Control>
<Control onClick={ this.handleZoomOut }>
<ControlIcon name="minus" />
</Control>
</ControlGroup>
{ cloneElement(child, {
zoom,
onMoveEnd: this.handleMoveEnd,
}) }
</div>
);
}
}
14 changes: 14 additions & 0 deletions components/Map/ControlLayer/ControlLayer.story.js
Original file line number Diff line number Diff line change
@@ -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', () => (
<div style={ { height: '96vh' } }>
<ControlLayer>
<BaseMap />
</ControlLayer>
</div>
));

0 comments on commit f891451

Please sign in to comment.