React/css Flexbox with stylable rows - javascript

i have a specific use case, and i am not sure what component or technology i can use for that.
I have a set of items in a wrapped flexbox:
xxx|xxxxxxxx|xx|xxxxxxxxx|
x|xxxxxx|xxxxxxxxxxxxxxx|xxx|
xxxxx|xxxxxxxxxx|XXXX|xxxx
xxxx|xxxxx|xxxxxxxxx
The items have different widths, but fixed heights. And their should be wrapped, so that there is no horizontal overflow. And there is alway one "active" item, which has a diffent style.
For now flexbox works perfecly fine for me. Here's a demo:
.wpr {
width: 150px;
display:flex;
flex-flow: row wrap;
border: 1px solid green;
}
span {
position: relative;
display: inline-block;
padding: 0 2px;
}
span:after {
content: '';
position: absolute;
right: 0;
width: 1px;
height: 16px;
background-color: #111;
}
.special {
color: green;
}
<div class="wpr">
<span>xxx</span>
<span>xxxxxx</span>
<span>xxx</span>
<span>xxxxx</span>
<span>xxx</span>
<span>xxxxx</span>
<span class="special">XXX</span>
<span>xx</span>
<span>xxxxxxxx</span>
<span>xx</span>
</div>
But now i want to also highlight the complete row of the active item. The problem is, that i dont what items are in which row, because flexbox ist handling that.
For example:
xxx|xxxxxxxx|xx|xxxxxxxxx|
x|xxxxxx|xxxxxxxxxxxxxxx|xxx|
xxxxx|xxxxxxxxxx|XXXX|xxxx
xxxx|xxxxx|xxxxxxxxx
Just to see also in which row the active item is.
I am using React and Flexbox. But im not sure if thats possible with flexbox.
I could render every single item into a hidden DOM element to get its size and calculate the row-number by myself, but this is very hacky....
Do you know a trick to do that? Or maybe a different layout system, which is able to do that?
Edit: Examplecode:
<div style={{ display: "flex", flexWrap: "wrap", maxWidth: "960px" }}>
{this.state.myItems.map((w, i) => (
<div className={`${i !== this.state.activeIndex ? "playerword" : "playerword-active"}`} style={{ marginTop: "15px", fontSize: "1.3em", cursor: "pointer" }}>
<div className="olBack" style={{ padding: "3px" }}>
{w[0]}
</div>
</div>
))}
</div>
-Alexander

Related

Create a circle next to a TextField using React

i am working with a Box element which contains Textfield elements. I was wondering If i can create a circle for each TextField. I have tried using css like below.
circle: {
display: 'flex',
width: '100px',
height: '100px',
color: 'green',
borderRadius:'50%',
},
<TextField
className={classes.circle}
id='consumptionInkWhPerkmAltitudeGain -number'
label='Altitude Gain(TomTom)'
type='number'
value={customConsumptionDetails.consumptionInkWhPerkmAltitudeGain }
color = "secondary"
onChange={handleConsumptionDetailsParameterChange('consumptionInkWhPerkmAltitudeGain')}
InputLabelProps={{
shrink: true,
}}
/>
but without luck.
For a better understanding of what I want to do I will leave a picture bellow.
How can I create something similar with what is in the picture?
You can try to add the styling with className, you can easily modify the code below, hope it helps!
import "./styles.css";
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<textarea />
<span className="circle"></span>
</div>
);
}
In the styles.css:
.circle {
display: flex;
width: 30px;
height: 30px;
background-color: green;
border-radius: 50%;
}
Live demo here: https://codesandbox.io/s/ecstatic-bardeen-dd4h1w?file=/src/App.js

How to make the content of a div go from left to right, then drop e continue going left to right

