Multiple variable className in next js - css

How to apply multiple className in Next js, in which there are variable classsnames as well ?
I'm using component level css approach
Here's my code and what I want to do:
import styles from "./ColorGroup.module.css";
const colors = ["red", "sky", "yellow", "green", "golden"];
const ColorGroup = () => {
return (
<div className={styles.colorContainer}>
<text>Colour</text>
<div className={styles.colorBoxContainer}>
{colors.map((color, index) => (
<div
// variable color class is not get applied, only colorBox is applied, I want both
className={`${styles}.${color} ${styles.colorBox}`}
key={index}
></div>
))}
</div>
</div>
);
};
Goal:
CSS code:
/* code for layout and arrangement above */
.colorBox {
height: 36px;
width: 36px;
}
.red {
background-color: lightcoral;
}
.sky {
background-color: skyblue;
}
.yellow {
background-color: lightyellow;
}
.green {
background-color: lightgreen;
}
.golden {
background-color: greenyellow;
}
But this method is only applying the colorBox className and not doing anything for ${styles}.${color} . How to apply both ?

You should use bracket
<div className={styles.colorBoxContainer}>
{colors.map((color, index) => (
<div
className={`${styles[color]} ${styles.colorBox}`}
key={index}
></div>
))}
</div>

You can try to use the style object, it easier to use it with variables :
<div key={index} className={`${styles.colorBox}`} style={{ backgroundColor: color }} >
</div>

Related

How to make the color of a div change permanently after it has been clicked in react.js

This is the grid that I have
Once a square has been clicked, the color changes to red. - This is done using active class
I would like the change to the background color of the div tag to remain permanent after the square has been clicked.
Code
Board.js
{board.map((row, rowIdx) => (
<div key={rowIdx} className="row">
{row.map((cell, cellIdx) => (
<div key={cellIdx} className="cell"></div>
))}
</div>
))}
Board.css
.row {
height: 30px;
margin: 10px;
transition: transform 0.1s;
}
.cell:hover {
transform: scale(1.4);
}
.cell {
width: 30px;
height: 30px;
outline: 1px solid rgb(134, 154, 189);
display: inline-block;
background-color: seagreen;
margin: 5px;
transition: transform 0.2s;
}
.row :active {
background-color: red;
}
.cell :active { // Does not do anything
background-color: blue;
}
Once another square is clicked, the previosly clicked one does not remain active, you can do this by adding another class with your desired style, and using state to track the squares that have been clicked.
const [boardIndeces, setBoardIndeces] = useState(initArray(board));
const initArray = arr => {
let rows = [];
for (let i = 0; i < arr.length; i++) {
let row = [];
const currBoard = arr[i];
for (let z = 0; z < currBoard.length; z++) {
row[z] = false;
}
rows[i] = row;
}
return rows;
};
const onCellClick = (rowIdx, cellIdx) => {
if (!(boardIndeces[rowIdx] && boardIndeces[rowIdx][cellIdx])) {
boardIndeces[rowIdx][cellIdx] = true;
setBoardIndeces([...boardIndeces]);
}
};
{
board.map((row, rowIdx) => (
<div key={rowIdx}>
{row.map((cell, cellIdx) => (
<div
key={cellIdx}
className={
boardIndeces[rowIdx].includes(cellIdx)
? 'your_active_class'
: 'your_inactive_class'
}
onClick={() => onCellClick(rowIdx, cellIdx)}
></div>
))}
</div>
));
}
You can use a checkbox if you don't want to use React
HTML
<input type="checkbox" id="color" name="color">
<label id="color-div" for="color">
<!-- the div you want to change color -->
</label>
CSS
#color {
display: none
}
#color:checked + #color-div { /* + in CSS is the sibling combinator */
background-color: #fffff /* your background color */
}
What you're basically doing is making an invisible checkbox and toggling it with the label, when it's toggled you do the changes to the CSS
Remember the CSS combinators only work in elements after the HTML element it's being applied to

