Bug 1176780 - Enable jsx-sort-props-types eslint rule for Loop. rs=dmose
authorMark Banner <standard8@mozilla.com>
Tue, 23 Jun 2015 23:11:48 -0700
changeset 273945 572593f71b17ed287241d217e9caf79a5182086f
parent 273944 2b391a831518764b800381e8eda7a8a6d58cbc6a
child 273946 3ae7fd12f53fa7955ab952273870f205a82de527
push id3020
push usermartin.thomson@gmail.com
push dateWed, 24 Jun 2015 18:22:16 +0000
reviewersdmose
bugs1176780
milestone41.0a1
Bug 1176780 - Enable jsx-sort-props-types eslint rule for Loop. rs=dmose
browser/components/loop/.eslintrc
browser/components/loop/content/js/contacts.js
browser/components/loop/content/js/contacts.jsx
browser/components/loop/content/js/conversation.js
browser/components/loop/content/js/conversation.jsx
browser/components/loop/content/js/conversationViews.js
browser/components/loop/content/js/conversationViews.jsx
browser/components/loop/content/js/panel.js
browser/components/loop/content/js/panel.jsx
browser/components/loop/content/js/roomViews.js
browser/components/loop/content/js/roomViews.jsx
browser/components/loop/content/shared/js/feedbackViews.js
browser/components/loop/content/shared/js/feedbackViews.jsx
browser/components/loop/content/shared/js/views.js
browser/components/loop/content/shared/js/views.jsx
browser/components/loop/standalone/content/js/standaloneRoomViews.js
browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
browser/components/loop/standalone/content/js/webapp.js
browser/components/loop/standalone/content/js/webapp.jsx
browser/components/loop/ui/react-frame-component.js
browser/components/loop/ui/ui-showcase.js
browser/components/loop/ui/ui-showcase.jsx
--- a/browser/components/loop/.eslintrc
+++ b/browser/components/loop/.eslintrc
@@ -59,17 +59,17 @@
     "quotes": [2, "double", "avoid-escape"],
     "strict": 0,                  // [2, "function"],
     // eslint-plugin-react rules. These are documented at
     // <https://github.com/yannickcr/eslint-plugin-react#list-of-supported-rules>
     "react/jsx-quotes": [2, "double", "avoid-escape"],
     "react/jsx-no-undef": 2,
     // Need to fix instances where this is failing.
     "react/jsx-sort-props": 2,
-    "react/jsx-sort-prop-types": 0,
+    "react/jsx-sort-prop-types": 2,
     "react/jsx-uses-vars": 2,
     // Need to fix the couple of instances which don't
     // currently pass this rule.
     "react/no-did-mount-set-state": 0,
     "react/no-did-update-set-state": 2,
     "react/no-unknown-property": 2,
     // Need to fix instances where this is currently failing
     "react/prop-types": 0,