I have a code where I want to make the content inside the div, go from left to right (which I did using Flex-direction: row) and when it gets to the limit of the div, goes down and continues this order. The order should look like this (https://i.stack.imgur.com/L97y0.png) with the elements inside going in this order.
I'm using MVC core, and its a system which accepts requests and shows them on the screen.
Here's the HTML of the div
<div class="pedido-tudo">
#foreach(var pedido in Model)
{
<div class="pedido-quadrado">
#pedido.IdPedido
#pedido.NomeCliente
#pedido.TelCliente
#pedido.DataEntrada
#pedido.HoraEntrada
#pedido.HoraSaida
#pedido.TextoStatus
#pedido.TextoTipoPedido
#if (#pedido.TextoStatus == "Andamento" && #pedido.HoraSaida == "")
{
<div class="botoes-cad">
Finalizar
</div>
}
</div>
}
</div>
the CSS of the div
.pedido-tudo {
margin-left: 1.5rem;
width: 60rem;
max-width: 60rem;
display: flex;
flex-direction: row;
}
.pedido-quadrado{
margin-top: 1rem;
margin-left: 5.7rem;
width: 18rem;
height: 20rem;
border: 1px rgb(170, 0, 0) solid;
color: black;
font-size: 16px;
}
Here's how it currently is:
If what i think you are saying is correct you should use the flex-wrap property so that when the size of the parent div becomes smaller is pushes the overflowing items from the top to the bottom reply to me if i am wrong

adding onclick to an array of items

I have this problem where if I click on an item, all the items in that column gets affected by the click. I want only that very item where I clicked to have the class. but in my code, all the other items of that column are getting the class when I click on a certain single item. I want to make a div go fullscreen when I click on that particular div. kinda like modal pop up, here I want that the div slowly animates to fullscreen
export default class App extends React.Component {
constructor(props) {
super(props);
this.addActiveClass = this.addActiveClass.bind(this);
this.state = {
activeIndex: -1
};
}
addActiveClass(activeIndex) {
this.setState(prev => ({
activeIndex: prev.activeIndex === activeIndex ? -1 : activeIndex
}));
}
render() {
return (
<div className="container">
{Array.from({ length: 30 }).map((item, index) => {
return (
<div
key={index}
style={{
background: randomColor(colors),
height: randomHeight(100, 200)
}}
className={this.state.activeIndex === index ? "full" : ""}
onClick={() => this.addActiveClass(index)}
/>
);
})}
</div>
);
}
}
* {
box-sizing: border-box;
}
body {
margin: 40px;
background-color: #fff;
color: #444;
font: 2em Sansita, sans-serif;
}
.container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
max-height: 100vh;
}
.container > * {
border: 2px solid orange;
border-radius: 5px;
margin: 10px;
padding: 10px 20px;
background-color: red;
color: #fff;
}
.full{
width: 100%;
height: 100%;
transition: 2s;
}
sandbox demonstrating the problem
I don't know exactly what kind of effect you would like to achieve with the selected item but items in the column are affected because of the default value of flexbox align-items which is stretch. The other items are stretching to match the selected element. Try to add align-items: flex-start to your .container class.
You'll have to make sure you're adding the class to the event target. Your onClick function needs to take the event as one of it's arguments, and you need to use event.target in the function body to make sure you're only affecting the element that is clicked. Hope that makes sense!
https://developer.mozilla.org/en-US/docs/Web/API/Event/target
The class adding logic works ok. You can observe this by checking the elements on developer tools. The problem is you are adding an inline style to your elements.
style={{
background: randomColor(colors),
height: randomHeight(100, 200)
}}
So, after each new render, this overrides the full class and give new height and new color.
The other problem is your full class. You are using 100% for height and width and probably this causes problems for your flex.
Just remove the inline style part and instead of using a percentage give custom width and height to full class, then you can see adding the class logic works well.
Pass down an event (e) from your onClick, then access that specific item through e.target.className. This way only the clicked item is updated, even if dynamically rendered from an array:
handleClick = e => { e.target.classNamme = 'class' }
<div className='' onClick={e => handleClick(e)}></div>
Alternatively, if you're keeping your classes in the state, you can just replace the string value with your variable and control in inside the function, as you've done in the example you've provided.
Adding !important overrides the inline-style height.
Height is set to 100vh to expand the div into full screen.
.full{
width: 100%;
height: 100vh !important;
transition: 2s;
}

How to make a div pop up on overflow?