How can i make slider animation?

I need to make the vertical slider animation ( dots and line ) as in this pic
i managed to do the Accordion and the dots but i don't know how i will going to implement it ( i'm using pseudo )
**my accordion component Where i define the logic of my nested accordions as in images based on array of data **
function MultiLevelAccordion({
data,
bodyClass,
headerClass,
wrapperClass,
renderHeader,
renderContent,
}) {
const RootAccordionId = 'parent-0';
const [accordionsStates, setActiveCardsIndex] = useMergeState({});
const onAccordionToggled = (id, activeEventKey) => {
console.log(activeEventKey);
setActiveCardsIndex({
[id]: activeEventKey ? Number(activeEventKey) : activeEventKey
});
};
console.log('data', data);
const accordionGenerator = (data, parentId) => {
return map(data, (item, index) => {
const active = accordionsStates[parentId] === index;
const hasChildren = item.hasOwnProperty('children') && isArray(item.children) && !isEmpty(item.children);
const isRootAccordion = RootAccordionId === parentId;
const isLastNestedAccordion = !isRootAccordion && !hasChildren;
const accordion = (
<Card className={classNames(wrapperClass, {
'nested-root-accordion': !isRootAccordion,
'last-nested-root-accordion': isLastNestedAccordion,
'multi-level-accordion': !isLastNestedAccordion
})}
>
<Accordion.Toggle
{...{ ...item.id && { id: item.id } }}
onClick={() => this}
as={Card.Header}
eventKey={`${index}`}
className={'cursor-pointer d-flex flex-column justify-content-center'}
>
<div className="d-flex justify-content-between align-items-center">
{renderHeader(item, hasChildren)}
<img
style={{
transition: 'all .5s ease-in-out',
transform: `rotate(${active ? 180 : 0}deg)`
}}
src={setIcon('arrow-down')}
className="ml-2"
alt="collapse"
/>
</div>
</Accordion.Toggle>
<Accordion.Collapse eventKey={`${index}`}>
<Card.Body
className={`accordion-content-wrapper ${!hasChildren ? 'accordion-children-body' : ''} ${bodyClass}`}
>
{!hasChildren ? renderContent(item, hasChildren) : (
<Accordion onSelect={activeEventKey => onAccordionToggled(`${parentId}-${index}`, activeEventKey)}>
<Fade cascade top when={active}>
{accordionGenerator(item.children, `${parentId}-${index}`)}
</Fade>
</Accordion>
)}
</Card.Body>
</Accordion.Collapse>
</Card>
);
return isRootAccordion ? accordion : (
<div className={'d-flex align-items-center'}>
{accordion}
<div className="accordion-indicator-wrapper">
<div className="accordion-indicator" id={`indicator-${parentId}-${index}`} />
</div>
</div>
);
});
};
if (!isArray(data)) {
return;
}
return (
<Accordion onSelect={activeEventKey => onAccordionToggled(RootAccordionId, activeEventKey)}>
{accordionGenerator(data, RootAccordionId)}
</Accordion>
);
}
export default MultiLevelAccordion;
the styles used in scss
.faqs-questions-wrapper {
padding: 20px 10px
}
.faqs-q-count {
color: $black-color;
font-size: calc(1rem - 1rem/8)
}
.faqs-q-a-wrapper {
flex-basis: 95%;
}
.faq-child-title {
color: $black-color
}
.nested-root-accordion {
flex-basis: 90%;
}
.accordion-indicator-wrapper {
flex-basis: 10%;
width: 100%;
display: flex;
justify-content: center;
.accordion-indicator {
width: 10px;
height: 10px;
border-radius: 50%;
background-color: $theme-color;
position: relative;
}
}
Any clue?
Thanks in Advance.
React JS is gonna make this easy
The lines expansion will need to be coded based on the height of the box window
For the dropdown container keep the vertical button lines in a separate div than the Accordian
Check out this pen for creating lines between buttons
https://codepen.io/cataldie/pen/ExVGjya
css part:
.status-container{
padding:10px;
margin:10px;
position:relative;
display: inline-block;
}
.bullet{
padding:0px;
margin:0px;
display: inline-block;
z-index: 10;
}
.bullet:before {
content: ' \25CF';
font-size: 5em;
}
.bullet-before{
/*position:relative;
right:-12px;*/
}
.bullet-after{
/*position:relative;
left:-30px;*/
}
.line{
stroke:blue;
stroke-width:0.3em;
padding:0px;
margin:0px;
display: inline-block;
}
.line-on{
stroke:red;
}
.line-off{
stroke:gray;
}
.color-on{
color: red;
}
.color-off{
color: gray;
}
https://codepen.io/emwing/pen/LgzJOx
I think you can use some inspiration here

