T. Evans
T. Evans

Reputation: 1011

Flexbox Expandable Items in Row, stop row expanding with item

I have items in flexbox showing in 2 columns. The items are expandable (similar to dropdowns). When the user clicks on the item it expands, but also expands the row with it. I am wanting the item to expand when clicking but not the row.

What is happening: enter image description here

What is supposed to happen: enter image description here

The code for the columns:

list {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  margin: 80px auto 0;
  max-width: 1096px;

  @include mediaQuery(max, 1080px) {
    width: 940px;
  }

  @include mediaQuery(max, $tablet) {
    width: 526px;
  }

  @include mediaQuery(max, $mobile) {
    width: 335px;
  }

  @include mediaQuery(max, 320px) {
    width: 285px;
  }
}

I have tried to find similar questions here on stack, but it seems that no one else is running into this or this has not been asked before.

Any help would be appreciated! Thanks

ADDON TO QUESTION:

<div className="analyzed-genes-list">
  {
   data.map((item, index) => (
    <GeneCard key={index} gene={item.gene} cancers={item.cancers} positives={this.state.posGenes} traits={this.state.traits} />
   ))
  }
 </div>

GeneCard.js

<div className={this.state.toggleBody ? "gene-card-active" : "gene-card"}>
  <div className="gene-card-title" onClick={this.showBody} style={{backgroundImage: this.state.toggleBody ? `url(${ChevronUp})` : `url(${ChevronDown})`}}>
    <span className="gene-name">{this.props.gene}</span>
      {
       this.state.pos ?
        <span className="pos-variant">{this.state.variants} variant
         { this.state.variants > 1 ? 's' : null }
           &nbsp;detected</span>
           :
           <span className="variant">Variant not detected</span>
         }
        </div>
        {
          this.state.toggleBody ?
          <div className="gene-card-body">
            {
              this.props.cancers.map((cancer, index) => (
                <span key={cancer} className="cancer">
                  {cancer}
                  {
                    index === this.props.cancers.length - 1 ?
                    null
                    :
                    ','
                  }
                  &nbsp;
                </span>
              ))
            }
          </div>
          :
          null
        }
      </div>

Upvotes: 2

Views: 1991

Answers (3)

T. Evans
T. Evans

Reputation: 1011

This is probably one way to do it...not a CSS solution, however...

Basically, you take the data coming in and divide it in half. So you'll be rendering 2 different arrays in React.

List:

componentDidMount(){
  let first = data.slice(0, Math.round(data.length / 2));

  let second = data.slice(Math.round(data.length / 2), data.length);

   this.setState({
      firstHalfData: first,
      lastHalfData: second
    });
}

JSX:

<div className="analyzed-genes-list">
   <div className="analyzed-genes-list-col">
      {
        this.state.firstHalfData.map((item, index) => (
         <GeneCard key={index} gene={item.gene} cancers={item.cancers} positives={this.state.posGenes} traits={this.state.traits} />
           ))
         }
       </div>
     <div className="analyzed-genes-list-col">
        {
          this.state.lastHalfData.map((item, index) => (
           <GeneCard key={index} gene={item.gene} cancers={item.cancers} positives={this.state.posGenes} traits={this.state.traits} />
            ))
         }
       </div>
     </div>

the CSS:

.analyzed-genes-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  margin: 80px auto 0;
  max-width: 1096px;
  width: 100%;

  @include mediaQuery(max, 1080px) {
    width: 940px;
  }

  @include mediaQuery(max, $tablet) {
    width: 526px;
  }

  @include mediaQuery(max, $mobile) {
    width: 335px;
  }

  @include mediaQuery(max, 320px) {
    width: 285px;
  }
}

.analyzed-genes-list-col {
  display: flex;
  flex-direction: column;
  max-width: 526px;

  @include mediaQuery(min, 1081px) {
    width: 508px;
  }

  @include mediaQuery(max, 1080px) {
    width: 440px;
  }

  @include mediaQuery(max, $tablet) {
    width: 100%;
  }
}

if someone has a solution for CSS I am all ears!

Upvotes: 0

Thijs Steel
Thijs Steel

Reputation: 1272

Here's a css solution using the columns feature of css.

.wrapping-list {
  columns: 2;
}

.list-item {
  padding: 5px;
  margin-bottom: 10px;
  background: red;
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
  page-break-inside: avoid;
}

.list-item-expansion {
  width: 100%;
  height: 50px;
  background: blue;
}
<div class="wrapping-list">
    <div class="list-item">
      test
      <div class="list-item-expansion">
        expansion
      </div>
    </div>
    <div class="list-item">test</div>
    <div class="list-item">test</div>
    <div class="list-item">test</div>
    <div class="list-item">test</div>
    <div class="list-item">test</div>
    <div class="list-item">test</div>
    <div class="list-item">test</div>
    <div class="list-item">test</div>
    <div class="list-item">test</div>
</div>

Upvotes: 1

Thijs Steel
Thijs Steel

Reputation: 1272

I wrote a quick example of how this can be achieved with css.

When using absolute positioning, the box does not take up space, so the other boxes do not move down. The relative positioning is necessary to get the positioning right.

function activate() {
    const listItem = document.getElementById("listitem1");
    const expansion = document.getElementById("expansion1");
    expansion.classList.toggle("active");
    expansion.style.top = listItem.clientHeight + "px";
}
.container {
  margin-top: 10px;
  display: flex;
  width: 300px;
  height: 300px;
  flex-direction: column;
}

.listitem {
  flex: 1;
  margin-top: 10px;
  background-color: red;
}

.listitem-expanded {
  display: none;
  position: absolute;
  top: 0px;
  width: 100%;
  height: 50px;
  background-color: blue;
}

.listitem-expanded.active {
    display: block;
}
<div class="container">
  <div id="listitem1" class="listitem" onclick="activate()">
    <div style="position: relative">
      <div id="expansion1" class="listitem-expanded">expansion</div>
    </div>
    test
  </div>
  <div class="listitem">test</div>
  <div class="listitem">test</div>
  <div class="listitem">test</div>
  <div class="listitem">test</div>
  <div class="listitem">test</div>
</div>

Upvotes: 0

Related Questions