I want to display a div(with className='invoice-info') on hover of the icon(which is in table cell) like this:
<div
style={{ position: "relative" }}
onMouseEnter={() => setHoveredInvoiceId(result.gsCustomersID)}
onMouseLeave={() => setHoveredInvoiceId()} >
<i className="icon-container invoice-icon" id={"csInvoiceIcon" +
result.gsCustomersID}></i>
<div className="invoice-info">Hello</div> //this is displayed conditionally
</div>
I wrote some styles for the div like this:
.invoice-info {
position: absolute;
background-color: red;
width: 10vw;
height: 10vh;
z-index: 10;
left: 1em;
bottom: -6em;
}
But due to the width of table-cell is small enough to fit only icon, the div is hidden. I gave z-index to make it float but it is not working. I want a floating div on hover. Could someone help me?
Invoice cell has overflow:hidden property. It worked after changing it to overflow:visible
You can use CSS instead of JS that will have some performance gain.
you can use something like this:
.invoice-info{
display: none;
// your other styling
}
.icon-class:hover ~ .invoice-info{
display: block;
}
~ is general sibling selector in CSS

JavaScript Wrap Around Carousel

I am looking for some information from some front end experts on how to go about creating a custom wrap around js carousel gallery. The idea is simple really I have a carousel of images, text, or whatever and when I get to the end I want it to wrap around. I don't want the content to simply fadeIn and out to the next piece of content. This is a gallery of div's currently but suppose it's images or whatever have you.
HTML
<div id="outside-container">
<div id="inside-container" class="cf">
<div class="items" id="item1"></div>
<div class="items" id="item2"></div>
<div class="items" id="item3"></div>
<div class="items" id="item4"></div>
</div>
</div>
<div id="directions">
<h4 id="left-button">Left</h4>
<h4 id="right-button">Right</h4>
</div>
CSS
#outside-container{
display: block;
width: 400px;
height: 125px;
overflow: hidden;
border: 1px solid #000;
margin: 0px auto;
}
#inside-container{
display: block;
width: 800px;
overflow: hidden;
height: 100%;
}
.items{
float: left;
margin: 0px;
width: 200px;
height: 100%;
}
#item1{ background: green; }
#item2{ background: red; }
#item3{ background: blue; }
#item4{ background: yellow; }
#directions{
display: block;
width: 400px;
margin: 0px auto;
text-align: center;
}
#left-button, #right-button{
display: inline-block;
cursor: pointer;
margin: 10px;
}
JS
var move = 0;
$("#left-button").click(function(){
move += 200;
$("#inside-container").animate({
marginLeft: move+"px"
}, 500);
});
$("#right-button").click(function(){
move -= 200;
$("#inside-container").animate({
marginLeft: move+"px"
}, 500);
});
Here is the codepen. So to sum all this up. I am asking for a way to create an infite loop for a gallery. I have always programmed these sorts of things to come to an end and then the user has to go back the other way. If this sounds confusing follow check out the codepen. Thanks in advance.
Here you go
http://codepen.io/nickavi/pen/cpFCE
But for the love of god, please don't use jQuery animate... at least add velocity.js to it, or the GSAP plugin, you don't even have to alter your JS you just add it in and it replaces the animate function with a more efficient one.
Cheers JBSTEW
First set move to the default slider and margin reset amount:
var move = 200;
Then, set the container margin to slide left by the move amount:
var margin_reset = (move * -1) + 'px'
$("#inside-container").css('margin-left', margin_reset);
Then, adjust the animation margin slide using move variable again, and execute a function when the animation is complete that moves the last/first item to the beginning/end of the container using prepend/append.
$("#left-button").click(function(){
$("#inside-container").animate({
marginLeft: 0
}, 500, function() {
$(this).prepend( $(this).find('.items:last') )
.css('margin-left', margin_reset);
});
});
$("#right-button").click(function(){
$("#inside-container").animate({
marginLeft: (move * -2) +"px"
}, 500, function() {
$(this).append( $(this).find('.items:first') )
.css('margin-left', margin_reset);
});
});
To avoid an initial draw jump, you could change the default css #inside-container as:
#inside-container{
...
margin-left: -200px;
}
see: Codepen

Categories

Resources