nkbt/react-collapse

Collapse "jumps" as it nears the end of an animation

SethArchambault opened this issue ยท 7 comments

react-collapse-glitchiness

This seems to happen everywhere I use it..

<h1>Mass Text</h1>
  <TextComposer message={this.state.message} onChange={this._handleMessageUpdate} />
  <TestPanel>
    <Collapse isOpened={!this.state.text_message_approved && this.state.message.length > 0}>
      <hr />
      <h3>Next Step: Testing</h3>
      <div className="form-group">
        My Cellphone
        <select className="form-control" onChange={this._handleSendTestTo} value={this.state.user_to_send_test_to}>
        { this.state.proup_team_members.map(
          (team_member, index)=>(
            <option value={index} key={index}>{team_member.last_name} {team_member.location.cell_phone_carrier}</option>
            ) 
          )}
        </select>  
      </div>
      <div className="form-group">
      <a href="#" className="btn btn-proup-black-background-white" onClick={this._handleSendTestText}>Send Test Text</a>
      </div>
    </Collapse>
    <Collapse isOpened={this.state.message.length > 0}>
      <div className="form-group">
      Text Message Looks Good On My Phone <input onChange={this._handleTextMessageApproved} className="form-control" type="checkbox" name="" />
      </div>
    </Collapse>
  </TestPanel>
  <AdvancedPanel>
    <Collapse isOpened={this.state.text_message_approved}>
      <h3>Next Step: Send It Out</h3>

      <div className="form-group">
      Advanced <input id="advanced-check" onChange={this._handleAdvancedChecked} className="form-control" type="checkbox" name="" />
      </div>
        <Collapse isOpened={this.state.show_advanced_panel}>
          <div>
            <div className="form-group">
            <select className="form-control" 
            onChange={this._handleProviderFilter} 
            value={this.state.providers}>
            <option value="all">All Providers</option>
            <option value="tmobile">T-Mobile Only</option>
            <option value="not-tmobile">All But T-Mobile</option>
            </select>
            </div>
            <div className="form-group">
            Send, Starting From ID
            <input className="form-control" type="text" onChange={this._handleStartingId} value={this.state.starting_id} />
            </div>
          </div>
        </Collapse>
    </Collapse>
  </AdvancedPanel>
  <SendPanel>
    <Collapse isOpened={this.state.text_message_approved}>

        <div className="form-group">
          <div><a href="#" className="btn btn-proup-black-background-white" onClick={this._handleSendMassText}>Send Mass Text</a><br /><br /></div>
          <div><a href="#" className="btn btn-proup-black-background-white" onClick={this._handleCancelSending}>Cancel Sending</a></div>
        </div>
    </Collapse>
  </SendPanel>
  </div>`
nkbt commented

The reason is because some of the child components most likely have margins (or some components that surround collapse). It is impossible to measure those "effects" until component is completely expanded (some margins are "squashed" or the other way doubled, depending on different conditions). I suggest to avoid using margins on components inside collapse and stick to paddings. The container itself should ideally have neither paddings nor margins (ideally). It needs some tweaking on app level.

can't react-height calculate the margins via el.getComputedStyle() and just add them on?

nkbt commented

I believe that it is out of scope for the component. There are many edge cases that will have incorrect behaviour unfortunately. I had it done this way before and would not do it on a public library. It is way easier not to add margins/paddings to collapse element and style all the elements inside and outside of it so everything looks like expected. PS react-collapse@3 does not use react-height anymore, but still assumes its own element has no padding/margins

Ah, collapsing margins would be a pain to calculate, I agree. Alright, this is closable then I guess - but a mention in the readme about this behavior would probably be good. I'll submit a PR

A bit late to the party, but you can work with margins if you add a clearfix to the content element like this:

.ReactCollapse--content:after,
.ReactCollapse--content:before {
    content: "";
    display: table;
}
nkbt commented

Thanks @LucusWebsites for suggestion! Feel free to add it to Behaviour notes section of README - that would most likely help somebody in the future
๐Ÿ™Œ๐Ÿป

My solution might not be generalisable because I had a single <ul> element as a child to the <Collapse> component.

What I did was to add display: flow-root; to the <ul> so that the margins of the <li> children were respected on the expand animation.