diff --git a/src/components/structures/BottomLeftMenu.js b/src/components/structures/BottomLeftMenu.js
index f378cac628c693fcec8f692db1533f7ca1a3ee66..8ae8aec7fad1900c8c9272f93bcbcd9c0126c14f 100644
--- a/src/components/structures/BottomLeftMenu.js
+++ b/src/components/structures/BottomLeftMenu.js
@@ -14,13 +14,15 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-'use strict';
+import React from 'react';
+import ReactDOM from 'react-dom';
+import sdk from 'matrix-react-sdk';
+import dis from 'matrix-react-sdk/lib/dispatcher';
+import AccessibleButton from 'matrix-react-sdk/lib/components/views/elements/AccessibleButton';
+import Velocity from 'velocity-vector';
+import 'velocity-vector/velocity.ui';
 
-var React = require('react');
-var ReactDOM = require('react-dom');
-var sdk = require('matrix-react-sdk')
-var dis = require('matrix-react-sdk/lib/dispatcher');
-var AccessibleButton = require('matrix-react-sdk/lib/components/views/elements/AccessibleButton');
+const CALLOUT_ANIM_DURATION = 1000;
 
 module.exports = React.createClass({
     displayName: 'BottomLeftMenu',
@@ -40,6 +42,18 @@ module.exports = React.createClass({
         });
     },
 
+    componentWillMount: function() {
+        this._dispatcherRef = dis.register(this.onAction);
+        this._peopleButton = null;
+        this._directoryButton = null;
+        this._createRoomButton = null;
+        this._lastCallouts = {};
+    },
+
+    componentWillUnmount: function() {
+        dis.unregister(this._dispatcherRef);
+    },
+
     // Room events
     onDirectoryClick: function() {
         dis.dispatch({ action: 'view_room_directory' });
@@ -104,6 +118,30 @@ module.exports = React.createClass({
         this.setState({ settingsHover: false });
     },
 
+    onAction: function(payload) {
+        let calloutElement;
+        switch (payload.action) {
+            // Incoming instruction: dance!
+            case 'callout_start_chat':
+                calloutElement = this._peopleButton;
+                break;
+            case 'callout_room_directory':
+                calloutElement = this._directoryButton;
+                break;
+            case 'callout_create_room':
+                calloutElement = this._createRoomButton;
+                break;
+        }
+        if (calloutElement) {
+            const lastCallout = this._lastCallouts[payload.action];
+            const now = Date.now();
+            if (lastCallout == undefined || lastCallout < now - CALLOUT_ANIM_DURATION) {
+                this._lastCallouts[payload.action] = now;
+                Velocity(ReactDOM.findDOMNode(calloutElement), "callout.bounce", CALLOUT_ANIM_DURATION);
+            }
+        }
+    },
+
     // Get the label/tooltip to show
     getLabel: function(label, show) {
         if (show) {
@@ -112,6 +150,18 @@ module.exports = React.createClass({
         }
     },
 
+    _collectPeopleButton: function(e) {
+        this._peopleButton = e;
+    },
+
+    _collectDirectoryButton: function(e) {
+        this._directoryButton = e;
+    },
+
+    _collectCreateRoomButton: function(e) {
+        this._createRoomButton = e;
+    },
+
     render: function() {
         var TintableSvg = sdk.getComponent('elements.TintableSvg');
 
@@ -130,15 +180,15 @@ module.exports = React.createClass({
                 <div className="mx_BottomLeftMenu_options">
                     { homeButton }
                     <AccessibleButton className="mx_BottomLeftMenu_people" onClick={ this.onPeopleClick } onMouseEnter={ this.onPeopleMouseEnter } onMouseLeave={ this.onPeopleMouseLeave } >
-                        <TintableSvg src="img/icons-people.svg" width="25" height="25" />
+                        <TintableSvg ref={this._collectPeopleButton} src="img/icons-people.svg" width="25" height="25" />
                         { this.getLabel("Start chat", this.state.peopleHover) }
                     </AccessibleButton>
                     <AccessibleButton className="mx_BottomLeftMenu_directory" onClick={ this.onDirectoryClick } onMouseEnter={ this.onDirectoryMouseEnter } onMouseLeave={ this.onDirectoryMouseLeave } >
-                        <TintableSvg src="img/icons-directory.svg" width="25" height="25"/>
+                        <TintableSvg ref={this._collectDirectoryButton} src="img/icons-directory.svg" width="25" height="25"/>
                         { this.getLabel("Room directory", this.state.directoryHover) }
                     </AccessibleButton>
                     <AccessibleButton className="mx_BottomLeftMenu_createRoom" onClick={ this.onRoomsClick } onMouseEnter={ this.onRoomsMouseEnter } onMouseLeave={ this.onRoomsMouseLeave } >
-                        <TintableSvg src="img/icons-create-room.svg" width="25" height="25" />
+                        <TintableSvg ref={this._collectCreateRoomButton} src="img/icons-create-room.svg" width="25" height="25" />
                         { this.getLabel("Create new room", this.state.roomsHover) }
                     </AccessibleButton>
                     <AccessibleButton className="mx_BottomLeftMenu_settings" onClick={ this.onSettingsClick } onMouseEnter={ this.onSettingsMouseEnter } onMouseLeave={ this.onSettingsMouseLeave } >