diff --git a/package.json b/package.json
index 0b5a18168f..fda905f94e 100644
--- a/package.json
+++ b/package.json
@@ -31,6 +31,7 @@
     "q": "^1.4.1",
     "react": "^0.14.2",
     "react-dom": "^0.14.2",
+    "react-gemini-scrollbar": "^2.0.1",
     "sanitize-html": "^1.11.1",
     "velocity-animate": "^1.2.3"
   },
diff --git a/src/controllers/organisms/MemberList.js b/src/components/views/rooms/MemberList.js
similarity index 68%
rename from src/controllers/organisms/MemberList.js
rename to src/components/views/rooms/MemberList.js
index 3e9736cf8e..8ca24f8992 100644
--- a/src/controllers/organisms/MemberList.js
+++ b/src/components/views/rooms/MemberList.js
@@ -13,14 +13,17 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
-
-var MatrixClientPeg = require("../../MatrixClientPeg");
-var Modal = require("../../Modal");
-var sdk = require('../../index');
+var React = require('react');
+var classNames = require('classnames');
+var MatrixClientPeg = require("../../../MatrixClientPeg");
+var Modal = require("../../../Modal");
+var sdk = require('../../../index');
+var GeminiScrollbar = require('react-gemini-scrollbar');
 
 var INITIAL_LOAD_NUM_MEMBERS = 50;
 
-module.exports = {
+module.exports = React.createClass({
+    displayName: 'MemberList',
     getInitialState: function() {
         if (!this.props.roomId) return { members: [] };
         var cli = MatrixClientPeg.get();
@@ -195,6 +198,94 @@ module.exports = {
             }
         }
         return to_display;
-    }
-};
+    },
+
+
+
+    memberSort: function(userIdA, userIdB) {
+        var userA = this.memberDict[userIdA].user;
+        var userB = this.memberDict[userIdB].user;
+
+        var presenceMap = {
+            online: 3,
+            unavailable: 2,
+            offline: 1
+        };
+
+        var presenceOrdA = userA ? presenceMap[userA.presence] : 0;
+        var presenceOrdB = userB ? presenceMap[userB.presence] : 0;
+
+        if (presenceOrdA != presenceOrdB) {
+            return presenceOrdB - presenceOrdA;
+        }
+
+        var latA = userA ? (userA.lastPresenceTs - (userA.lastActiveAgo || userA.lastPresenceTs)) : 0;
+        var latB = userB ? (userB.lastPresenceTs - (userB.lastActiveAgo || userB.lastPresenceTs)) : 0;
+
+        return latB - latA;
+    },
+
+    makeMemberTiles: function(membership) {
+        var MemberTile = sdk.getComponent("rooms.MemberTile");
+
+        var self = this;
+        return self.state.members.filter(function(userId) {
+            var m = self.memberDict[userId];
+            return m.membership == membership;
+        }).map(function(userId) {
+            var m = self.memberDict[userId];
+            return (
+                <MemberTile key={userId} member={m} ref={userId} />
+            );
+        });
+    },
+
+    onPopulateInvite: function(e) {
+        this.onInvite(this.refs.invite.value);
+        e.preventDefault();
+    },
+
+    inviteTile: function() {
+        if (this.state.inviting) {
+            var Loader = sdk.getComponent("elements.Spinner");
+            return (
+                <Loader />
+            );
+        } else {
+            return (
+                <form onSubmit={this.onPopulateInvite}>
+                    <input className="mx_MemberList_invite" ref="invite" placeholder="Invite another user"/>
+                </form>
+            );
+        }
+    },
+
+    render: function() {
+        var invitedSection = null;
+        var invitedMemberTiles = this.makeMemberTiles('invite');
+        if (invitedMemberTiles.length > 0) {
+            invitedSection = (
+                <div className="mx_MemberList_invited">
+                    <h2>Invited</h2>
+                    <div className="mx_MemberList_wrapper">
+                        {invitedMemberTiles}
+                    </div>
+                </div>
+            );
+        }
+        return (
+            <div className="mx_MemberList">
+                <GeminiScrollbar autoshow={true} className="mx_MemberList_border">
+                    {this.inviteTile()}
+                    <div>
+                        <div className="mx_MemberList_wrapper">
+                            {this.makeMemberTiles('join')}
+                        </div>
+                    </div>
+                    {invitedSection}
+                </GeminiScrollbar>
+            </div>
+        );
+    }
+});