Repository: busyorg/busy
Pull request #741 (2017-09-19 13:00:35)

Add horizontal scroll on mobile
![demo](https://user-images.githubusercontent.com/1968722/30595839-ab468c58-9d52-11e7-886f-e270de9b7ff7.gif)

https://trello.com/c/V3EcBYHs/252-implement-mobile-horizontal-scroll


Patch:
diff --git a/.storybook/storyshots-setup.js b/.storybook/storyshots-setup.js
index 1939448a..1957ed09 100644
--- a/.storybook/storyshots-setup.js
+++ b/.storybook/storyshots-setup.js
@@ -2,6 +2,7 @@ jest.mock('rc-animate');
 jest.mock('rc-tabs');
 jest.mock('rc-select');
 jest.mock('css-animation');
+jest.mock('react-custom-scrollbars');
 jest.mock('../src/widgets/FollowButton');
 
 jest.mock('react-dom', () => ({
diff --git a/src/components/UserMenu.js b/src/components/UserMenu.js
index e801e42e..ff4aa010 100644
--- a/src/components/UserMenu.js
+++ b/src/components/UserMenu.js
@@ -1,7 +1,8 @@
 import React from 'react';
 import PropTypes from 'prop-types';
+import classNames from 'classnames';
+import { Scrollbars } from 'react-custom-scrollbars';
 import { FormattedMessage, FormattedNumber } from 'react-intl';
-import { Menu } from 'antd';
 import './UserMenu.less';
 
 class UserMenu extends React.Component {
@@ -26,49 +27,40 @@ class UserMenu extends React.Component {
     };
   }
 
+  getItemClasses = key => classNames('UserMenu__item', { 'UserMenu__item--active': this.state.current === key });
+
   handleClick = (e) => {
-    this.setState(
-      {
-        current: e.key,
-      },
-      () => {
-        if (this.props.onChange) {
-          this.props.onChange(e.key);
-        }
-      },
-    );
+    const key = e.currentTarget.dataset.key;
+    this.setState({ current: key }, () => this.props.onChange(key));
   };
 
   render() {
     return (
       <div className="UserMenu">
-        <div className="container topnav-layout">
+        <div className="container menu-layout">
           <div className="left" />
-          <Menu
-            className="UserMenu__menu center"
-            onClick={this.handleClick}
-            selectedKeys={[this.state.current]}
-            mode="horizontal"
-          >
-            <Menu.Item key="discussions" className="UserMenu__item">
-              <FormattedMessage id="discussions" defaultMessage="Discussions" />
-            </Menu.Item>
-            <Menu.Item key="comments" className="UserMenu__item">
-              <FormattedMessage id="comments" defaultMessage="Comments" />
-            </Menu.Item>
-            <Menu.Item key="followers" className="UserMenu__item">
-              <FormattedMessage id="followers" defaultMessage="Followers" />
-              <span className="UserMenu__badge">
-                <FormattedNumber value={this.props.followers} />
-              </span>
-            </Menu.Item>
-            <Menu.Item key="followed" className="UserMenu__item">
-              <FormattedMessage id="following" defaultMessage="Following" />
-              <span className="UserMenu__badge">
-                <FormattedNumber value={this.props.following} />
-              </span>
-            </Menu.Item>
-          </Menu>
+          <Scrollbars autoHide style={{ width: '100%', height: 46 }}>
+            <ul className="UserMenu__menu center">
+              <li className={this.getItemClasses('discussions')} onClick={this.handleClick} role="presentation" data-key="discussions">
+                <FormattedMessage id="discussions" defaultMessage="Discussions" />
+              </li>
+              <li className={this.getItemClasses('comments')} onClick={this.handleClick} role="presentation" data-key="comments">
+                <FormattedMessage id="comments" defaultMessage="Comments" />
+              </li>
+              <li className={this.getItemClasses('followers')} onClick={this.handleClick} role="presentation" data-key="followers">
+                <FormattedMessage id="followers" defaultMessage="Followers" />
+                <span className="UserMenu__badge">
+                  <FormattedNumber value={this.props.followers} />
+                </span>
+              </li>
+              <li className={this.getItemClasses('followed')} onClick={this.handleClick} role="presentation" data-key="followed">
+                <FormattedMessage id="following" defaultMessage="Following" />
+                <span className="UserMenu__badge">
+                  <FormattedNumber value={this.props.following} />
+                </span>
+              </li>
+            </ul>
+          </Scrollbars>
         </div>
       </div>
     );
diff --git a/src/components/UserMenu.less b/src/components/UserMenu.less
index d6fd501c..2d92dd25 100644
--- a/src/components/UserMenu.less
+++ b/src/components/UserMenu.less
@@ -2,21 +2,29 @@
 
 .UserMenu {
   height: 46px;
-  background: @white;
   border-top: solid 1px #e9e7e7;
   border-bottom: solid 1px #e9e7e7;
 
   &__menu {
-    height: 45px !important;
-    border-bottom: solid 1px #e9e7e7 !important;
+    height: 46px;
+    line-height: 46px;
+    white-space: nowrap;
   }
 
   &__item {
-    height: 45px !important;
+    display: inline-block;
+    height: 45px;
+    margin-right: 16px;
+    cursor: pointer;
     color: #99aab5;
     font-weight: bold;
-    padding: 0 !important;
-    margin-right: 16px !important;
+
+
+    &--active, &:hover {
+      color: @purple;
+
+      border-bottom: 2px solid @purple;
+    }
   }
 
   &__badge {
diff --git a/src/styles/modules/feed-layout.less b/src/styles/modules/feed-layout.less
index 1f1452b6..e87d7952 100644
--- a/src/styles/modules/feed-layout.less
+++ b/src/styles/modules/feed-layout.less
@@ -1,3 +1,5 @@
+@import (reference) "./variables.less";
+
 .feed-layout {
   position: relative;
 
diff --git a/src/styles/modules/grid.less b/src/styles/modules/grid.less
index 3cd39d7f..50c477f6 100644
--- a/src/styles/modules/grid.less
+++ b/src/styles/modules/grid.less
@@ -2,6 +2,7 @@
 @import "./post-layout.less";
 @import "./feed-layout.less";
 @import "./topnav-layout.less";
+@import "./menu-layout.less";
 
 .container {
   position: relative;
diff --git a/src/styles/modules/menu-layout.less b/src/styles/modules/menu-layout.less
new file mode 100644
index 00000000..79cdaed3
--- /dev/null
+++ b/src/styles/modules/menu-layout.less
@@ -0,0 +1,41 @@
+@import (reference) "./variables.less";
+
+.menu-layout {
+  .left {
+    display: none;
+    position: absolute;
+    width: @left-width;
+
+    @media @medium {
+      display: block;
+    }
+  }
+
+  .right {
+    display: none;
+    position: absolute;
+    top: 0;
+    right: 0;
+    width: @right-width;
+
+    @media @small {
+      display: block;
+    }  
+  }
+
+  .center {
+    width: 100%;
+    padding: 0 @mobile-padding;
+
+    @media @small {
+      width: calc(100% ~"-" (@right-width + @margin)); 
+      margin-right: @right-width + @margin;
+    }
+    
+    @media @medium {
+      width: calc(100% ~"-" (@left-width + @right-width + 2 * @margin));
+      margin-left: @left-width + @margin;
+      padding: 0;
+    }
+  }
+}
diff --git a/src/styles/modules/post-layout.less b/src/styles/modules/post-layout.less
index 55b1d9d1..af03b63b 100644
--- a/src/styles/modules/post-layout.less
+++ b/src/styles/modules/post-layout.less
@@ -1,4 +1,4 @@
-@mobile-padding: 20px;
+@import (reference) "./variables.less";
 
 .post-layout {
   position: relative;
diff --git a/src/styles/modules/topnav-layout.less b/src/styles/modules/topnav-layout.less
index f3e67e46..30885323 100644
--- a/src/styles/modules/topnav-layout.less
+++ b/src/styles/modules/topnav-layout.less
@@ -1,3 +1,5 @@
+@import (reference) "./variables.less";
+
 .topnav-layout {
   .left {
     position: absolute;
diff --git a/src/styles/modules/variables.less b/src/styles/modules/variables.less
index 45a48b08..ec8fa7bb 100644
--- a/src/styles/modules/variables.less
+++ b/src/styles/modules/variables.less
@@ -1,4 +1,5 @@
 @container-width: 1010px;
+@mobile-padding: 20px;
 @margin: 20px;
 @left-width: 180px;
 @right-width: 270px;


Test patch:
diff --git a/src/stories/__snapshots__/stories.test.js.snap b/src/stories/__snapshots__/stories.test.js.snap
index 8added63..dbdcff83 100644
--- a/src/stories/__snapshots__/stories.test.js.snap
+++ b/src/stories/__snapshots__/stories.test.js.snap
@@ -1090,94 +1090,11 @@ exports[`Storyshots Profile UserMenu 1`] = `
     className="UserMenu"
   >
     <div
-      className="container topnav-layout"
+      className="container menu-layout"
     >
       <div
         className="left"
       />
-      <ul
-        aria-activedescendant=""
-        className="ant-menu ant-menu-horizontal UserMenu__menu center ant-menu-light ant-menu-root"
-        onKeyDown={[Function]}
-        role="menu"
-        style={Object {}}
-        tabIndex="0"
-      >
-        <li
-          aria-disabled={undefined}
-          aria-selected={true}
-          className="ant-menu-item-selected ant-menu-item UserMenu__item"
-          onClick={[Function]}
-          onMouseEnter={[Function]}
-          onMouseLeave={[Function]}
-          role="menuitem"
-          style={Object {}}
-          title={undefined}
-        >
-          <span>
-            Discussions
-          </span>
-        </li>
-        <li
-          aria-disabled={undefined}
-          aria-selected={false}
-          className="ant-menu-item UserMenu__item"
-          onClick={[Function]}
-          onMouseEnter={[Function]}
-          onMouseLeave={[Function]}
-          role="menuitem"
-          style={Object {}}
-          title={undefined}
-        >
-          <span>
-            Comments
-          </span>
-        </li>
-        <li
-          aria-disabled={undefined}
-          aria-selected={false}
-          className="ant-menu-item UserMenu__item"
-          onClick={[Function]}
-          onMouseEnter={[Function]}
-          onMouseLeave={[Function]}
-          role="menuitem"
-          style={Object {}}
-          title={undefined}
-        >
-          <span>
-            Followers
-          </span>
-          <span
-            className="UserMenu__badge"
-          >
-            <span>
-              0
-            </span>
-          </span>
-        </li>
-        <li
-          aria-disabled={undefined}
-          aria-selected={false}
-          className="ant-menu-item UserMenu__item"
-          onClick={[Function]}
-          onMouseEnter={[Function]}
-          onMouseLeave={[Function]}
-          role="menuitem"
-          style={Object {}}
-          title={undefined}
-        >
-          <span>
-            Following
-          </span>
-          <span
-            className="UserMenu__badge"
-          >
-            <span>
-              244
-            </span>
-          </span>
-        </li>
-      </ul>
     </div>
   </div>
 </div>