TweetBox (Mobx + React)

by ramnathv

HTML

<script src="https://npmcdn.com/[email protected]/lib/mobx.umd.js"></script>
<script src="https://npmcdn.com/[email protected]/index.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/react/0.14.3/react-dom.min.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<div class="container" id="main">
  <div class="row">
    <div class="col-xs-12 col-md-6">
      <div id="app"></div>
    </div>
  </div>
</div>

CSS

#main{margin-top: 20px;}
.list-group-item{
  border-radius: 0px !important;
}
.form-control{
  border-radius: 0px !important;
}
.constraint .edit, 
.constraint .delete{
  visibility: hidden;
}

.constraint:hover .edit, 
.constraint:hover .delete{
  visibility: visible;
}
.constraint{
  
}
.tweet-editor{
  resize: vertical;
}
.tweet-actions{
  margin-top: 10px;
}

Babel + JSX

const {observable, computed, extendObservable} = mobx;
const {observer} = mobxReact;
const {Component} = React;
const {render} = ReactDOM

class Store {
 @observable tweetText = ""
 @observable photoAdded = false
 @computed get remainingChars(){
   return 140 - this.tweetText.length - 23*this.photoAdded
 }
 @computed get disableTweetButton(){
   return this.tweetText.length === 0
 }
 @computed get photoButtonText(){
   return this.photoAdded ? 'Photo Added' : 'Add Photo'
 }
 togglePhotoAdded(){
   this.photoAdded = !this.photoAdded
 }
}


const TweetAlert = observer(({store}) => {
  if (store.remainingChars >= 0) return(null)
  return(
    <div className="alert alert-warning" role="alert">
      Oops! Too Long
    </div>
  )
})



const TweetEditor = observer(({store}) => {
  return(
    <textarea 
      rows="5"
      className="form-control tweet-editor" 
      defaultValue={store.tweetText}
      onChange={(e) => store.tweetText = e.target.value}
    />
  )
})

const TweetActions = observer(({store}) => {
  console.log(store.disableTweetButton)
  return(
    <div className="tweet-actions">
      <span className="pull-left">
        {store.remainingChars}
      </span>
      <span className="pull-right">
        <div className="btn-group">
          <button 
            className="btn btn-sm btn-default"
            onClick = {store.togglePhotoAdded.bind(store)}
          >
            {store.photoButtonText}
          </button>
          <button 
            className="btn btn-sm btn-primary"
            disabled={store.disableTweetButton}
          >
            Tweet
          </button>
        </div>
      </span>
    </div>
  )
})


const App = observer(({store}) => {
  return(
    <div className="well clearfix">
      <h3>TweetBox</h3>
      <TweetAlert store={store}/>
      <TweetEditor store={store}/>
      <TweetActions store={store} />
    </div>
  ) 
})

const myStore = new Store();
                        
render(
  <App store={myStore} />,
 ...