GUERU
GUERU

Reputation: 75

Building a page layout using the FLIP technique

I'm a beginner in programming, and I'm trying to build a page layout using the FLIP technique in React, but I'm stuck, so I'd like to ask for your help. For more information about the FLIP technique, please refer to the reference URL.

Quickly, what I would like to build is a page layout that consists of one main content and multiple sub-contents, as shown in the image below, and that can be repositioned with the main content by clicking on the sub-content. enter image description here

I found a layout similar to the one I want to create by surfing the net, and I've included it below as a reference URL.

・What I tried.

I thought I could achieve this using hooks, CSS, and the react-flip-toolkit -library-. In fact, the code to swap the position of the two elements was easy to implement.

enter image description here

https://codesandbox.io/s/flip-l4o04?file=/src/index.js

However, I don't know how to write the code to control the behavior when the number of contents is increased. The react-flip-toolkit uses the flipkey as a key, so if I just add more containers, onclick will fire all the containers in the flipper tag and it won't work.

enter image description here

https://codesandbox.io/s/flip-test-f3pqb?file=/src/index.js

Next, I rewrote some of the code.

const AnimatedSquare = () => {
  const [active, setActive] = useState(false);
  const toggleActive = () => setActive(prevState => !prevState);

  const [active1, setActive1] = useState(false);
  const toggleActive1 = () => setActive1(prevState => !prevState);

  return (
    <div>
    <Flipper flipKey={active,active1}>
      <div className="box">
      <Flipped flipId="square">
        <div
          className={active ? "square" : "square-active"}
          onClick={toggleActive}/>
      </Flipped>
      <Flipped flipId="square1">
        <div
          className={active1 ? "square-active-1" : "square1"}
          onClick={toggleActive1}/>
      </Flipped>

enter image description here

Only the part of the code that was rewritten now behaves independently, but this is not good enough because it cannot be repositioned with the main content.

・Question

What code should I write to make each container behave independently and swap its position with the main content as shown in the reference URL? I would appreciate your help.

~Reference URL~

・About the FLIP technique

・What I want to build like this

Upvotes: 3

Views: 206

Answers (1)

wowandy
wowandy

Reputation: 1302

I think this is what you want

I just divide active state on squares and accumulate active square classes

If someday the link stops opening, I attach the code below

import React, { useCallback, useState } from "react";
import ReactDOM from "react-dom";
import { Flipper, Flipped } from "react-flip-toolkit";
import "./styles.css";

const AnimatedSquare = () => {
  const [active, setActive] = useState({
    square1: true,
    square2: false,
    square3: false,
    square4: false,
    square5: false
  });
  const handleActive = useCallback(
    (id) => () =>
      setActive({
        square1: false,
        square2: false,
        square3: false,
        square4: false,
        square5: false,
        [id]: true
      }),
    []
  );

  return (
    <div>
      <Flipper flipKey={true}>
        <div className="box">
          <Flipped flipId="square1">
            <div
              className={`square1${active.square1 ? " active" : ""}`}
              onClick={handleActive("square1")}
            ></div>
          </Flipped>
          <Flipped flipId="square2">
            <div
              className={`square2${active.square2 ? " active" : ""}`}
              onClick={handleActive("square2")}
            />
          </Flipped>
        </div>
        <Flipped flipId="square3">
          <div
            className={`square3${active.square3 ? " active" : ""}`}
            onClick={handleActive("square3")}
          />
        </Flipped>
        <Flipped flipId="square4">
          <div
            className={`square4${active.square4 ? " active" : ""}`}
            onClick={handleActive("square4")}
          />
        </Flipped>
        <Flipped flipId="square5">
          <div
            className={`square5${active.square5 ? " active" : ""}`}
            onClick={handleActive("square5")}
          />
        </Flipped>
      </Flipper>
    </div>
  );
};

ReactDOM.render(<AnimatedSquare />, document.querySelector("#root"));
* {
  box-sizing: border-box;
}

body {
  justify-content: left;
  align-items: left;
  min-height: 100vh;
}

.box {
  position: relative;
}

.square1 {
  transition: all 1s;
  margin-top: 10px;
  margin-left: 5px;
  margin-right: 5px;
  width: 17rem;
  height: 12rem;
  cursor: pointer;
  background-image: linear-gradient(45deg, rgb(0, 255, 0), rgb(71, 182, 108));
}

.square2 {
  transition: all 1s;
  margin-top: 10px;
  margin-left: 5px;
  margin-right: 5px;
  width: 17rem;
  height: 12rem;
  cursor: pointer;
  background-image: linear-gradient(45deg, rgb(255, 0, 255), rgb(182, 71, 158));
}

.square3 {
  transition: all 1s;
  margin-top: 10px;
  margin-left: 5px;
  margin-right: 5px;
  width: 17rem;
  height: 12rem;
  cursor: pointer;
  background-image: linear-gradient(
    45deg,
    rgb(113, 206, 234),
    rgb(60, 107, 170)
  );
}

.square4 {
  transition: all 1s;
  margin-top: 10px;
  margin-left: 5px;
  margin-right: 5px;
  width: 17rem;
  height: 12rem;
  cursor: pointer;
  background-image: linear-gradient(45deg, rgb(253, 72, 0), rgb(170, 110, 60));
}

.square5 {
  transition: all 1s;
  margin-top: 10px;
  margin-left: 5px;
  margin-right: 5px;
  width: 17rem;
  height: 12rem;
  cursor: pointer;
  background-image: linear-gradient(45deg, rgb(255, 0, 0), rgb(182, 71, 71));
}

.active {
  position: fixed;
  top: 0;
  transform: translateX(300px);
  width: 75rem;
  height: 50rem;
  cursor: pointer;
}

Upvotes: 1

Related Questions