Search code examples
javascriptcssangularsassangular-material

Angular Material drag&drop stacked deck of cards and auto expand on hover


How can I achieve the following behaviour using Angular Material and Drag&Drop functionalities? I want to be able to see the cards fully expanded on mouse over, so the other cards below just move down their absolute margin-tops, and still be able to rearrange them using drag&drop cdk.

Those are a couple of examples from a website that offers this functionality. I was wondering if it can be done with Angular and Material.

Stacked drag&drop sortable hoverable Stacked drag&drop sortable hoverable

I was able to stack them by using position: absolute and margin-top: calc(35% * (var(--index))); them but still don't know how to make the one hovered full height while pushing the others below down.

Also, my solution seems to be a bit clumsy as it recalculates the margin a lot when there is a drag movement, you can see how it "jumps" or "staggers" a lot. That would be another problem, though.

This is my example: https://stackblitz.com/edit/gabkl9-zywnff?file=src%2Fexample%2Fcdk-drag-drop-sorting-example.css

Thanks in advance.


Solution

  • We can use the general sibling selector (~) to offset the other cards, below a height, here 130px, this will give the desired result!

    .example-box:hover ~ div.example-box {
      margin-top: calc((35% * (var(--index))) + 130px);
    }
    

    full css

    .example-list {
      width: 200px;
      height: 100%;
      display: block;
      position: relative;
    }
    
    .example-box {
      position: absolute;
      height: 200px;
      width: 200px;
      padding: 20px 10px;
      border: solid 1px #ccc;
      box-sizing: border-box;
      cursor: move;
      background: white;
      margin-top: calc(35% * (var(--index)));
    }
    
    .example-box:hover ~ div.example-box {
      margin-top: calc((35% * (var(--index))) + 130px);
    }
    
    .cdk-drag-preview {
      box-sizing: border-box;
      border-radius: 4px;
      box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
        0 8px 10px 1px rgba(0, 0, 0, 0.14), 0 3px 14px 2px rgba(0, 0, 0, 0.12);
    }
    
    .cdk-drag-placeholder {
      opacity: 0;
    }
    
    .cdk-drag-animating {
      transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
    }
    
    .example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder) {
      transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
    }
    

    Stackblitz Demo