react collapisble panel css issue - css

I'm trying to add a Collapsible in my project. The functionality works simply. But there is a CSS issue in collapsible. When I click on a header the collapsible panel opens on after all the header. I want to open the collapsible panel next to each header. I'm using react-collapsible package.
Here is my code,
return (
assignTasklist && assignTasklist.map((assign) =>
<div className="dashboard-tasklists-group_header">
<div id={assign.TaskType} className={ "dashboard-tasklists-group_header-left"} onClick={()=> {
// e.preventDefault();
// e.stopPropagation();
this.onToggleAccordion(assign.TaskType)}}>
{assign.Description}
</div>
<div className="dashboard-tasklists-group_header-right">
<button className="dashboard-tasklists-group_header-caret-button" onClick={()=> {
// e.preventDefault();
// e.stopPropagation();
this.onToggleAccordion(assign.TaskType)}}>
<CaretIcon />
</button>
</div>
</div>
)
);
}
render() {
const { assignDetails } = this.props;
return <div className="dashboard-tasklists-group">
<Collapsible trigger={this.groupWorkingHeader()} /* handleTriggerClick={() => {
}}open={this.state.testflag} */ >
{assignDetails && assignDetails.length>0 && <div className="dashboard-index_announcements-wrapperWP" style={{cursor:'pointer'}}>
<div /* className="dashboard-index_announcements" */ style={{maxHeight: '240px',overflowY: "scroll"}}>
{assignDetails.map(patient =>
<div onClick={()=> { browserHistory.push(`/patientsTask/${patient.PatientID}`); }} className="showingdet"><span style={{fontWeight:700}}>{patient.PatientID}</span>-{patient.Name}</div>
)}
</div>
</div>}
</Collapsible>
</div>;
}
Please help me to solve

Related

How do i bind a css stylesheet to only 1 react component?