--- a/browser/components/loop/content/js/contacts.js
+++ b/browser/components/loop/content/js/contacts.js
@@ -141,18 +141,18 @@ loop.contacts = (function(_, mozL10n) {
           )
         )
       );
     }
   });
 
   const ContactDropdown = React.createClass({displayName: "ContactDropdown",
     propTypes: {
-      handleAction: React.PropTypes.func.isRequired,
-      canEdit: React.PropTypes.bool
+      canEdit: React.PropTypes.bool,
+      handleAction: React.PropTypes.func.isRequired
     },
 
     getInitialState: function () {
       return {
         openDirUp: false
       };
     },
 
@@ -231,18 +231,18 @@ loop.contacts = (function(_, mozL10n) {
   const ContactDetail = React.createClass({displayName: "ContactDetail",
     getInitialState: function() {
       return {
         showMenu: false
       };
     },
 
     propTypes: {
-      handleContactAction: React.PropTypes.func,
-      contact: React.PropTypes.object.isRequired
+      contact: React.PropTypes.object.isRequired,
+      handleContactAction: React.PropTypes.func
     },
 
     _onBodyClick: function() {
       // Hide the menu after other click handlers have been invoked.
       setTimeout(this.hideDropdownMenu, 10);
     },
 
     showDropdownMenu: function() {
--- a/browser/components/loop/content/js/contacts.jsx
+++ b/browser/components/loop/content/js/contacts.jsx
@@ -141,18 +141,18 @@ loop.contacts = (function(_, mozL10n) {
           </ButtonGroup>
         </div>
       );
     }
   });
 
   const ContactDropdown = React.createClass({
     propTypes: {
-      handleAction: React.PropTypes.func.isRequired,
-      canEdit: React.PropTypes.bool
+      canEdit: React.PropTypes.bool,
+      handleAction: React.PropTypes.func.isRequired
     },
 
     getInitialState: function () {
       return {
         openDirUp: false
       };
     },
 
@@ -231,18 +231,18 @@ loop.contacts = (function(_, mozL10n) {
   const ContactDetail = React.createClass({
     getInitialState: function() {
       return {
         showMenu: false
       };
     },
 
     propTypes: {
-      handleContactAction: React.PropTypes.func,
-      contact: React.PropTypes.object.isRequired
+      contact: React.PropTypes.object.isRequired,
+      handleContactAction: React.PropTypes.func
     },
 
     _onBodyClick: function() {
       // Hide the menu after other click handlers have been invoked.
       setTimeout(this.hideDropdownMenu, 10);
     },
 
     showDropdownMenu: function() {
--- a/browser/components/loop/content/js/conversation.js
+++ b/browser/components/loop/content/js/conversation.js
@@ -24,18 +24,18 @@ loop.conversation = (function(mozL10n) {
     mixins: [
       Backbone.Events,
       loop.store.StoreMixin("conversationAppStore"),
       sharedMixins.WindowCloseMixin
     ],
 
     propTypes: {
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      roomStore: React.PropTypes.instanceOf(loop.store.RoomStore),
-      mozLoop: React.PropTypes.object.isRequired
+      mozLoop: React.PropTypes.object.isRequired,
+      roomStore: React.PropTypes.instanceOf(loop.store.RoomStore)
     },
 
     getInitialState: function() {
       return this.getStoreState();
     },
 
     render: function() {
       switch(this.state.windowType) {
--- a/browser/components/loop/content/js/conversation.jsx
+++ b/browser/components/loop/content/js/conversation.jsx
@@ -24,18 +24,18 @@ loop.conversation = (function(mozL10n) {
     mixins: [
       Backbone.Events,
       loop.store.StoreMixin("conversationAppStore"),
       sharedMixins.WindowCloseMixin
     ],
 
     propTypes: {
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      roomStore: React.PropTypes.instanceOf(loop.store.RoomStore),
-      mozLoop: React.PropTypes.object.isRequired
+      mozLoop: React.PropTypes.object.isRequired,
+      roomStore: React.PropTypes.instanceOf(loop.store.RoomStore)
     },
 
     getInitialState: function() {
       return this.getStoreState();
     },
 
     render: function() {
       switch(this.state.windowType) {
--- a/browser/components/loop/content/js/conversationViews.js
+++ b/browser/components/loop/content/js/conversationViews.js
@@ -357,19 +357,19 @@ loop.conversationViews = (function(mozL1
   /**
    * View for pending conversations. Displays a cancel button and appropriate
    * pending/ringing strings.
    */
   var PendingConversationView = React.createClass({displayName: "PendingConversationView",
     mixins: [sharedMixins.AudioMixin],
 
     propTypes: {
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
       callState: React.PropTypes.string,
       contact: React.PropTypes.object,
+      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
       enableCancelButton: React.PropTypes.bool
     },
 
     getDefaultProps: function() {
       return {
         enableCancelButton: false
       };
     },
@@ -421,18 +421,18 @@ loop.conversationViews = (function(mozL1
     mixins: [
       Backbone.Events,
       loop.store.StoreMixin("conversationStore"),
       sharedMixins.AudioMixin,
       sharedMixins.WindowCloseMixin
     ],
 
     propTypes: {
+      contact: React.PropTypes.object.isRequired,
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      contact: React.PropTypes.object.isRequired,
       // This is used by the UI showcase.
       emailLinkError: React.PropTypes.bool,
       outgoing: React.PropTypes.bool.isRequired
     },
 
     getInitialState: function() {
       return {
         emailLinkError: this.props.emailLinkError,
@@ -566,28 +566,28 @@ loop.conversationViews = (function(mozL1
 
   var OngoingConversationView = React.createClass({displayName: "OngoingConversationView",
     mixins: [
       loop.store.StoreMixin("conversationStore"),
       sharedMixins.MediaSetupMixin
     ],
 
     propTypes: {
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      // local
-      video: React.PropTypes.object,
       // local
       audio: React.PropTypes.object,
-      remoteVideoEnabled: React.PropTypes.bool,
+      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
+      // The poster URLs are for UI-showcase testing and development.
+      localPosterUrl: React.PropTypes.string,
       // This is used from the props rather than the state to make it easier for
       // the ui-showcase.
       mediaConnected: React.PropTypes.bool,
-      // The poster URLs are for UI-showcase testing and development.
-      localPosterUrl: React.PropTypes.string,
-      remotePosterUrl: React.PropTypes.string
+      remotePosterUrl: React.PropTypes.string,
+      remoteVideoEnabled: React.PropTypes.bool,
+      // local
+      video: React.PropTypes.object
     },
 
     getDefaultProps: function() {
       return {
         video: {enabled: true, visible: true},
         audio: {enabled: true, visible: true}
       };
     },
--- a/browser/components/loop/content/js/conversationViews.jsx
+++ b/browser/components/loop/content/js/conversationViews.jsx
@@ -357,19 +357,19 @@ loop.conversationViews = (function(mozL1
   /**
    * View for pending conversations. Displays a cancel button and appropriate
    * pending/ringing strings.
    */
   var PendingConversationView = React.createClass({
     mixins: [sharedMixins.AudioMixin],
 
     propTypes: {
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
       callState: React.PropTypes.string,
       contact: React.PropTypes.object,
+      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
       enableCancelButton: React.PropTypes.bool
     },
 
     getDefaultProps: function() {
       return {
         enableCancelButton: false
       };
     },
@@ -421,18 +421,18 @@ loop.conversationViews = (function(mozL1
     mixins: [
       Backbone.Events,
       loop.store.StoreMixin("conversationStore"),
       sharedMixins.AudioMixin,
       sharedMixins.WindowCloseMixin
     ],
 
     propTypes: {
+      contact: React.PropTypes.object.isRequired,
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      contact: React.PropTypes.object.isRequired,
       // This is used by the UI showcase.
       emailLinkError: React.PropTypes.bool,
       outgoing: React.PropTypes.bool.isRequired
     },
 
     getInitialState: function() {
       return {
         emailLinkError: this.props.emailLinkError,
@@ -566,28 +566,28 @@ loop.conversationViews = (function(mozL1
 
   var OngoingConversationView = React.createClass({
     mixins: [
       loop.store.StoreMixin("conversationStore"),
       sharedMixins.MediaSetupMixin
     ],
 
     propTypes: {
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      // local
-      video: React.PropTypes.object,
       // local
       audio: React.PropTypes.object,
-      remoteVideoEnabled: React.PropTypes.bool,
+      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
+      // The poster URLs are for UI-showcase testing and development.
+      localPosterUrl: React.PropTypes.string,
       // This is used from the props rather than the state to make it easier for
       // the ui-showcase.
       mediaConnected: React.PropTypes.bool,
-      // The poster URLs are for UI-showcase testing and development.
-      localPosterUrl: React.PropTypes.string,
-      remotePosterUrl: React.PropTypes.string
+      remotePosterUrl: React.PropTypes.string,
+      remoteVideoEnabled: React.PropTypes.bool,
+      // local
+      video: React.PropTypes.object
     },
 
     getDefaultProps: function() {
       return {
         video: {enabled: true, visible: true},
         audio: {enabled: true, visible: true}
       };
     },
--- a/browser/components/loop/content/js/panel.js
+++ b/browser/components/loop/content/js/panel.js
@@ -15,19 +15,19 @@ loop.panel = (function(_, mozL10n) {
   var ButtonGroup = sharedViews.ButtonGroup;
   var Checkbox = sharedViews.Checkbox;
   var ContactsList = loop.contacts.ContactsList;
   var ContactDetailsForm = loop.contacts.ContactDetailsForm;
 
   var TabView = React.createClass({displayName: "TabView",
     propTypes: {
       buttonsHidden: React.PropTypes.array,
+      mozLoop: React.PropTypes.object,
       // The selectedTab prop is used by the UI showcase.
-      selectedTab: React.PropTypes.string,
-      mozLoop: React.PropTypes.object
+      selectedTab: React.PropTypes.string
     },
 
     getDefaultProps: function() {
       return {
         buttonsHidden: []
       };
     },
 
@@ -330,20 +330,20 @@ loop.panel = (function(_, mozL10n) {
     }
   });
 
   /**
    * Panel settings (gear) menu entry.
    */
   var SettingsDropdownEntry = React.createClass({displayName: "SettingsDropdownEntry",
     propTypes: {
-      onClick: React.PropTypes.func.isRequired,
+      displayed: React.PropTypes.bool,
+      icon: React.PropTypes.string,
       label: React.PropTypes.string.isRequired,
-      icon: React.PropTypes.string,
-      displayed: React.PropTypes.bool
+      onClick: React.PropTypes.func.isRequired
     },
 
     getDefaultProps: function() {
       return {displayed: true};
     },
 
     render: function() {
       if (!this.props.displayed) {
@@ -608,19 +608,19 @@ loop.panel = (function(_, mozL10n) {
 
   /**
    * Room list.
    */
   var RoomList = React.createClass({displayName: "RoomList",
     mixins: [Backbone.Events, sharedMixins.WindowCloseMixin],
 
     propTypes: {
+      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
       mozLoop: React.PropTypes.object.isRequired,
       store: React.PropTypes.instanceOf(loop.store.RoomStore).isRequired,
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
       userDisplayName: React.PropTypes.string.isRequired  // for room creation
     },
 
     getInitialState: function() {
       return this.props.store.getStoreState();
     },
 
     componentDidMount: function() {
@@ -796,26 +796,26 @@ loop.panel = (function(_, mozL10n) {
     }
   });
 
   /**
    * Panel view.
    */
   var PanelView = React.createClass({displayName: "PanelView",
     propTypes: {
+      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
+      mozLoop: React.PropTypes.object.isRequired,
       notifications: React.PropTypes.object.isRequired,
-      // Mostly used for UI components showcase and unit tests
-      userProfile: React.PropTypes.object,
+      roomStore:
+        React.PropTypes.instanceOf(loop.store.RoomStore).isRequired,
+      selectedTab: React.PropTypes.string,
       // Used only for unit tests.
       showTabButtons: React.PropTypes.bool,
-      selectedTab: React.PropTypes.string,
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      mozLoop: React.PropTypes.object.isRequired,
-      roomStore:
-        React.PropTypes.instanceOf(loop.store.RoomStore).isRequired
+      // Mostly used for UI components showcase and unit tests
+      userProfile: React.PropTypes.object
     },
 
     getInitialState: function() {
       return {
         hasEncryptionKey: this.props.mozLoop.hasEncryptionKey,
         userProfile: this.props.userProfile || this.props.mozLoop.userProfile,
         gettingStartedSeen: this.props.mozLoop.getLoopPref("gettingStarted.seen")
       };
--- a/browser/components/loop/content/js/panel.jsx
+++ b/browser/components/loop/content/js/panel.jsx
@@ -15,19 +15,19 @@ loop.panel = (function(_, mozL10n) {
   var ButtonGroup = sharedViews.ButtonGroup;
   var Checkbox = sharedViews.Checkbox;
   var ContactsList = loop.contacts.ContactsList;
   var ContactDetailsForm = loop.contacts.ContactDetailsForm;
 
   var TabView = React.createClass({
     propTypes: {
       buttonsHidden: React.PropTypes.array,
+      mozLoop: React.PropTypes.object,
       // The selectedTab prop is used by the UI showcase.
-      selectedTab: React.PropTypes.string,
-      mozLoop: React.PropTypes.object
+      selectedTab: React.PropTypes.string
     },
 
     getDefaultProps: function() {
       return {
         buttonsHidden: []
       };
     },
 
@@ -330,20 +330,20 @@ loop.panel = (function(_, mozL10n) {
     }
   });
 
   /**
    * Panel settings (gear) menu entry.
    */
   var SettingsDropdownEntry = React.createClass({
     propTypes: {
-      onClick: React.PropTypes.func.isRequired,
+      displayed: React.PropTypes.bool,
+      icon: React.PropTypes.string,
       label: React.PropTypes.string.isRequired,
-      icon: React.PropTypes.string,
-      displayed: React.PropTypes.bool
+      onClick: React.PropTypes.func.isRequired
     },
 
     getDefaultProps: function() {
       return {displayed: true};
     },
 
     render: function() {
       if (!this.props.displayed) {
@@ -608,19 +608,19 @@ loop.panel = (function(_, mozL10n) {
 
   /**
    * Room list.
    */
   var RoomList = React.createClass({
     mixins: [Backbone.Events, sharedMixins.WindowCloseMixin],
 
     propTypes: {
+      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
       mozLoop: React.PropTypes.object.isRequired,
       store: React.PropTypes.instanceOf(loop.store.RoomStore).isRequired,
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
       userDisplayName: React.PropTypes.string.isRequired  // for room creation
     },
 
     getInitialState: function() {
       return this.props.store.getStoreState();
     },
 
     componentDidMount: function() {
@@ -796,26 +796,26 @@ loop.panel = (function(_, mozL10n) {
     }
   });
 
   /**
    * Panel view.
    */
   var PanelView = React.createClass({
     propTypes: {
+      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
+      mozLoop: React.PropTypes.object.isRequired,
       notifications: React.PropTypes.object.isRequired,
-      // Mostly used for UI components showcase and unit tests
-      userProfile: React.PropTypes.object,
+      roomStore:
+        React.PropTypes.instanceOf(loop.store.RoomStore).isRequired,
+      selectedTab: React.PropTypes.string,
       // Used only for unit tests.
       showTabButtons: React.PropTypes.bool,
-      selectedTab: React.PropTypes.string,
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      mozLoop: React.PropTypes.object.isRequired,
-      roomStore:
-        React.PropTypes.instanceOf(loop.store.RoomStore).isRequired
+      // Mostly used for UI components showcase and unit tests
+      userProfile: React.PropTypes.object
     },
 
     getInitialState: function() {
       return {
         hasEncryptionKey: this.props.mozLoop.hasEncryptionKey,
         userProfile: this.props.userProfile || this.props.mozLoop.userProfile,
         gettingStartedSeen: this.props.mozLoop.getLoopPref("gettingStarted.seen")
       };
--- a/browser/components/loop/content/js/roomViews.js
+++ b/browser/components/loop/content/js/roomViews.js
@@ -585,19 +585,19 @@ loop.roomViews = (function(mozL10n) {
       sharedMixins.DocumentTitleMixin,
       sharedMixins.MediaSetupMixin,
       sharedMixins.RoomsAudioMixin,
       sharedMixins.WindowCloseMixin
     ],
 
     propTypes: {
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      mozLoop: React.PropTypes.object.isRequired,
       // The poster URLs are for UI-showcase testing and development.
       localPosterUrl: React.PropTypes.string,
+      mozLoop: React.PropTypes.object.isRequired,
       remotePosterUrl: React.PropTypes.string
     },
 
     componentWillUpdate: function(nextProps, nextState) {
       // The SDK needs to know about the configuration and the elements to use
       // for display. So the best way seems to pass the information here - ideally
       // the sdk wouldn't need to know this, but we can't change that.
       if (this.state.roomState !== ROOM_STATES.MEDIA_WAIT &&
--- a/browser/components/loop/content/js/roomViews.jsx
+++ b/browser/components/loop/content/js/roomViews.jsx
@@ -585,19 +585,19 @@ loop.roomViews = (function(mozL10n) {
       sharedMixins.DocumentTitleMixin,
       sharedMixins.MediaSetupMixin,
       sharedMixins.RoomsAudioMixin,
       sharedMixins.WindowCloseMixin
     ],
 
     propTypes: {
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      mozLoop: React.PropTypes.object.isRequired,
       // The poster URLs are for UI-showcase testing and development.
       localPosterUrl: React.PropTypes.string,
+      mozLoop: React.PropTypes.object.isRequired,
       remotePosterUrl: React.PropTypes.string
     },
 
     componentWillUpdate: function(nextProps, nextState) {
       // The SDK needs to know about the configuration and the elements to use
       // for display. So the best way seems to pass the information here - ideally
       // the sdk wouldn't need to know this, but we can't change that.
       if (this.state.roomState !== ROOM_STATES.MEDIA_WAIT &&
--- a/browser/components/loop/content/shared/js/feedbackViews.js
+++ b/browser/components/loop/content/shared/js/feedbackViews.js
@@ -19,18 +19,18 @@ loop.shared.views.FeedbackView = (functi
    * Feedback outer layout.
    *
    * Props:
    * -
    */
   var FeedbackLayout = React.createClass({displayName: "FeedbackLayout",
     propTypes: {
       children: React.PropTypes.component.isRequired,
-      title: React.PropTypes.string.isRequired,
-      reset: React.PropTypes.func // if not specified, no Back btn is shown
+      reset: React.PropTypes.func, // if not specified, no Back btn is shown
+      title: React.PropTypes.string.isRequired
     },
 
     render: function() {
       var backButton = React.createElement("div", null);
       if (this.props.reset) {
         backButton = (
           React.createElement("button", {className: "fx-embedded-btn-back", 
             onClick: this.props.reset, 
@@ -232,20 +232,20 @@ loop.shared.views.FeedbackView = (functi
    */
   var FeedbackView = React.createClass({displayName: "FeedbackView",
     mixins: [
       Backbone.Events,
       loop.store.StoreMixin("feedbackStore")
     ],
 
     propTypes: {
-      onAfterFeedbackReceived: React.PropTypes.func,
       // Used by the UI showcase.
       feedbackState: React.PropTypes.string,
-      noCloseText: React.PropTypes.bool
+      noCloseText: React.PropTypes.bool,
+      onAfterFeedbackReceived: React.PropTypes.func
     },
 
     getInitialState: function() {
       var storeState = this.getStoreState();
       return _.extend({}, storeState, {
         feedbackState: this.props.feedbackState || storeState.feedbackState
       });
     },
--- a/browser/components/loop/content/shared/js/feedbackViews.jsx
+++ b/browser/components/loop/content/shared/js/feedbackViews.jsx
@@ -19,18 +19,18 @@ loop.shared.views.FeedbackView = (functi
    * Feedback outer layout.
    *
    * Props:
    * -
    */
   var FeedbackLayout = React.createClass({
     propTypes: {
       children: React.PropTypes.component.isRequired,
-      title: React.PropTypes.string.isRequired,
-      reset: React.PropTypes.func // if not specified, no Back btn is shown
+      reset: React.PropTypes.func, // if not specified, no Back btn is shown
+      title: React.PropTypes.string.isRequired
     },
 
     render: function() {
       var backButton = <div />;
       if (this.props.reset) {
         backButton = (
           <button className="fx-embedded-btn-back"
             onClick={this.props.reset}
@@ -232,20 +232,20 @@ loop.shared.views.FeedbackView = (functi
    */
   var FeedbackView = React.createClass({
     mixins: [
       Backbone.Events,
       loop.store.StoreMixin("feedbackStore")
     ],
 
     propTypes: {
-      onAfterFeedbackReceived: React.PropTypes.func,
       // Used by the UI showcase.
       feedbackState: React.PropTypes.string,
-      noCloseText: React.PropTypes.bool
+      noCloseText: React.PropTypes.bool,
+      onAfterFeedbackReceived: React.PropTypes.func
     },
 
     getInitialState: function() {
       var storeState = this.getStoreState();
       return _.extend({}, storeState, {
         feedbackState: this.props.feedbackState || storeState.feedbackState
       });
     },
--- a/browser/components/loop/content/shared/js/views.js
+++ b/browser/components/loop/content/shared/js/views.js
@@ -18,20 +18,20 @@ loop.shared.views = (function(_, l10n) {
    * Required props:
    * - {String}   scope   Media scope, can be "local" or "remote".
    * - {String}   type    Media type, can be "audio" or "video".
    * - {Function} action  Function to be executed on click.
    * - {Enabled}  enabled Stream activation status (default: true).
    */
   var MediaControlButton = React.createClass({displayName: "MediaControlButton",
     propTypes: {
+      action: React.PropTypes.func.isRequired,
+      enabled: React.PropTypes.bool.isRequired,
       scope: React.PropTypes.string.isRequired,
       type: React.PropTypes.string.isRequired,
-      action: React.PropTypes.func.isRequired,
-      enabled: React.PropTypes.bool.isRequired,
       visible: React.PropTypes.bool.isRequired
     },
 
     getDefaultProps: function() {
       return {enabled: true, visible: true};
     },
 
     handleClick: function() {
@@ -78,18 +78,18 @@ loop.shared.views = (function(_, l10n) {
    * - {String}          state       One of the screen sharing states, see
    *                                 loop.shared.utils.SCREEN_SHARE_STATES
    */
   var ScreenShareControlButton = React.createClass({displayName: "ScreenShareControlButton",
     mixins: [sharedMixins.DropdownMenuMixin()],
 
     propTypes: {
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      visible: React.PropTypes.bool.isRequired,
-      state: React.PropTypes.string.isRequired
+      state: React.PropTypes.string.isRequired,
+      visible: React.PropTypes.bool.isRequired
     },
 
     getInitialState: function() {
       var os = loop.shared.utils.getOS();
       var osVersion = loop.shared.utils.getOSVersion();
       // Disable screensharing on older OSX and Windows versions.
       if ((os.indexOf("mac") > -1 && osVersion.major <= 10 && osVersion.minor <= 6) ||
           (os.indexOf("win") > -1 && osVersion.major <= 5 && osVersion.minor <= 2)) {
@@ -184,24 +184,24 @@ loop.shared.views = (function(_, l10n) {
         video: {enabled: true, visible: true},
         audio: {enabled: true, visible: true},
         screenShare: {state: SCREEN_SHARE_STATES.INACTIVE, visible: false},
         enableHangup: true
       };
     },
 
     propTypes: {
+      audio: React.PropTypes.object.isRequired,
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      video: React.PropTypes.object.isRequired,
-      audio: React.PropTypes.object.isRequired,
+      enableHangup: React.PropTypes.bool,
+      hangup: React.PropTypes.func.isRequired,
+      hangupButtonLabel: React.PropTypes.string,
+      publishStream: React.PropTypes.func.isRequired,
       screenShare: React.PropTypes.object,
-      hangup: React.PropTypes.func.isRequired,
-      publishStream: React.PropTypes.func.isRequired,
-      hangupButtonLabel: React.PropTypes.string,
-      enableHangup: React.PropTypes.bool
+      video: React.PropTypes.object.isRequired
     },
 
     handleClickHangup: function() {
       this.props.hangup();
     },
 
     handleToggleVideo: function() {
       this.props.publishStream("video", !this.props.video.enabled);
@@ -254,21 +254,21 @@ loop.shared.views = (function(_, l10n) {
   var ConversationView = React.createClass({displayName: "ConversationView",
     mixins: [
       Backbone.Events,
       sharedMixins.AudioMixin,
       sharedMixins.MediaSetupMixin
     ],
 
     propTypes: {
-      sdk: React.PropTypes.object.isRequired,
-      video: React.PropTypes.object,
       audio: React.PropTypes.object,
       initiate: React.PropTypes.bool,
-      isDesktop: React.PropTypes.bool
+      isDesktop: React.PropTypes.bool,
+      sdk: React.PropTypes.object.isRequired,
+      video: React.PropTypes.object
     },
 
     getDefaultProps: function() {
       return {
         initiate: true,
         isDesktop: false,
         video: {enabled: true, visible: true},
         audio: {enabled: true, visible: true}
@@ -469,18 +469,18 @@ loop.shared.views = (function(_, l10n) {
 
   /**
    * Notification view.
    */
   var NotificationView = React.createClass({displayName: "NotificationView",
     mixins: [Backbone.Events],
 
     propTypes: {
-      notification: React.PropTypes.object.isRequired,
-      key: React.PropTypes.number.isRequired
+      key: React.PropTypes.number.isRequired,
+      notification: React.PropTypes.object.isRequired
     },
 
     render: function() {
       var notification = this.props.notification;
       return (
         React.createElement("div", {className: "notificationContainer"}, 
           React.createElement("div", {className: "alert alert-" + notification.get("level"), 
             key: this.props.key}, 
@@ -502,18 +502,18 @@ loop.shared.views = (function(_, l10n) {
 
   /**
    * Notification list view.
    */
   var NotificationListView = React.createClass({displayName: "NotificationListView",
     mixins: [Backbone.Events, sharedMixins.DocumentVisibilityMixin],
 
     propTypes: {
-      notifications: React.PropTypes.object.isRequired,
-      clearOnDocumentHidden: React.PropTypes.bool
+      clearOnDocumentHidden: React.PropTypes.bool,
+      notifications: React.PropTypes.object.isRequired
     },
 
     getDefaultProps: function() {
       return {clearOnDocumentHidden: false};
     },
 
     componentDidMount: function() {
       this.listenTo(this.props.notifications, "reset add remove", function() {
@@ -550,21 +550,21 @@ loop.shared.views = (function(_, l10n) {
         
         )
       );
     }
   });
 
   var Button = React.createClass({displayName: "Button",
     propTypes: {
+      additionalClass: React.PropTypes.string,
       caption: React.PropTypes.string.isRequired,
-      onClick: React.PropTypes.func.isRequired,
       disabled: React.PropTypes.bool,
-      additionalClass: React.PropTypes.string,
-      htmlId: React.PropTypes.string
+      htmlId: React.PropTypes.string,
+      onClick: React.PropTypes.func.isRequired
     },
 
     getDefaultProps: function() {
       return {
         disabled: false,
         additionalClass: "",
         htmlId: ""
       };
--- a/browser/components/loop/content/shared/js/views.jsx
+++ b/browser/components/loop/content/shared/js/views.jsx
@@ -18,20 +18,20 @@ loop.shared.views = (function(_, l10n) {
    * Required props:
    * - {String}   scope   Media scope, can be "local" or "remote".
    * - {String}   type    Media type, can be "audio" or "video".
    * - {Function} action  Function to be executed on click.
    * - {Enabled}  enabled Stream activation status (default: true).
    */
   var MediaControlButton = React.createClass({
     propTypes: {
+      action: React.PropTypes.func.isRequired,
+      enabled: React.PropTypes.bool.isRequired,
       scope: React.PropTypes.string.isRequired,
       type: React.PropTypes.string.isRequired,
-      action: React.PropTypes.func.isRequired,
-      enabled: React.PropTypes.bool.isRequired,
       visible: React.PropTypes.bool.isRequired
     },
 
     getDefaultProps: function() {
       return {enabled: true, visible: true};
     },
 
     handleClick: function() {
@@ -78,18 +78,18 @@ loop.shared.views = (function(_, l10n) {
    * - {String}          state       One of the screen sharing states, see
    *                                 loop.shared.utils.SCREEN_SHARE_STATES
    */
   var ScreenShareControlButton = React.createClass({
     mixins: [sharedMixins.DropdownMenuMixin()],
 
     propTypes: {
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      visible: React.PropTypes.bool.isRequired,
-      state: React.PropTypes.string.isRequired
+      state: React.PropTypes.string.isRequired,
+      visible: React.PropTypes.bool.isRequired
     },
 
     getInitialState: function() {
       var os = loop.shared.utils.getOS();
       var osVersion = loop.shared.utils.getOSVersion();
       // Disable screensharing on older OSX and Windows versions.
       if ((os.indexOf("mac") > -1 && osVersion.major <= 10 && osVersion.minor <= 6) ||
           (os.indexOf("win") > -1 && osVersion.major <= 5 && osVersion.minor <= 2)) {
@@ -184,24 +184,24 @@ loop.shared.views = (function(_, l10n) {
         video: {enabled: true, visible: true},
         audio: {enabled: true, visible: true},
         screenShare: {state: SCREEN_SHARE_STATES.INACTIVE, visible: false},
         enableHangup: true
       };
     },
 
     propTypes: {
+      audio: React.PropTypes.object.isRequired,
       dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      video: React.PropTypes.object.isRequired,
-      audio: React.PropTypes.object.isRequired,
+      enableHangup: React.PropTypes.bool,
+      hangup: React.PropTypes.func.isRequired,
+      hangupButtonLabel: React.PropTypes.string,
+      publishStream: React.PropTypes.func.isRequired,
       screenShare: React.PropTypes.object,
-      hangup: React.PropTypes.func.isRequired,
-      publishStream: React.PropTypes.func.isRequired,
-      hangupButtonLabel: React.PropTypes.string,
-      enableHangup: React.PropTypes.bool
+      video: React.PropTypes.object.isRequired
     },
 
     handleClickHangup: function() {
       this.props.hangup();
     },
 
     handleToggleVideo: function() {
       this.props.publishStream("video", !this.props.video.enabled);
@@ -254,21 +254,21 @@ loop.shared.views = (function(_, l10n) {
   var ConversationView = React.createClass({
     mixins: [
       Backbone.Events,
       sharedMixins.AudioMixin,
       sharedMixins.MediaSetupMixin
     ],
 
     propTypes: {
-      sdk: React.PropTypes.object.isRequired,
-      video: React.PropTypes.object,
       audio: React.PropTypes.object,
       initiate: React.PropTypes.bool,
-      isDesktop: React.PropTypes.bool
+      isDesktop: React.PropTypes.bool,
+      sdk: React.PropTypes.object.isRequired,
+      video: React.PropTypes.object
     },
 
     getDefaultProps: function() {
       return {
         initiate: true,
         isDesktop: false,
         video: {enabled: true, visible: true},
         audio: {enabled: true, visible: true}
@@ -469,18 +469,18 @@ loop.shared.views = (function(_, l10n) {
 
   /**
    * Notification view.
    */
   var NotificationView = React.createClass({
     mixins: [Backbone.Events],
 
     propTypes: {
-      notification: React.PropTypes.object.isRequired,
-      key: React.PropTypes.number.isRequired
+      key: React.PropTypes.number.isRequired,
+      notification: React.PropTypes.object.isRequired
     },
 
     render: function() {
       var notification = this.props.notification;
       return (
         <div className="notificationContainer">
           <div className={"alert alert-" + notification.get("level")}
             key={this.props.key}>
@@ -502,18 +502,18 @@ loop.shared.views = (function(_, l10n) {
 
   /**
    * Notification list view.
    */
   var NotificationListView = React.createClass({
     mixins: [Backbone.Events, sharedMixins.DocumentVisibilityMixin],
 
     propTypes: {
-      notifications: React.PropTypes.object.isRequired,
-      clearOnDocumentHidden: React.PropTypes.bool
+      clearOnDocumentHidden: React.PropTypes.bool,
+      notifications: React.PropTypes.object.isRequired
     },
 
     getDefaultProps: function() {
       return {clearOnDocumentHidden: false};
     },
 
     componentDidMount: function() {
       this.listenTo(this.props.notifications, "reset add remove", function() {
@@ -550,21 +550,21 @@ loop.shared.views = (function(_, l10n) {
         }
         </div>
       );
     }
   });
 
   var Button = React.createClass({
     propTypes: {
+      additionalClass: React.PropTypes.string,
       caption: React.PropTypes.string.isRequired,
-      onClick: React.PropTypes.func.isRequired,
       disabled: React.PropTypes.bool,
-      additionalClass: React.PropTypes.string,
-      htmlId: React.PropTypes.string
+      htmlId: React.PropTypes.string,
+      onClick: React.PropTypes.func.isRequired
     },
 
     getDefaultProps: function() {
       return {
         disabled: false,
         additionalClass: "",
         htmlId: ""
       };
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.js
+++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.js
@@ -11,21 +11,21 @@ loop.standaloneRoomViews = (function(moz
   var ROOM_STATES = loop.store.ROOM_STATES;
   var sharedActions = loop.shared.actions;
   var sharedMixins = loop.shared.mixins;
   var sharedUtils = loop.shared.utils;
   var sharedViews = loop.shared.views;
 
   var StandaloneRoomInfoArea = React.createClass({displayName: "StandaloneRoomInfoArea",
     propTypes: {
-      isFirefox: React.PropTypes.bool.isRequired,
       activeRoomStore: React.PropTypes.oneOfType([
         React.PropTypes.instanceOf(loop.store.ActiveRoomStore),
         React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore)
-      ]).isRequired
+      ]).isRequired,
+      isFirefox: React.PropTypes.bool.isRequired
     },
 
     onFeedbackSent: function() {
       // We pass a tick to prevent React warnings regarding nested updates.
       setTimeout(function() {
         this.props.activeRoomStore.dispatchAction(new sharedActions.FeedbackComplete());
       }.bind(this));
     },
--- a/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
+++ b/browser/components/loop/standalone/content/js/standaloneRoomViews.jsx
@@ -11,21 +11,21 @@ loop.standaloneRoomViews = (function(moz
   var ROOM_STATES = loop.store.ROOM_STATES;
   var sharedActions = loop.shared.actions;
   var sharedMixins = loop.shared.mixins;
   var sharedUtils = loop.shared.utils;
   var sharedViews = loop.shared.views;
 
   var StandaloneRoomInfoArea = React.createClass({
     propTypes: {
-      isFirefox: React.PropTypes.bool.isRequired,
       activeRoomStore: React.PropTypes.oneOfType([
         React.PropTypes.instanceOf(loop.store.ActiveRoomStore),
         React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore)
-      ]).isRequired
+      ]).isRequired,
+      isFirefox: React.PropTypes.bool.isRequired
     },
 
     onFeedbackSent: function() {
       // We pass a tick to prevent React warnings regarding nested updates.
       setTimeout(function() {
         this.props.activeRoomStore.dispatchAction(new sharedActions.FeedbackComplete());
       }.bind(this));
     },
--- a/browser/components/loop/standalone/content/js/webapp.js
+++ b/browser/components/loop/standalone/content/js/webapp.js
@@ -379,18 +379,18 @@ loop.webapp = (function($, _, OT, mozL10
     }
   });
 
   var InitiateCallButton = React.createClass({displayName: "InitiateCallButton",
     mixins: [sharedMixins.DropdownMenuMixin()],
 
     propTypes: {
       caption: React.PropTypes.string.isRequired,
-      startCall: React.PropTypes.func.isRequired,
-      disabled: React.PropTypes.bool
+      disabled: React.PropTypes.bool,
+      startCall: React.PropTypes.func.isRequired
     },
 
     getDefaultProps: function() {
       return {disabled: false};
     },
 
     render: function() {
       var dropdownMenuClasses = React.addons.classSet({
@@ -436,25 +436,25 @@ loop.webapp = (function($, _, OT, mozL10
 
   /**
    * Initiate conversation view.
    */
   var InitiateConversationView = React.createClass({displayName: "InitiateConversationView",
     mixins: [Backbone.Events],
 
     propTypes: {
+      callButtonLabel: React.PropTypes.string.isRequired,
+      client: React.PropTypes.object.isRequired,
       conversation: React.PropTypes.oneOfType([
                       React.PropTypes.instanceOf(sharedModels.ConversationModel),
                       React.PropTypes.instanceOf(FxOSConversationModel)
                     ]).isRequired,
       // XXX Check more tightly here when we start injecting window.loop.*
       notifications: React.PropTypes.object.isRequired,
-      client: React.PropTypes.object.isRequired,
-      title: React.PropTypes.string.isRequired,
-      callButtonLabel: React.PropTypes.string.isRequired
+      title: React.PropTypes.string.isRequired
     },
 
     getInitialState: function() {
       return {
         urlCreationDateString: "",
         disableCallButton: false
       };
     },
@@ -571,18 +571,18 @@ loop.webapp = (function($, _, OT, mozL10
 
   /**
    * Ended conversation view.
    */
   var EndedConversationView = React.createClass({displayName: "EndedConversationView",
     propTypes: {
       conversation: React.PropTypes.instanceOf(sharedModels.ConversationModel)
                          .isRequired,
-      sdk: React.PropTypes.object.isRequired,
-      onAfterFeedbackReceived: React.PropTypes.func.isRequired
+      onAfterFeedbackReceived: React.PropTypes.func.isRequired,
+      sdk: React.PropTypes.object.isRequired
     },
 
     render: function() {
       document.title = mozL10n.get("standalone_title_with_status",
                                    {clientShortname: mozL10n.get("clientShortname2"),
                                     currentStatus: mozL10n.get("status_conversation_ended")});
       return (
         React.createElement("div", {className: "ended-conversation"}, 
@@ -927,33 +927,31 @@ loop.webapp = (function($, _, OT, mozL10
    */
   var WebappRootView = React.createClass({displayName: "WebappRootView",
 
     mixins: [sharedMixins.UrlHashChangeMixin,
              sharedMixins.DocumentLocationMixin,
              Backbone.Events],
 
     propTypes: {
+      activeRoomStore: React.PropTypes.oneOfType([
+        React.PropTypes.instanceOf(loop.store.ActiveRoomStore),
+        React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore)
+      ]).isRequired,
       client: React.PropTypes.instanceOf(loop.StandaloneClient).isRequired,
       conversation: React.PropTypes.oneOfType([
         React.PropTypes.instanceOf(sharedModels.ConversationModel),
         React.PropTypes.instanceOf(FxOSConversationModel)
       ]).isRequired,
+      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
       notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection)
                           .isRequired,
       sdk: React.PropTypes.object.isRequired,
-
-      // XXX New types for flux style
       standaloneAppStore: React.PropTypes.instanceOf(
-        loop.store.StandaloneAppStore).isRequired,
-      activeRoomStore: React.PropTypes.oneOfType([
-        React.PropTypes.instanceOf(loop.store.ActiveRoomStore),
-        React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore)
-      ]).isRequired,
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired
+        loop.store.StandaloneAppStore).isRequired
     },
 
     getInitialState: function() {
       return this.props.standaloneAppStore.getStoreState();
     },
 
     componentWillMount: function() {
       this.listenTo(this.props.standaloneAppStore, "change", function() {
--- a/browser/components/loop/standalone/content/js/webapp.jsx
+++ b/browser/components/loop/standalone/content/js/webapp.jsx
@@ -379,18 +379,18 @@ loop.webapp = (function($, _, OT, mozL10
     }
   });
 
   var InitiateCallButton = React.createClass({
     mixins: [sharedMixins.DropdownMenuMixin()],
 
     propTypes: {
       caption: React.PropTypes.string.isRequired,
-      startCall: React.PropTypes.func.isRequired,
-      disabled: React.PropTypes.bool
+      disabled: React.PropTypes.bool,
+      startCall: React.PropTypes.func.isRequired
     },
 
     getDefaultProps: function() {
       return {disabled: false};
     },
 
     render: function() {
       var dropdownMenuClasses = React.addons.classSet({
@@ -436,25 +436,25 @@ loop.webapp = (function($, _, OT, mozL10
 
   /**
    * Initiate conversation view.
    */
   var InitiateConversationView = React.createClass({
     mixins: [Backbone.Events],
 
     propTypes: {
+      callButtonLabel: React.PropTypes.string.isRequired,
+      client: React.PropTypes.object.isRequired,
       conversation: React.PropTypes.oneOfType([
                       React.PropTypes.instanceOf(sharedModels.ConversationModel),
                       React.PropTypes.instanceOf(FxOSConversationModel)
                     ]).isRequired,
       // XXX Check more tightly here when we start injecting window.loop.*
       notifications: React.PropTypes.object.isRequired,
-      client: React.PropTypes.object.isRequired,
-      title: React.PropTypes.string.isRequired,
-      callButtonLabel: React.PropTypes.string.isRequired
+      title: React.PropTypes.string.isRequired
     },
 
     getInitialState: function() {
       return {
         urlCreationDateString: "",
         disableCallButton: false
       };
     },
@@ -571,18 +571,18 @@ loop.webapp = (function($, _, OT, mozL10
 
   /**
    * Ended conversation view.
    */
   var EndedConversationView = React.createClass({
     propTypes: {
       conversation: React.PropTypes.instanceOf(sharedModels.ConversationModel)
                          .isRequired,
-      sdk: React.PropTypes.object.isRequired,
-      onAfterFeedbackReceived: React.PropTypes.func.isRequired
+      onAfterFeedbackReceived: React.PropTypes.func.isRequired,
+      sdk: React.PropTypes.object.isRequired
     },
 
     render: function() {
       document.title = mozL10n.get("standalone_title_with_status",
                                    {clientShortname: mozL10n.get("clientShortname2"),
                                     currentStatus: mozL10n.get("status_conversation_ended")});
       return (
         <div className="ended-conversation">
@@ -927,33 +927,31 @@ loop.webapp = (function($, _, OT, mozL10
    */
   var WebappRootView = React.createClass({
 
     mixins: [sharedMixins.UrlHashChangeMixin,
              sharedMixins.DocumentLocationMixin,
              Backbone.Events],
 
     propTypes: {
+      activeRoomStore: React.PropTypes.oneOfType([
+        React.PropTypes.instanceOf(loop.store.ActiveRoomStore),
+        React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore)
+      ]).isRequired,
       client: React.PropTypes.instanceOf(loop.StandaloneClient).isRequired,
       conversation: React.PropTypes.oneOfType([
         React.PropTypes.instanceOf(sharedModels.ConversationModel),
         React.PropTypes.instanceOf(FxOSConversationModel)
       ]).isRequired,
+      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
       notifications: React.PropTypes.instanceOf(sharedModels.NotificationCollection)
                           .isRequired,
       sdk: React.PropTypes.object.isRequired,
-
-      // XXX New types for flux style
       standaloneAppStore: React.PropTypes.instanceOf(
-        loop.store.StandaloneAppStore).isRequired,
-      activeRoomStore: React.PropTypes.oneOfType([
-        React.PropTypes.instanceOf(loop.store.ActiveRoomStore),
-        React.PropTypes.instanceOf(loop.store.FxOSActiveRoomStore)
-      ]).isRequired,
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired
+        loop.store.StandaloneAppStore).isRequired
     },
 
     getInitialState: function() {
       return this.props.standaloneAppStore.getStoreState();
     },
 
     componentWillMount: function() {
       this.listenTo(this.props.standaloneAppStore, "change", function() {
--- a/browser/components/loop/ui/react-frame-component.js
+++ b/browser/components/loop/ui/react-frame-component.js
@@ -20,28 +20,28 @@ window.queuedFrames = [];
  * contents will have been rendered, and then fires a callback indicating that.
  *
  * @see onContentsRendered for the gory details about this.
  *
  * @type {ReactComponentFactory<P>}
  */
 window.Frame = React.createClass({
   propTypes: {
-    style: React.PropTypes.object,
-    head: React.PropTypes.node,
-    width: React.PropTypes.number,
-    height: React.PropTypes.number,
-    onContentsRendered: React.PropTypes.func,
     className: React.PropTypes.string,
     /* By default, <link rel="stylesheet> nodes from the containing frame's
        head will be cloned into this iframe.  However, if the link also has
        a "class" attribute, we only clone it if that class attribute is the
        same as cssClass.  This allows us to avoid injecting stylesheets that
        aren't intended for this rendering of this component. */
-    cssClass: React.PropTypes.string
+    cssClass: React.PropTypes.string,
+    head: React.PropTypes.node,
+    height: React.PropTypes.number,
+    onContentsRendered: React.PropTypes.func,
+    style: React.PropTypes.object,
+    width: React.PropTypes.number
   },
   render: function() {
     return React.createElement("iframe", {
       style: this.props.style,
       head: this.props.head,
       width: this.props.width,
       height: this.props.height,
       className: this.props.className
--- a/browser/components/loop/ui/ui-showcase.js
+++ b/browser/components/loop/ui/ui-showcase.js
@@ -430,21 +430,21 @@
       return (
         React.createElement("ul", {className: "svg-icon-list"}, icons)
       );
     }
   });
 
   var FramedExample = React.createClass({displayName: "FramedExample",
     propTypes: {
-      width: React.PropTypes.number,
+      cssClass: React.PropTypes.string,
+      dashed: React.PropTypes.bool,
       height: React.PropTypes.number,
       onContentsRendered: React.PropTypes.func,
-      dashed: React.PropTypes.bool,
-      cssClass: React.PropTypes.string
+      width: React.PropTypes.number
     },
 
     makeId: function(prefix) {
       return (prefix || "") + this.props.summary.toLowerCase().replace(/\s/g, "-");
     },
 
     render: function() {
       var height = this.props.height;
--- a/browser/components/loop/ui/ui-showcase.jsx
+++ b/browser/components/loop/ui/ui-showcase.jsx
@@ -430,21 +430,21 @@
       return (
         <ul className="svg-icon-list">{icons}</ul>
       );
     }
   });
 
   var FramedExample = React.createClass({
     propTypes: {
-      width: React.PropTypes.number,
+      cssClass: React.PropTypes.string,
+      dashed: React.PropTypes.bool,
       height: React.PropTypes.number,
       onContentsRendered: React.PropTypes.func,
-      dashed: React.PropTypes.bool,
-      cssClass: React.PropTypes.string
+      width: React.PropTypes.number
     },
 
     makeId: function(prefix) {
       return (prefix || "") + this.props.summary.toLowerCase().replace(/\s/g, "-");
     },
 
     render: function() {
       var height = this.props.height;