Skip to content

Commit

Permalink
Refactored form component to handle auto growth a bit better
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelclemens committed Mar 6, 2016
1 parent ed71736 commit 4385c93
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 74 deletions.
103 changes: 44 additions & 59 deletions client/reader/comments/form.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ class PostCommentForm extends React.Component {
super();

this.state = {
isButtonActive: props.commentText && props.commentText.length > 0,
isButtonVisible: props.commentText && props.commentText.length > 0
commentText: props.commentText || '',
haveFocus: false
};

// bind event handlers to this instance
Expand All @@ -37,24 +37,21 @@ class PostCommentForm extends React.Component {
.forEach( ( prop ) => this[ prop ] = this[ prop ].bind( this ) );
}

componentWillReceiveProps( nextProps ) {
this.setState( {
commentText: nextProps.commentText || ''
} );
}

componentDidMount() {
// If it's a reply, give the input focus if commentText exists ( can not exist if comments are closed )
if ( this.props.parentCommentID && this.refs.commentText ) {
this.refs.commentText.focus();
if ( this.props.parentCommentID && this._textareaNode ) {
this._textareaNode.focus();
}
}

componentDidUpdate() {
const commentTextNode = this.refs.commentText;
// can happen if comments are closed
if ( ! commentTextNode ) {
return;
}

const commentText = this.getCommentText();
const currentHeight = parseInt( commentTextNode.style.height, 10 ) || 0;

commentTextNode.style.height = commentText.length ? Math.max( commentTextNode.scrollHeight, currentHeight ) + 'px' : null;
handleTextAreaNode( textareaNode ) {
this._textareaNode = textareaNode;
}

handleSubmit( event ) {
Expand All @@ -80,58 +77,34 @@ class PostCommentForm extends React.Component {
}
}

handleKeyUp() {
this.updateCommentText();
}

handleFocus() {
this.toggleButtonVisibility( true );
this.setState( { haveFocus: true } );
}

handleBlur() {
if ( ! this.hasCommentText() ) {
this.toggleButtonVisibility( false );
}
this.setState( { haveFocus: false } );
}

toggleButtonVisibility( isVisible ) {
this.setState( { isButtonVisible: isVisible } );
}
handleTextChange( event ) {
const commentText = event.target.value;

updateCommentText() {
const commentText = this.getCommentText();
this.setState( { commentText } );

// Update the comment text in the container's state
this.props.onUpdateCommentText( commentText );

// If there's content, make the button active
this.setState( { isButtonActive: this.hasCommentText() } );
}

resetCommentText() {
const commentTextNode = this.refs.commentText;
commentTextNode.value = '';
this.setState( { isButtonActive: false } );
this.toggleButtonVisibility( false );
this.setState( { commentText: '' } );
}

hasCommentText() {
const commentText = this.getCommentText();
return ( commentText && commentText.length > 0 );
}

getCommentText() {
if ( ! this.refs.commentText ) {
return;
}

return this.refs.commentText.value.trim();
return this.state.commentText.trim().length > 0;
}

submit() {
const post = this.props.post;
const commentTextNode = this.refs.commentText;
const commentText = commentTextNode.value.trim();
const commentText = this.state.commentText.trim();

if ( ! commentText ) {
this.resetCommentText(); // Clean up any newlines
Expand Down Expand Up @@ -191,25 +164,37 @@ class PostCommentForm extends React.Component {
}

const buttonClasses = classNames( {
'is-active': this.state.isButtonActive,
'is-visible': this.state.isButtonVisible
'is-active': this.hasCommentText(),
'is-visible': this.state.haveFocus || this.hasCommentText()
} );

const expandingAreaClasses = classNames( {
focused: this.state.haveFocus,
'expanding-area': true
} );

// how auto expand works for that textarea is covered in this article: http://alistapart.com/article/expanding-text-areas-made-elegant
return (
<form className="comments__form" ref="commentForm">
<fieldset>
<Gravatar user={ this.props.currentUser } />
<label>
<textarea
defaultValue={ this.props.commentText }
rows="1"
placeholder={ translate( 'Enter your comment here…' ) }
ref="commentText"
onKeyUp={ this.handleKeyUp }
onKeyDown={ this.handleKeyDown }
onFocus={ this.handleFocus }
onBlur={ this.handleBlur } />
<button ref="commentButton" className={ buttonClasses } disabled={ ! this.state.isButtonActive } onClick={ this.handleSubmit }>{ translate( 'Send' ) }</button>
<div className={ expandingAreaClasses } >
<pre><span>{ this.state.commentText }</span><br/></pre>
<textarea
value={ this.state.commentText }
placeholder={ translate( 'Enter your comment here…' ) }
ref={ this.handleTextAreaNode }
onKeyUp={ this.handleKeyUp }
onKeyDown={ this.handleKeyDown }
onFocus={ this.handleFocus }
onBlur={ this.handleBlur }
onChange={ this.handleTextChange }
/>
</div>
<button ref="commentButton" className={ buttonClasses } disabled={ this.state.commentText.length === 0 } onClick={ this.handleSubmit }>
{ translate( 'Send' ) }
</button>
{ this.renderError() }
</label>
</fieldset>
Expand Down
8 changes: 4 additions & 4 deletions client/reader/comments/post-comment.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class PostComment extends React.Component {

handleReply() {
this.props.onReplyClick( this.props.commentId );
this.setState( { showReplies: true } ); // show the comments when replying
}

handleAuthorClick() {
Expand All @@ -63,8 +64,7 @@ class PostComment extends React.Component {
const commentChildrenIds = this.props.commentsTree.getIn( [ this.props.commentId, 'children' ] ).toJS();
// Hide children if more than maxChildrenToShow, but not if replying
const showReplies = this.state.showReplies || // use wanted to show comments
commentChildrenIds.length < this.props.maxChildrenToShow || // we have less comments than required to hide
this.props.activeReplyCommentID === this.props.commentId; // user replying that comment
commentChildrenIds.length < this.props.maxChildrenToShow; // we have less comments than required to hide

// No children to show
if ( ! commentChildrenIds || commentChildrenIds.length < 1 ) {
Expand Down Expand Up @@ -123,8 +123,8 @@ class PostComment extends React.Component {

return (
<div className="comment__actions">
{ showReplyButton ?
<button className="comment__actions-reply" onClick={ this.handleReply }>
{ showReplyButton
? <button className="comment__actions-reply" onClick={ this.handleReply }>
<Gridicon icon="reply" size={ 18 } />
<span className="comment__actions-reply-label">{ translate( 'Reply' ) }</span>
</button>
Expand Down
51 changes: 40 additions & 11 deletions client/reader/comments/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
position: relative;
padding: 0 0 0 48px;
margin-top: 24px;
margin-bottom: -12px;

.gravatar {
position: absolute;
Expand All @@ -27,21 +26,51 @@
border-radius: 48px;
}

input, textarea {
input {
font-size: 14px;
padding: 5px 10px;
}

textarea {
max-height: 400px;
min-height: 33px;
height: 33px;
padding-right: 60px;
resize: vertical;
font-family: $serif;
// The inner working of these styles is covered here: http://alistapart.com/article/expanding-text-areas-made-elegant
.expanding-area {
position: relative;
$initial-focused-height: 70px;

pre,
textarea {
max-height: 400px;
min-height: 33px;
margin: 0;
padding: 5px 60px 5px 5px;
resize: vertical;
font-size: 14px;
font-family: $serif;
line-height: 21px;

white-space: pre-wrap;
word-wrap: break-word;

&:focus {
min-height: $initial-focused-height;
}
}

textarea {
position: absolute;
top: 0;
left: 0;
height: 100%;
}

pre {
border: 1px solid $gray;
box-sizing: border-box;
display: block;
visibility: hidden;
}

&:focus {
min-height: 70px;
&.focused {
min-height: $initial-focused-height;
}
}

Expand Down

0 comments on commit 4385c93

Please sign in to comment.