How to handle z-index on React components on a table - css

I'm having some issues while displaying a modal on a table. For each expense data I render a expenseItem component inside of a tbody. When clicking on this components, it opens a lateral modal and a backdrop on the remaining screen.
Backdrop has a action that whenever is clicked, it closes modal. But, when I click inside of modal, it calls close modal action of backdrop on top of it.
I've tried to set z-index of backdrop to 100 and moda to 200. It didn't work.
return (
<tr className="expense-box" onClick={() => handleOpenModal()}>
<td className="expense-info">{description}</td>
<td>-</td>
<td>-</td>
<td className="expense-info">{date}</td>
<td className="expense-info">{debit || credit}</td>
<td>
<BackDrop isShowing={isModalOpen} closeModal={handleOpenModal} />
<EditExpenseModal isShowing={isModalOpen} closeModal={handleOpenModal} expense={props.expense} />
</td>
</tr>
Backdrop component:
function BackDrop({ isShowing, closeModal }) {
return (
<div onClick={closeModal}>
{isShowing ? <div className="backDrop" /> : null}
<style jsx>
{`
.backDrop {
position: fixed;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
z-index: 100;
top: 0;
left: 0;
}
`}
</style>
</div>
);
}
export default BackDrop;
Modal component:
import { useState, Fragment } from 'react';
import { editExpenses } from '../redux/actions/expenseActions';
import DropdownMenu from '../components/dropdownMenu';
import { connect } from 'react-redux';
import { createPortal } from 'react-dom';
const EditExpenseModal = ({ expense, isShowing, closeModal, editExpenses, savedCategories }) => {
const { id, description, date, credit, debit } = expense;
const [ expenseItem, setExpenseItem ] = useState({
date,
description,
category: '',
subcategory: '',
credit,
debit
});
function handleInputChange(e, targetName) {
const { name, value } = e.target;
(value && !targetName) || (!value && !targetName)
? setExpenseItem({ ...expenseItem, [name]: value })
: setExpenseItem({ ...expenseItem, [targetName]: e.currentTarget.innerText });
}
function onEditExpense(id, expense) {
editExpenses(id, expense);
closeModal();
}
return isShowing
? createPortal(
<Fragment>
<div>
<div className="form">
<form>
<ul>
<li className="form-inputs">
<label>Date</label>
<input
className="field-input"
type="text"
name="date"
defaultValue={date}
onChange={handleInputChange}
/>
</li>
<li className="form-inputs">
<label>Description</label>
<input
className="field-input"
type="text"
name="description"
defaultValue={description}
onChange={handleInputChange}
/>
</li>
<li className="form-inputs">
<label>Category</label>
<DropdownMenu
savedCategories={savedCategories}
handleInputChange={handleInputChange}
type={'category'}
category={expenseItem.category}
/>
</li>
<li className="form-inputs">
<label>Subcategory</label>
<DropdownMenu
savedCategories={savedCategories}
handleInputChange={handleInputChange}
type={'subcategory'}
parentCategory={expenseItem.category}
category={expenseItem.subcategory}
/>
</li>
<li className="form-inputs">
<label>Credit</label>
<input
className="field-input"
type="text"
name="credit"
defaultValue={credit}
onChange={handleInputChange}
/>
</li>
<li className="form-inputs">
<label>Debit</label>
<input
className="field-input"
type="text"
name="debit"
defaultValue={debit}
onChange={handleInputChange}
/>
</li>
</ul>
</form>
<button onClick={() => onEditExpense(id, expenseItem)}>save</button>
<button onClick={() => closeModal()}>close</button>
</div>
<style jsx>{`
.form {
position: fixed;
background: white;
box-shadow: 0px 20px 5px rgba(0, 0, 0, 0.7);
display: flex;
flex-direction: column;
height: 100%;
top: 0;
right: 0;
width: 40%;
z-index: 200;
overflow: scroll;
}
.form-inputs {
display: flex;
flex-direction: column;
list-style-type: none;
padding: 1rem 2rem;
}
.form-inputs label {
margin-left: 8px;
}
.field-input {
margin: 5px;
width: 330px;
height: 40px;
font-size: 15px;
outline: none;
}
`}</style>
</div>
</Fragment>,
document.body
)
: null;
};
const mapDispatchToProps = (dispatch) => ({
editExpenses: (id, expense) => dispatch(editExpenses(id, expense))
});
const mapStateToProps = (state) => state;
export default connect(mapStateToProps, mapDispatchToProps)(EditExpenseModal);
This problem started to happen when I've turned all structure to a table. Before I was using only <div> and it was working.

Related

Reactjs sidebar doesn't collapse and dropdown doesn't open

I am trying to achieve two things:
(1) each time I click on the red arrow icon in the sidebar, I want the sidebar to collapse or open. From the below video, you'd see that the active and inactive states are already there. However, the sidebar doesn't collapse on inactive.
(2) each time I click on the Content menu, which is a drowndown menu, it doesn't open the submenu. Also, from the below video, you'd notice that the active and inactive states are already there. However, the dropdown still doesn't open on active.
Below is the video that clearly shows the error:
https://www.loom.com/share/6e0488101cee4c5b9bac7ded782b8807
Docs.js Page
import React from "react";
import { Helmet } from "react-helmet";
import SideMenu from "../docs/SideMenu";
const Docs = () => {
return (
<div className="">
<Helmet>
<title>Docs :: MyApp</title>
<meta name="description" content="MyApp" />
</Helmet>
<SideMenu />
</div >
)
};
export default Docs
SideMenu.js Component
import React, { useState } from "react";
import { Helmet } from "react-helmet";
import * as Icon from "react-bootstrap-icons";
import MenuItems from "./MenuItems";
const SideMenu = () => {
const [inActive, setInActive] = useState(false)
return (
<div className="">
<div className={`side-menu ${inActive ? "inActive" : ""}`}>
<Helmet>
<title>Docs :: MyApp</title>
<meta name="description" content="MyApp" />
</Helmet>
<div className="top-section">
<div className="logo">
<img src="/assets/media/logos/naked.png" alt="MyApp" />
</div>
<div onClick={() => setInActive(!inActive)} className="toggle-back">
{inActive ? (<Icon.ArrowLeftSquareFill />) : (<Icon.ArrowRightSquareFill />)}
</div>
</div>
<div className="search-bar">
<button className="search-bar-btn">
<Icon.Search />
</button>
<input type="text" placeholder="search" />
</div>
<div className="divider"></div>
<div className="main-menu">
<ul>
{menuItems.map((menuItem, index) => (
<MenuItems
key={index}
name={menuItem.name}
to={menuItem.to}
subMenu={menuItem.subMenu || []} />
))}
{/*<li>
<a className="menu-item">
<Icon.ArrowRightSquareFill className="menu-icon" />
<span>Dashboard</span>
</a>
</li>
<MenuItems
name={"Content"}
subMenu={[
{ name: 'Courses' },
{ name: 'Videos' },
]}
/>
<li>
<a className="menu-item">
<Icon.ArrowRightSquareFill className="menu-icon" />
<span>Support</span>
</a>
</li>*/}
</ul>
</div>
<div className="side-menu-footer">
<div className="avatar">
<img src="/assets/media/avatars/aa/brooks_lloyd.png" alt="MyApp" />
</div>
<div className="user-info">
<div className="font-size-h6">Title</div>
<div className="font-size-sm">Subtitle</div>
</div>
</div>
</div>
</div>
);
};
export default SideMenu
const menuItems = [
{ name: "Dashboard", to: "/" },
{ name: "Content", to: "/", subMenu: [{ name: "Courses" }, { name: "Videos" }], },
{ name: "Design", to: "/" },
];
MenuItems.js Component
import React, { useState } from "react";
import * as Icon from "react-bootstrap-icons";
const MenuItems = (props) => {
const { name, subMenu } = props;
const [expand, setExpand] = useState(false);
return (
<div className="">
<li>
<a onClick={() => setExpand(!expand)} className="menu-item">
<Icon.ArrowRightSquareFill className="menu-icon" />
<span>{name}</span>
</a>
{
subMenu && subMenu.length > 0 ? (
<ul className={`sub-menu ${expand ? "active" : ""}`}>
{subMenu.map((menu, index) =>
<li key={index}>
<a className="sub-menu">
<Icon.ArrowRightSquareFill className="menu-icon" />
{menu.name}
</a>
</li>
)}
</ul>) : null}
</li>
</div>
);
};
export default MenuItems
Docs.css File that contains the suspected errors, which are the side-menu and sub-menu lines:
.side-menu {
position: fixed;
background: #000;
width: 300px;
height: 100%;
box-sizing: border-box;
padding: 30px 20px;
transition: width .2s ease-in;
}
.side-menu.inactive {
width: 80px;
}
.side-menu .main-menu .sub-menu {
color: #333;
margin-left: 20px;
border-left: 1px solid #666;
box-sizing: border-box;
padding-left: 30px;
max-height: 0;
overflow: hidden;
transition: max-height .2s ease-in;
}
.side-menu .main-menu .sub-menu.active {
max-height: 200px;
}

organize Css menu-bars

i had create a menu-bars hamburger inside the app.js file to show it when I click on the 3bars alls is good but I had a problem related to CSS so when I click on icons-bar the menubar display very well but the other menu navbar on the right of it disappear.to be honest with you I'm not hero in CSS.this is my code :
app.js file:
import {useState} from "react";
import {BrowserRouter, Routes, Route, Link} from "react-router-dom";
import {useSelector} from "react-redux";
import HomePage from "./Pages/HomePage";
import ProductPage from "./Pages/ProductPage";
import CartPage from "./Pages/CartPage"
function App() {
const cart = useSelector(state=> state.cart);
const productsList = useSelector(state=> state.productsList);
const { products } = productsList;
const categories = products?.length
? products.map(({category})=> category)
: [];
const [open, setOpen] = useState(false);
const allCategories = categories.filter((element, index, categories)=> element !== categories[index + 1]);
console.log(allCategories)
const { cartProducts } = cart;
const menuBar = () => {
return (
<div className={open ?"bars": "bars-close"} >
{allCategories.map((category, index)=> <div key={index} className="bar" >{category}</div>
)}
</div>
)
}
console.log(open)
return (
<BrowserRouter>
<div className="grid-container" >
<header className="row">
<div>
<Link className="brand" to="/">My shop</Link>
<span className ="menu-bar">
<i onClick={()=> setOpen(!open)} className="fa fa-bars"></i>
</span>
{menuBar()}
</div>
<div>
<Link to="/cart/:id">Cart
{cartProducts.length > 0 && (
<span className="badge" >{cartProducts.length}</span>
)}
</Link>
<Link to="/signin">Sign In</Link>
</div>
</header>
<main>
<Routes>
<Route path="/cart/:id" element={<CartPage />} ></Route>
<Route path="/product/:id" element={<ProductPage />} exact ></Route>
<Route path="/" element={<HomePage />} ></Route>
</Routes>
</main>
<footer className="row center" >All right reserved</footer>
</div>
</BrowserRouter>
);
}
export default App;
index.css file just the part of menu-bars:
.bars {
display: block;
width: 20rem;
background-color: #101010;
height: 80px;
transition-delay: 400ms;
z-index: 2;
position: relative;
left: 5rem;
}
.bars-close {
display: none;
transition-delay: 500ms;
}
.bars .bar {
font-size: 2rem;
color: #fff;
text-decoration: underline;
margin: 0.2rem 0;
text-align: center;
}
.menu-bar {
color: #ffffff;
}
.menu-bar i {
margin-left: 2rem;
font-size: 3rem;
cursor: pointer;
}

Is it bad to use Refs to change styles in react?

here is a code example where i use Ref's to change style
import React, {useRef, useState, useEffect} from 'react'
import S from "./collapsible.module.css"
import PropTypes from 'prop-types'
import { faMinus, faPlus } from '#fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
function Collapsible(props) {
let myRef = useRef(null);
let buttonRef = useRef(null);
let [ button, setButton] = useState(true)
let Show = () => {
if(button) {
setButton(false)
buttonRef.current.style.backgroundColor = "#555"
myRef.current.style.maxHeight = myRef.current.scrollHeight + "px";
} else {
setButton(true)
buttonRef.current.style.backgroundColor = "hsl(181, 100%, 11%)"
myRef.current.style.maxHeight = "0px";
}
}
return (
<div
className={S.body}
>
<button
className={S.collapsible}
onClick={Show}
ref={buttonRef}
> {props.label}
<div className={S.icon}>
{button? <FontAwesomeIcon icon={faPlus} />:
<FontAwesomeIcon icon={faMinus} />}
</div>
</button>
<div
className={S.content}
ref={myRef}
>
<h3>{props.body}</h3>
</div>
</div>
)
}
Collapsible.propTypes = {
label: PropTypes.string,
body: PropTypes.string,
}
Collapsible.defaultProps = {
label: '',
body: "",
}
export default Collapsible
css:
.collapsible {
display: flex;
background-color: hsl(181, 100%, 11%);
color: white;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
outline: none;
font-size: 15px;
border-radius: 3px;
/* margin-bottom: 3px; */
box-shadow: 0px 1px 5px 1px black;
margin-top:13px;
}
.icon{
color:white;
position:absolute;
right:50px;
text-align:right;
justify-content: flex-end;
}
.active, .collapsible:hover {
background-color: #555;
}
.content {
padding: 0 18px;
max-height: 0px;
overflow: hidden;
transition: max-height 0.2s ease-out;
background-color: #f1f1f1;
}
This is just replicating this in React:
https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_collapsible_animate
I have read that using Refs is bad, especially when using it to change the DOM, but if I didn't change the style with the exact amount shown in "scrollHeight" then the transition would be a messed up speed.
If there is another method Is this still bad practice?
It's more common practice to use a state value to determine the style like this:
<button
className={S.collapsible}
onClick={Show}
style={{backgroundColor: button ? "#555" : "hsl(181, 100%, 11%)"}
>
{props.label}
<div className={S.icon}>
{button ? (
<FontAwesomeIcon icon={faPlus} />
) : (
<FontAwesomeIcon icon={faMinus} />
)}
</div>
</button>
Or have a conditional className for your styles:
<button
className={`${S.collapsible} ${
button ? S.buttonColor : S.anotherButtonColor
}`}
onClick={Show}
>
{props.label}
<div className={S.icon}>
{button ? (
<FontAwesomeIcon icon={faPlus} />
) : (
<FontAwesomeIcon icon={faMinus} />
)}
</div>
</button>
and add .buttonColor and .anotherButtonColor to your CSS Module file (collapsible.module.css).
.buttonColor {
background-color: #555;
}
.anotherButtonColor {
background-color: hsl(181, 100%, 11%);
}
For the maxHeight on myRef, I'd do something like:
<div className={S.content} ref={myRef}>
<div style={{ maxHeight: myRef.current.scrollHeight }}>
<h3>{props.body}</h3>
</div>
</div>

Cannot centralize div on bootstrap

I'm trying to centralize the div "Status" using css. Already tryied to use vertical-align: middle, display: flex, align-item: center and nothing works. Can someone help me? it seens like the height of the div remains the same so I can't centralize it since it's content fills it's exactly entire space.
import React from 'react'
import { Row, Col } from 'reactstrap'
import styled from 'styled-components'
import Status from './Status'
export default ({ temporadas = [], temporadaSelecionada = {}, onChange = () => {} }) => {
return (
<StyledContainer>
<Row>
<Col md={12}>
{temporadas.map(temporada => {
return (
<StyledCard selected={temporadaSelecionada.codigo === temporada.codigo}
onClick={() => onChange(temporada)}>
<Status className='pull-right' style={{ marginRight: '-8px' }} ativa={temporada.status === 'A'} />
{/* <StyledIcon className={temporadaSelecionada.codigo === temporada.codigo ? 'fa fa-fw fa-minus' : 'fa fa-fw fa-plus'} /> */}
<StyledText alt={temporada.descricao} title={temporada.descricao}>{temporada.descricao || '-'}</StyledText>
</StyledCard>
)
})}
</Col>
</Row>
</StyledContainer>
)
}
const StyledContainer = styled.div`
margin-bottom: 10px;
`
const StyledCard = styled.div`
cursor: pointer;
padding: 16px;
display: block;
border: 1px solid #DADFEA;
background-color: #F4F7FA;
font-size: 100%
&:not(:first-child) {
margin-top: -1px;
}
&:last-child {
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
}
${({ selected }) => selected && `
border-left: 5px solid #C5CBD9;
padding-left: 12px;
`}
`
const StyledText = styled.span`
margin: 0;
`
const StyledIcon = styled.i`
font-size: 10px;
`
The div "Status" is imported from another file and it behaves like this:
import React from 'react'
import styled from 'styled-components'
export default ({ ativa, label, ...props }) => {
if (ativa) {
return (
<div {...props}>
<StyledText>
<StyledLabel>{label}</StyledLabel>
<i class='fa fa-fw fa-circle text-success' />
<span>Ativa</span>
</StyledText>
</div>
)
} else {
return (
<div {...props}>
<StyledText>
<StyledLabel>{label}</StyledLabel>
<i class='fa fa-fw fa-circle text-danger' />
<span>Inativa</span>
</StyledText>
</div>
)
}
}
const StyledText = styled.small`
text-transform: none;
`
const StyledLabel = styled.span`
color: #79919D;
`
I want to put that div in the vertical-center of the row it is contained in. Can someone help me?
You can try this way.
<div className=" centeredDiv">
<status></status>
<div>
.centeredDiv{
display:flex;
justify-content:center;
align-items:center;
}

Why is the value of the select field getting added to the remaining fields in the form

When I have selected a value from the select tag it the selected value is getting added to the remaining fields. This was the error :- [This was what happened
import React, { Component } from 'react';
import './C.css';
import {ButtonToolbar,Button} from 'react-bootstrap';
import axios from 'axios';
export default class Coldata extends React.Component {
constructor(props) {
super(props);
this.state = {value: 'select dept'};
this.handleChange = this.handleChange.bind(this);
this.state={
Regdno:'',
Yos:'',
dept:'',
complaint:''
};
}
onChange = (e) => {
console.log(e.target.Regdno)
// Because we named the inputs to match their corresponding values in state, it's
// super easy to update the state
const state = this.state
// console.log(e.target.value)
state[e.target.Regdno] = e.target.value;
this.setState(state);
}
onSubmit = (e) => {
// console.log("entered")
e.preventDefault();
// console.log(this.state)
// get our form data out of state
const data = this.state;
axios.post('http://localhost:80/create/complaint', data)
.then((result) => {
//access the results here....
alert("Complaint created")
// console.log(result)
})
// console.log(this.state)
}
handleChange(event) {
this.setState({value: event.target.value});
}
render() {
const{Regdno,Yos,dept,complaint}=this.state;
return (
<form onSubmit={this.onSubmit} className="col" >
<div align="right"><Button bsSize="large" href="/login" value="Logout"> Logout </Button></div>
<font size="5" >
<div className="log">
<h1> College </h1>
<p> Regd_no </p>
<input type="text" name="Regdno" id="regdno" size="10" placeholder="Enter Regd_no" value={this.state.value} onChange={this.onChange} required />
<p> Year of study </p>
<input type="text" name="Yos " size="5" placeholder="Enter year of study" value={this.state.value} onChange={this.onChange} />
<label> Select Dept </label>
<select value={this.state.value} onChange={this.handleChange} className="op" name="dept" id="dept" required>
<option value="Cse">Cse</option>
<option value="Ece">Ece</option>
<option value="It">IT</option>
<option value="EEE">EEE</option>
<option value="Mech">Mech</option>
<option value="Chem">Chem</option>
</select>
<br />
<label> Disciplinary Issue </label>
<input type="text" size="20" name="complaint" value={this.state.value} onChange={this.onChange} required/>
<ButtonToolbar>
<Button bsStyle="primary" bsSize="lg" type="submit" value="submit" block> ADD </Button>
</ButtonToolbar>
</div>
</font>
</form>
);
}
}
.col{
margin: 0;
padding: 0;
background: url(./Nature.jpeg);
background-size: contain;
background-position: center;
font-family: sans-serief;
height: 768px
}
.log{
width: 320px;
height:570px;
background: rgba(0,0,0,0.5);
color: #fff;
top: 50%;
left: 50%;
position: absolute;
transform: translate(-50%,-50%);
box-sizing: border-box;
padding: 70px 30px;
}
h1{
margin:0;
padding: 0 0 10px;
position: relative;
text-align:center;
font-size:22px;
}
.log p{
margin: 0;
padding: 0;
font-weight:bold;
}
.log input{
width:100%;
margin-bottom:10px;
}
.log input[type="text"],input[type="password"] :focus
{
border:none;
border-bottom: 1px solid #fff;
background:transparent;
outline:none;
height:60 px;
color: #fff;
font-size: 22px;
box-sizing: border-box;
}
.log input[type="submit"]
{
border:none;
outline:none;
background: #1c8adb;
color: #fff;
font-size: 20px;
margin-top: 10px;
}
.op {
margin-top: 10px;
width:auto;
color: red;
height: 40px;
}
A component is changing an uncontrolled input of type text to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component.
Remove value={this.state.value} and onChange={this.onChange} from the input type="text" elements.

Resources