diff --git a/client/less/drawers.less b/client/less/drawers.less new file mode 100644 index 0000000000..7a1cf51c05 --- /dev/null +++ b/client/less/drawers.less @@ -0,0 +1,108 @@ +/* + * based off of https://github.com/gitterHQ/sidecar + * license: MIT + */ +.drawer { + width:500px; + + z-index: 20000; + position: fixed; + top: 0; + bottom: 0; + right: 0; + + display: -webkit-flex; + display: flex; + -webkit-flex-direction: row; + flex-direction: row; + background-color: @body-bg; + border-left: 1px solid #ddd; + box-shadow: -12px 0 18px 0 rgba(50, 50, 50, 0.1); + + transition: transform 0.3s cubic-bezier(0.16, 0.22, 0.22, 1.7); + + &.is-collapsed:not(.is-loading) { + -webkit-transform: translateX(110%); + transform: translateX(110%); + } + + /* Add some "extension" so that there isn't a gap + * when we translate(via animation) more than 100% */ + &:after { + content: ''; + + z-index: -1; + position: absolute; + top: 0; + left: 100%; + bottom: 0; + right: -100%; + + background-color: @body-bg; + } + iframe { + width: 100%; + height: 100%; + } +} + +.drawer-action-bar { + position: absolute; + top: 0; + right: 0; + + display: -webkit-flex; + display: flex; + justify-content: flex-end; + + padding-bottom: 5px; + padding-right:10px; + padding-top:5px; + z-index: 100; +} + +.drawer-action-item { + display: -webkit-flex; + display: flex; + /* main axis */ + justify-content: center; + /* cross axis */ + align-items: center; + + width: 40px; + height: 40px; + + padding-left: 0; + padding-right: 0; + + opacity: 0.65; + background: none; + background-position: center center; + background-repeat: no-repeat; + background-size: 22px 22px; + border: 0; + outline: none; + + cursor: pointer; + cursor: hand; + + transition: all 0.2s ease; + + &:hover, + &:focus { + opacity: 1; + } + + &:active { + filter: hue-rotate(80deg) saturate(150); + } +} + +.drawer-action-pop-out { + margin-right: -4px; + background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMDAgMTcxLjQyOSIgZmlsbD0iIzNhMzEzMyI+PHBhdGggZD0iTTE1Ny4xNDMsMTAzLjU3MXYzNS43MTRjMCw4Ljg1NC0zLjE0NCwxNi40MjYtOS40MzEsMjIuNzEzcy0xMy44NTgsOS40MzEtMjIuNzEyLDkuNDMxSDMyLjE0MyBjLTguODU0LDAtMTYuNDI1LTMuMTQ0LTIyLjcxMi05LjQzMVMwLDE0OC4xNCwwLDEzOS4yODVWNDYuNDI5YzAtOC44NTQsMy4xNDQtMTYuNDI1LDkuNDMxLTIyLjcxMiBjNi4yODctNi4yODcsMTMuODU4LTkuNDMxLDIyLjcxMi05LjQzMWg3OC41NzJjMS4wNDEsMCwxLjg5NiwwLjMzNSwyLjU2NiwxLjAwNGMwLjY3LDAuNjcsMS4wMDQsMS41MjUsMS4wMDQsMi41NjdWMjUgYzAsMS4wNDItMC4zMzQsMS44OTctMS4wMDQsMi41NjdjLTAuNjcsMC42Ny0xLjUyNSwxLjAwNC0yLjU2NiwxLjAwNEgzMi4xNDNjLTQuOTExLDAtOS4xMTUsMS43NDktMTIuNjEyLDUuMjQ2IHMtNS4yNDYsNy43MDEtNS4yNDYsMTIuNjEydjkyLjg1NmMwLDQuOTExLDEuNzQ5LDkuMTE1LDUuMjQ2LDEyLjYxMnM3LjcwMSw1LjI0NSwxMi42MTIsNS4yNDVIMTI1YzQuOTEsMCw5LjExNS0xLjc0OCwxMi42MTEtNS4yNDUgYzMuNDk3LTMuNDk3LDUuMjQ2LTcuNzAxLDUuMjQ2LTEyLjYxMnYtMzUuNzE0YzAtMS4wNDIsMC4zMzQtMS44OTcsMS4wMDQtMi41NjdjMC42Ny0wLjY2OSwxLjUyNS0xLjAwNCwyLjU2Ny0xLjAwNGg3LjE0MyBjMS4wNDIsMCwxLjg5NywwLjMzNSwyLjU2NywxLjAwNEMxNTYuODA5LDEwMS42NzQsMTU3LjE0MywxMDIuNTI5LDE1Ny4xNDMsMTAzLjU3MXogTTIwMCw3LjE0M3Y1Ny4xNDMgYzAsMS45MzUtMC43MDcsMy42MDktMi4xMjEsNS4wMjJjLTEuNDEzLDEuNDE0LTMuMDg4LDIuMTIxLTUuMDIxLDIuMTIxYy0xLjkzNSwwLTMuNjA5LTAuNzA3LTUuMDIyLTIuMTIxbC0xOS42NDQtMTkuNjQzIGwtNzIuNzY3LDcyLjc2OWMtMC43NDQsMC43NDQtMS42LDEuMTE1LTIuNTY3LDEuMTE1cy0xLjgyMy0wLjM3MS0yLjU2Ny0xLjExNUw3Ny41NjcsMTA5LjcxYy0wLjc0NC0wLjc0NC0xLjExNi0xLjYtMS4xMTYtMi41NjcgYzAtMC45NjcsMC4zNzItMS44MjIsMS4xMTYtMi41NjZsNzIuNzY4LTcyLjc2OGwtMTkuNjQ0LTE5LjY0M2MtMS40MTMtMS40MTQtMi4xMi0zLjA4OC0yLjEyLTUuMDIyYzAtMS45MzUsMC43MDctMy42MDksMi4xMi01LjAyMiBDMTMyLjEwNSwwLjcwNywxMzMuNzc5LDAsMTM1LjcxNSwwaDU3LjE0M2MxLjkzNCwwLDMuNjA4LDAuNzA3LDUuMDIxLDIuMTIxQzE5OS4yOTMsMy41MzQsMjAwLDUuMjA4LDIwMCw3LjE0M3oiLz48L3N2Zz4=) +} + +.drawer-action-collapse { + background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNzEuNDI5IDE3MS40MjkiIGZpbGw9IiMzYTMxMzMiPjxwYXRoIGQ9Ik0xMjIuNDMzLDEwNi4xMzhsLTE2LjI5NSwxNi4yOTVjLTAuNzQ0LDAuNzQ0LTEuNiwxLjExNi0yLjU2NiwxLjExNmMtMC45NjgsMC0xLjgyMy0wLjM3Mi0yLjU2Ny0xLjExNmwtMTUuMjktMTUuMjkgbC0xNS4yOSwxNS4yOWMtMC43NDQsMC43NDQtMS42LDEuMTE2LTIuNTY3LDEuMTE2cy0xLjgyMy0wLjM3Mi0yLjU2Ny0xLjExNmwtMTYuMjk0LTE2LjI5NWMtMC43NDQtMC43NDQtMS4xMTYtMS42LTEuMTE2LTIuNTY2IGMwLTAuOTY4LDAuMzcyLTEuODIzLDEuMTE2LTIuNTY3bDE1LjI5LTE1LjI5bC0xNS4yOS0xNS4yOWMtMC43NDQtMC43NDQtMS4xMTYtMS42LTEuMTE2LTIuNTY3czAuMzcyLTEuODIzLDEuMTE2LTIuNTY3IEw2NS4yOSw0OC45OTZjMC43NDQtMC43NDQsMS42LTEuMTE2LDIuNTY3LTEuMTE2czEuODIzLDAuMzcyLDIuNTY3LDEuMTE2bDE1LjI5LDE1LjI5bDE1LjI5LTE1LjI5IGMwLjc0NC0wLjc0NCwxLjYtMS4xMTYsMi41NjctMS4xMTZjMC45NjcsMCwxLjgyMiwwLjM3MiwyLjU2NiwxLjExNmwxNi4yOTUsMTYuMjk0YzAuNzQ0LDAuNzQ0LDEuMTE2LDEuNiwxLjExNiwyLjU2NyBzLTAuMzcyLDEuODIzLTEuMTE2LDIuNTY3bC0xNS4yOSwxNS4yOWwxNS4yOSwxNS4yOWMwLjc0NCwwLjc0NCwxLjExNiwxLjYsMS4xMTYsMi41NjcgQzEyMy41NDksMTA0LjUzOSwxMjMuMTc3LDEwNS4zOTQsMTIyLjQzMywxMDYuMTM4eiBNMTQ2LjQyOSw4NS43MTRjMC0xMS4wMTItMi43MTctMjEuMTY4LTguMTQ4LTMwLjQ2OSBzLTEyLjc5Ny0xNi42NjctMjIuMDk4LTIyLjA5OFM5Ni43MjYsMjUsODUuNzE0LDI1cy0yMS4xNjgsMi43MTYtMzAuNDY5LDguMTQ3UzM4LjU3OSw0NS45NDUsMzMuMTQ3LDU1LjI0NlMyNSw3NC43MDMsMjUsODUuNzE0IHMyLjcxNiwyMS4xNjgsOC4xNDcsMzAuNDY5czEyLjc5NywxNi42NjYsMjIuMDk4LDIyLjA5OHMxOS40NTcsOC4xNDgsMzAuNDY5LDguMTQ4czIxLjE2OC0yLjcxNywzMC40NjktOC4xNDggczE2LjY2Ni0xMi43OTcsMjIuMDk4LTIyLjA5OFMxNDYuNDI5LDk2LjcyNiwxNDYuNDI5LDg1LjcxNHogTTE3MS40MjksODUuNzE0YzAsMTUuNTUxLTMuODMyLDI5Ljg5My0xMS40OTYsNDMuMDI0IGMtNy42NjQsMTMuMTMzLTE4LjA2MiwyMy41My0zMS4xOTQsMzEuMTk0Yy0xMy4xMzIsNy42NjQtMjcuNDc0LDExLjQ5Ni00My4wMjQsMTEuNDk2cy0yOS44OTItMy44MzItNDMuMDI0LTExLjQ5NiBjLTEzLjEzMy03LjY2NC0yMy41MzEtMTguMDYyLTMxLjE5NC0zMS4xOTRDMy44MzIsMTE1LjYwNywwLDEwMS4yNjUsMCw4NS43MTRTMy44MzIsNTUuODIyLDExLjQ5Niw0Mi42OSBjNy42NjQtMTMuMTMzLDE4LjA2Mi0yMy41MzEsMzEuMTk0LTMxLjE5NEM1NS44MjIsMy44MzIsNzAuMTY0LDAsODUuNzE0LDBzMjkuODkzLDMuODMyLDQzLjAyNCwxMS40OTYgYzEzLjEzMyw3LjY2NCwyMy41MywxOC4wNjIsMzEuMTk0LDMxLjE5NEMxNjcuNTk3LDU1LjgyMiwxNzEuNDI5LDcwLjE2NCwxNzEuNDI5LDg1LjcxNHoiLz48L3N2Zz4=) +} diff --git a/client/less/main.less b/client/less/main.less index 49ee08fe87..aefcae1a09 100644 --- a/client/less/main.less +++ b/client/less/main.less @@ -1,4 +1,4 @@ - @import "lib/bootstrap/bootstrap"; +@import "lib/bootstrap/bootstrap"; @import "lib/bootstrap-social/bootstrap-social"; @import "lib/ionicons/ionicons"; @import "lib/animate.min.less"; @@ -1171,7 +1171,4 @@ and (max-width : 400px) { @import "challenge.less"; @import "toastr.less"; @import "map.less"; - -ul > li { - list-style-type: disc; -} +@import "drawers.less"; diff --git a/client/less/map.less b/client/less/map.less index beddce7d86..b16fcda7ce 100644 --- a/client/less/map.less +++ b/client/less/map.less @@ -63,7 +63,7 @@ } .map-fixed-header { - position: fixed; + position: absolute; background: white; padding-top: 5px; width: 100%; @@ -158,7 +158,6 @@ } .map-wrapper { - position: absolute; display: block; height: 100%; width: 100%; diff --git a/common/app/App.jsx b/common/app/App.jsx index 0b16145fbb..ab67446dd3 100644 --- a/common/app/App.jsx +++ b/common/app/App.jsx @@ -6,10 +6,12 @@ import { connect } from 'react-redux'; import { contain } from 'redux-epic'; import { createSelector } from 'reselect'; +import MapDrawer from './components/Map-Drawer.jsx'; import { fetchUser, initWindowHeight, - updateNavHeight + updateNavHeight, + toggleMapDrawer } from './redux/actions'; import { submitChallenge } from './routes/challenges/redux/actions'; @@ -24,18 +26,24 @@ const mapStateToProps = createSelector( state => state.app.points, state => state.app.picture, state => state.app.toast, + state => state.app.isMapDrawerOpen, + state => state.app.isMapAlreadyLoaded, state => state.challengesApp.toast, ( username, points, picture, toast, + isMapDrawerOpen, + isMapAlreadyLoaded, showChallengeComplete ) => ({ username, points, picture, toast, + isMapDrawerOpen, + isMapAlreadyLoaded, showChallengeComplete }) ); @@ -44,7 +52,8 @@ const bindableActions = { initWindowHeight, updateNavHeight, fetchUser, - submitChallenge + submitChallenge, + toggleMapDrawer }; const fetchContainerOptions = { @@ -67,7 +76,10 @@ export class FreeCodeCamp extends React.Component { updateNavHeight: PropTypes.func, initWindowHeight: PropTypes.func, showChallengeComplete: PropTypes.number, - submitChallenge: PropTypes.func + submitChallenge: PropTypes.func, + isMapDrawerOpen: PropTypes.bool, + isMapAlreadyLoaded: PropTypes.bool, + toggleMapDrawer: PropTypes.func }; componentWillReceiveProps({ @@ -122,8 +134,22 @@ export class FreeCodeCamp extends React.Component { } render() { - const { username, points, picture, updateNavHeight } = this.props; - const navProps = { username, points, picture, updateNavHeight }; + const { + username, + points, + picture, + updateNavHeight, + isMapDrawerOpen, + isMapAlreadyLoaded, + toggleMapDrawer + } = this.props; + const navProps = { + username, + points, + picture, + updateNavHeight, + toggleMapDrawer + }; return (