I am using a React Template, where i inserted a shopping cart site using some react and Simple HTML (The code is below the question). Also i have a index.css file, which contains the css for the shopping cart. My goal is to implement the css only in the shopping cart site.
I tried to "import './index.css' inside my shopping cart.
The problem was as follows: After rendering the shopping cart, the css was applied to every other site as well.
How is it possible to use the css code only in the shopping cart?
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Link } from 'react-router-dom';
import { addToCart, removeFromCart } from '../../frontend/actions/cartActions';
import MessageBox from '../../frontend/MessageBox';
import { useLocation } from 'library/hooks/useLocation';
export default function CartScreen(props) {
// Namen
var a = window.location.href;
var b = a.substring(a.indexOf("?")+1)
const productId = b;
console.log(productId)
// redux store
const cart = useSelector((state) => state.cart);
const { cartItems, error } = cart;
const dispatch = useDispatch();
useEffect(() => {
if (productId) {
dispatch(addToCart(productId));
}
}, [dispatch, productId]);
const removeFromCartHandler = (id) => {
// delete action
dispatch(removeFromCart(id));
};
const checkoutHandler = () => {
props.history.push('/signin?redirect=shipping');
};
return (
<div className="row top">
<div className="col-2">
<h1>Shopping Cart</h1>
{error && <MessageBox variant="danger">{error}</MessageBox>}
{/* display cart or message if empty */}
{cartItems.length === 0 ? (
<MessageBox>
Cart is empty. <Link to="/">Go Shopping</Link>
</MessageBox>
) : (
<ul>
{cartItems.map((item) => (
<li key={item.product}>
<div className="row">
<div>
<img
src={item.image}
alt={item.name}
className="small"
></img>
</div>
<div className="min-30">
<Link to={`/product/${item.product}`}>{item.name}</Link>
</div>
<div>
<select
value={item.qty}
onChange={(e) =>
dispatch(
addToCart(item.product, Number(e.target.value))
)
}
>
{[...Array(item.countInStock).keys()].map((x) => (
<option key={x + 1} value={x + 1}>
{x + 1}
</option>
))}
</select>
</div>
<div>${item.price}</div>
<div>
<button
type="button"
onClick={() => removeFromCartHandler(item.product)}
>
Delete
</button>
</div>
</div>
</li>
))}
</ul>
)}
</div>
<div className="col-1">
<div className="card card-body">
<ul>
<li>
<h2>
Subtotal ({cartItems.reduce((a, c) => a + c.qty, 0)} items) : $
{cartItems.reduce((a, c) => a + c.price * c.qty, 0)}
</h2>
</li>
<li>
<button
type="button"
onClick={checkoutHandler}
className="primary block"
disabled={cartItems.length === 0}
>
Proceed to Checkout
</button>
</li>
</ul>
</div>
</div>
</div>
);
}
import './index.css'
give the div in the html a specific name: <div className="cartScreen">
in css, specify the element where the style should be used:
body .cartScreen{
margin: 0;
height: 100vh;
font-size: 1.6rem;
font-family: Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

React in CSS with react in viewport

I am using react in viewport from here: https://github.com/roderickhsiao/react-in-viewport and I set up the boiler plate so that the following line of code works:
<ViewportBlock onEnterViewport={() => console.log('enter')} onLeaveViewport={() => console.log('leave')} />
Looking at console.log it is saying enter and leave where I need it too. However, I need to have it say onEnterViewport set .Header (the css className is Header) to display:none in css, and onLeaveViewport set to display:block
Edit:
Full code:
const Block = (props: { inViewport: boolean }) => {
const { inViewport, forwardedRef } = props;
const color = inViewport ? '#217ac0' : '#ff9800';
const text = inViewport ? 'In viewport' : 'Not in viewport';
return (
<div className="viewport-block" ref={forwardedRef}>
{/* <h3>{ text }</h3>
<div style={{ width: '400px', height: '300px', background: color }} /> */}
<Link to="Header" spy={true} smooth={true} offset={-100} duration={1400}><img src={arrow} alt="arrow" className={inViewport ? 'hide' : 'Header-div2-mainnav-arrow' } /></Link>
</div>
);
};
const ViewportBlock = handleViewport(Block, /** options: {}, config: {} **/);
export const Header = () => ({
componentDidMount: function() {
Events.scrollEvent.register('begin', function(to, element) {
console.log('begin', arguments);
});
Events.scrollEvent.register('end', function(to, element) {
console.log('end', arguments);
});
scrollSpy.update();
},
componentWillUnmount: function() {
Events.scrollEvent.remove('begin');
Events.scrollEvent.remove('end');
},
scrollToBottom: function() {
scroll.scrollToBottom();
},
handleSetActive: function(to) {
console.log(to);
},
render: function() {
return (
<div className="Header">
<div className="Header-div1">
{/* background image */}
<h1 className="Header-div1-number">910-910-910</h1>
<h2 className="Header-div1-email">larryslawn#gmail.com</h2>
</div>
<div className="Header-div2">
<h1 className="Header-div2-h1"><span className="Header-div2-span">Larry's </span>Lawn Mowing</h1>
<p className="Header-div2-p">No job too big or too small, we do it all </p>
<div className="Header-div2-mainnav">
<Link to="Pricing" spy={true} smooth={true} offset={-50} duration={1200}><p>Pricing</p></Link>
<Link to="Services" spy={true} smooth={true} offset={-100} duration={1200}><p className="Header-div2-mainnav-p">Services</p></Link>
<Link to="Contact" spy={true} smooth={true} offset={-100} duration={1400}><p>Contact</p></Link>
</div>
<Block />
</div>
</div>
)
}
})
Use useState to toggle a class with display: none on the Header component:
const Example = () => {
const [inView, setInView] = useState(false)
return (
<>
<ViewportBlock
onEnterViewport={() => setInView(true)}
onLeaveViewport={() => setInView(false)}
/>
<Header className={inView ? 'hide' : '' }>Header</Header>
</>
)
}
CSS:
hide { display: none; }

How to catch click event with addEventListener

I am having a modal with button inside. Unfortunatly, it's not properly working. During the build I got an error : TypeError: Cannot read property 'addEventListener' of null
Below is the code:
import React from "react";
import { Modal } from "react-bootstrap";
import '../../assets/styles/Login.css';
class LoginRegisterModal extends React.Component {
constructor(props, context) {
super(props);
this.state = {show: false};
}
componentDidMount(){
const signUpButton = document.getElementById('signUp');
const signInButton = document.getElementById('signIn');
const container = document.getElementById('container');
signUpButton.addEventListener('click', () => {
container.classList.add('right-panel-active');
});
signInButton.addEventListener('click', () => {
container.classList.remove('right-panel-active');
});
}
....
render() {
const styleModal = {
marginTop: "15%",
marginLeft: "30%",
padding: 0,
width:770,
height:480,
backgroundColor:"#ffffffff",
borderRadius:21.5,
}
return (
<Modal show={this.state.show} style={styleModal} >
<div class="container" id="container">
<div>
.....
</div>
<div class="overlay-container">
<div class="overlay">
<div class="overlay-panel overlay-left">
<h1>Sign in.</h1>
<p>
Nice to see you again.Login and continue the journey.
</p>
<button class="ghost" id="signIn">Sign In</button>
</div>
<div class="overlay-panel overlay-right">
<h1>Hey, new friend!</h1>
<p>New to the Village? Sign up and start your journey</p>
<button class="ghost" id="signUp">Sign Up</button>
</div>
</div>
</div>
</div>
</Modal>
);
}
}
export default LoginRegisterModal;
I have tried adding a if condition before the addListener but it's just fixing the error but not working.
Also I have tried to replace by onClick instead but it's not working the code
signUpButton = () => {
container.classList.add('right-panel-active');
}
but container is not known..
Any idea?
Thanks
Your code should be inside component did mount method componentDidMount(). That's because when you look for a element with id "signUp" it doesn't exist yet. I don't encourage you to do what you are doing. A better approach would be <button onClick={myMethod}>

How do I scroll up and down a SideBar rather than the whole window?

I will only show relevant code as there is a lot of it. This is the parent component App:
export default class App extends React.Component {
render() {
return (
<nav className="navbar navbar-expand-xl navbar-side" aria-label="Side Navigation">
<div className={`navbar-toggler ${this.state.notification ? 'has-notification' : ''}`} data-toggle="collapse" data-target="#sidebarCollapse" aria-controls="sidebarCollapse" aria-expanded="false" aria-label="Toggle side navigation">
Menu
</div>
<div className="collapse navbar-collapse" id="sidebarCollapse">
<ul className="navbar-nav mr-auto">
<li className="nav-user">
<div className="profile-pic">
<i className="fa fa-lg fa-user mt-1" />
</div>
<i><span>{this.state.authenticatedUser.first_name} {this.state.authenticatedUser.last_name}</span><br />{this.state.authenticatedUser.job_title}</i>
</li>
<NavBar />
</ul>
</div>
</nav>
)
}
This is the Navbar component:
class NavBar extends Component {
constructor(props) {
super(props);
this.state = {
auth: false,
slide: 0, // How much should the Navbar slide up or down
lastScrollY: 0, // Keep track of current position in state
}
}
componentWillMount() {
let navbar = document.getElementById('navbar-div');
navbar.addEventListener('scroll', this.handleScroll);
}
componentWillUnmount() {
let navbar = document.getElementById('navbar-div');
navbar.removeEventListener('scroll', this.handleScroll);
}
handleScroll = () => {
let navbar = document.getElementById('navbar-div');
const { lastScrollY } = this.state;
const currentScrollY = navbar.scrollY;
if (currentScrollY > lastScrollY) {
this.setState({ slide: '-48px' });
} else {
this.setState({ slide: '0px' });
}
this.setState({ lastScrollY: currentScrollY });
};
render() {
return (
<div className="navbar-div" id="navbar-div">
{this.adminMenu()}
{this.usersMenu()}
</div>
);
}
}
adminMenu and usersMenu are just arrays of objects which output the object names. The error I get says navbar is null hence it cannot add an event listener onto a null object. How do I solve this?
Use componentDidMount rather than componentWillMount. The latter will run before any markup is rendered.
You can read more about lifecycle methods here: https://reactjs.org/docs/state-and-lifecycle.html#adding-lifecycle-methods-to-a-class
However, I'd highly recommend you to apply a handler on the element instead of componentDid/Will/Mount/Unmount, like this:
render() {
return (
<div className="navbar-div" id="navbar-div" onScroll={this.handleScroll}>
{this.adminMenu()}
{this.usersMenu()}
</div>
);
}

How to wrapp Reactjs component with CSS

I'm pretty new to Reactjs world and I have wrote component that I would love to make beautiful with CSS :)
I have component consisted of few buttons and boxes which would be displayed after button is clicked.
class Days extends React.Component {
constructor(props) {
super(props);
this.state = { showComponent: "Box1" };
}
toggleDiv = name => {
if (name === "monday") {
this.setState({
showComponent: "Box1"
});
} else if (name === "thursday") {
this.setState({
showComponent: "Box2"
});
}
};
render() {
return (
<div>
<button onClick={() => this.toggleDiv("monday")}>
<div className="botun">Monday</div>
</button>
{this.state.showComponent === "Box1" && <Box1 />}
<button onClick={() => this.toggleDiv("thursday")}>
<div className="botun">Thursday</div>
</button>
{this.state.showComponent === "Box2" && <Box2 />}
</div>
);
}
}
class Box1 extends React.Component {
render() {
return (
<div className="container">
<div className="row">
<div className="col">
<h1>BOx1</h1>
</div>
</div>
</div>
);
}
}
class Box2 extends React.Component {
render() {
return (
<div className="container">
<div className="row">
<div className="col">
<h1>Box2</h1>
</div>
</div>
</div>
);
}
}
After button1 is clicked belonging boxes will be shown under.
So my question is how to put all buttons and boxes into one container and style it like in screenshot?
If I include it in my landingpage.js like this
<div className="container">
<div className="row">
<Days />
</div>
</div>
How can I still make my buttons be in one line?
I am not sure how to approach this with CSS.
What is the best practice when using CSS and CSS frameworks with ReactJS?
I am using global style.css and Boostrap.
You should wrap all your buttons inside a single div, give the container a single class, give it's children a modifier class when they are active and if you want to animate the display of the boxes then you shouldn't unmount them when another button is active opting for making them invisible or something like that because otherwise it's kinda difficult to not have React just pop them into existence.
I use inline style tags. It's really a personal preference situation. As you try new things you'll discover the practice that's best for you and for individual projects. An inline style tag looks like this.<div style={{ display: 'flex', width: '100%', backgroundColor: 'red' }}></div> the benefit to this is you can keep styles defined in the component.

Resources