How i use this style in react... " class[attribute] " [Edited v.2]

I wanna custom my element if he has an attribute...
In pure css i just would use:
<div class='something' data-test='4'></div>
...
.something[data-test] {
background-color: red;
}
but in react i'm failing to convert this code...
<div dataTest={0} className={classes.something} >
Lorem Ipsum
</div>
...
something: {
"&[dataTest]": {
backgroundColor: 'red',
}
}
so, where i'm wrong ?
PS: i tried too:
"& [data-test]": {
"&.[data-test]": {
You need to use className, not class. Then in CSS:
.something[data-test="4"] {
background-color: red;
}
This is how you can access data attributes in react. here is a quick demo
return (
< >
<div className="test" data-id="4">
<h1>Hello dear world</h1>
</div>
</>
);
styles.css
.test {
border: 1px solid red;
}
div::before {
content: attr(data-id);
}

I'm converting existing SCSS code to JSS, I'm stuck at converting the following nested classes

I'm attaching the code for SCSS and react elements below
.chatPane {
height: 100%;
overflow: hidden;
.form-control, .form-control:focus, .form-control:active {
border-bottom: 0;
}
}
render() {
const { isLoaded, messages, handleSendMessage, user } = this.props;
const dialogChildren = (
<div className="modalBox">
<h1 className="modalBox-header">Join chat</h1>
<form onSubmit={this.onCreateUser}>
<input className="modalBox-input" placeholder="Type your name" onChange={this.onNameChange} />
<hr className="modalBox-horizontal"/>
<div className="modalFooter">
<Link className="modalBox-link" to="/chat">close</Link>
<button className="modalBox-button" onClick={this.onCreateUser} type="submit">join</button>
</div>
</form>
</div>
);
I want some help in converting this code into JSS
You need default presets or particularly jss-nested plugin, which replaces & with the parent rule selector.
{
a: {
'& .b, & .c:focus, & .d:focus': {
color: 'red'
}
}
}
Also if you need all selectors global, which is a bad idea, you can use jss-global plugin (also part of default preset)
'#global': {
'.a': {
color: 'green',
'& .b, & .c:focus, & .d:focus': {
color: 'red'
}
}
}

Why is the css style not applying to the modal?

For some reason the css style is not applying to the React Modal. Any reason why?
render() {
return (
<div>
<Modal defaultOpen={this.props.isShowing} className="openmodal">
</Modal>
</div>
);
}
CSS File
.openmodal{
text-align: center;
background-color: black;
border-radius: 0;
width: 400px;
position: relative;
}
If you want to use a javascript style you apply it like this;
const openmodal = {
content: {
textAlign: 'center',
backgroundColor: 'black',
borderRadius: '0',
width: '400px',
position: 'relative'
}
}
render() {
return (
<div>
<Modal defaultOpen={this.props.isShowing} style={openmodal}>
</Modal>
</div>
);
}
Try with the inline style.
It should be portalClassName:
<Modal defaultOpen={this.props.isShowing} portalClassName="openmodal">
</Modal>
It comes with its own DOM structure and its own set of classes.
so you have to target those classes in the screenshot

Resources