Reputation: 11863
I am working on a React app in which there is a section of behavior which should behave as follows. There are a list of steps (which are collapsible and expandable). There is ability for the user to select the "Start Loop" link after which some selectable circles appear for the user to select which step they want to loop back to. Upon selecting that step, there should be a curve that is drawn to indicate that that connection has been made.
Here is a diagram to show how I want it to be:
Currently, I am able to get steps 1 and 2 working but am lost at how to achieve step 3. Here is a React fiddle to show you what I have so far.
https://jsfiddle.net/xaz7c6Le/7/
I have two issues:
1) If you look at the CSS for startMarker
and clickCircle
, you'll notice that I am trying to absolutely position those elements. However, with some browser window resizing, it is evident that that does not work. How do I get those elements to always rename vertically centered within the step div it is a part of?
Just FYI, my question is about the behavior, alignment of elements, and drawing of lines, NOT on how well the JSFiddle React code is written. (The real application is quite extensive and adheres to React best practices but to get something to show on the JSFiddle, I just threw something together).
My code is below:
class LoopApp extends React.Component {
constructor(props) {
super(props);
this.state = {
showCircles: false,
selectedCircleIndex: -1,
steps: [
{ title: "Step 1", partOfLoop: false },
{ title: "Step 2", partOfLoop: false },
{ title: "Step 3", partOfLoop: false },
{ title: "Step 4", partOfLoop: false }
]
}
}
showCircles() {
this.setState({ showCircles: true });
}
selectCircle(idx) {
this.setState({ selectedCircleIndex: idx });
}
render() {
return (
<div>
<h2>Block A:</h2>
<div class="inner-block">
{
this.state.steps.map((step, index) =>
<div class="step-entry">
{index + 1}. {step.title}
{
this.state.showCircles &&
<div
className={"clickCircle " + (this.state.selectedCircleIndex === index ? "selected" : "" )}
onClick={() => this.selectCircle(index)}></div>
}
</div>
)
}
<div class="step-entry">
5. Step 5
<a
class="start-loop"
onClick={() => this.showCircles()}>Start loop
</a>
{
this.state.showCircles && <div class="startMarker"></div>
}
</div>
</div>
</div>
)
}
}
ReactDOM.render(<LoopApp />, document.querySelector("#app"))
CSS
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
.inner-block {
margin-top: 10px;
border: 1px black solid;
width: 30%;
}
.step-entry {
padding: 20px;
position: relative;
border-bottom: 1px solid black;
}
.clickCircle {
position: absolute;
border: 1px solid blue;
border-radius: 50%;
height: 20px;
width: 20px;
left: 97%;
top: 18px;
background-color: white;
}
.clickCircle:hover {
background-color: orange;
}
.selected {
background-color: orange;
}
.start-loop {
float: right;
color: orange;
}
.start-loop:hover {
cursor: pointer;
text-decoration: underline;
}
.startMarker {
position: absolute;
width: 20px;
height: 10px;
background-color: orange;
top: 25px;
left: 97%;
}
Upvotes: 1
Views: 1791
Reputation: 1464
95% working solution on JSFiddle
To answer your questions:
<div className="step-entry">
<div className="startMarker"/>
</div>
You can implement the following CSS:
.step-entry {
display: flex;
align-items: center;
}
This will align the children of .step-entry
vertically in relation to the .step-entry
element.
Unfortunately, I do not have an answer to horizontally aligning .startMarker
.
One possible solution to the line connecting two circles is to have a box behind your .step-entry
elements and offset it so that its right section is sticking out to the right of your Logo App.
You can then manipulate the height that underlying box to match the distance between the selected circle and the last circle.
I was able to work out the calculations in an onClick
event handler set on the circles.
Upvotes: 3