why first two item is not working in react? - reactjs

I have generated the following four buttons but the first two button (More button) is not working.
Here is the code:
BuildControls.js
import React from 'react';
import BuildControl from './BuildControl/BuildControl';
import classes from './BuildControls.css';
const controls = [
{label:'Salad', type:'salad'},
{label:'Bacon', type:'bacon'},
{label:'Cheese', type:'cheese'},
{label:'Meat', type:'meat'}
]
const buildControls =(props)=>(
<div className={classes.BuildControls}>
<p>Current Price: <strong> {props.price} </strong> BDT</p>
{controls.map(ctrl => (
<BuildControl
label ={ctrl.label}
key={ctrl.label}
addIngredient={()=>props.addIngredients(ctrl.type)}
removeIngredient={()=>props.removeIngredient(ctrl.type)}
disabled ={props.disabled[ctrl.type]}
/>
)
)}
<button
disabled={!props.purchaseAble}
className={classes.OrderButton}
onClick ={props.ordered}> ORDER NOW</button>
</div>
);
export default buildControls;
BuildControl.js
import React from 'react';
import classes from './BuildControl.css';
const builControl =(props)=>(
<div className={classes.BuildControl}>
<div className={classes.Label}> {props.label}</div>
<button className={classes.Less} onClick={props.removeIngredient} disabled ={props.disabled}> Less</button>
<button className={classes.More} onClick={props.addIngredient}> More</button>
</div>
);
export default builControl;
as all the button is being generated by loop problem should be same for all button. last two button is working perfectly but first two is not working. It kills my day. I don't know how to debug as I am new in react js. Any help ?
update:
When I remove {classes.BuildControls} from <div className={classes.BuildControls}> it works fine. and here is the css:
.BuildControls {
width: 100%;
background-color: #CF8F2E;
display: flex;
flex-flow: column;
align-items: center;
box-shadow: 0 2px 1px #ccc;
margin: auto;
padding: 10px 0;
}
.OrderButton {
background-color: #DAD735;
outline: none;
cursor: pointer;
border: 1px solid #966909;
color: #966909;
font-family: inherit;
font-size: 1.2em;
padding: 15px 30px;
box-shadow: 2px 2px 2px #966909;
}
.OrderButton:hover, .OrderButton:active {
background-color: #A0DB41;
border: 1px solid #966909;
color: #966909;
}
.OrderButton:disabled {
background-color: #C7C6C6;
cursor: not-allowed;
border: 1px solid #ccc;
color: #888888;
}
.OrderButton:not(:disabled) {
animation: enable 0.3s linear;
}
#keyframes enable {
0% {
transform: scale(1);
}
60% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
Strange! css causes problem in click event. Whats wrong in my code?

Without seeing the complete code, I would guess that addIngredients should be addIngredient in buildControls :
const buildControls =(props)=>(
<div className={classes.BuildControls}>
<p>Current Price: <strong> {props.price} </strong> BDT</p>
{controls.map(ctrl => (
<BuildControl
label ={ctrl.label}
key={ctrl.label}
addIngredient={()=>props.addIngredients(ctrl.type)}
// typo here -------------------------^
If that's not it, please post the addIngredient and removeIngredient methods, including where they are defined and how they are passed down.

Related

Unexpected gap between two columns

I'm working on a react application and one of the pages has a two column layout. When I'm using a larger screen, there is a gap in between the two columns, thats not there on a smaller screen like a laptop. When i use the chrome inspect tool on the larger screen, the gap disappears.
I know its not my CSS doing this because I've adjusted every margin and padding value and it still shows up. I've even tried the resolution and the display on the larger screen and its still there.
Any help would be greatly appreciated!
EDIT
ProjectList.js
.project-list-page {
float: right;
width: 90vw;
}
.project-top-bar {
padding: 1rem;
display: flex;
justify-content: space-between;
border-bottom: 1px solid grey;
box-shadow: var(--box-shadow);
}
.project-top-bar input {
box-shadow: var(--box-shadow);
border: none;
border-radius: var(--border-radius);
width: 25vw;
padding: 5px;
font-size: 1em;
}
.project-list {
height: 100%;
list-style-type: none;
margin: 0;
padding: 0;
height: 100%;
overflow: scroll;
}
.project-column {
float: left;
border-collapse: collapse;
height: 87vh;
}
.project-left-side {
width: 30%;
}
.project-right-side {
width: 70%;
}
.project-list-item {
padding: 2em 0.5rem;
border-collapse: collapse;
border: 1px solid lightgrey;
overflow: auto;
width: 100%;
cursor: pointer;
}
.project-list-item:hover {
background-color: #e6e6e6;
}
.project-list a {
text-decoration: none;
color: black;
}
<>
<div className='project-list-page'>
<div className='project-top-bar'>
<input type="text" className='project-search-input' placeholder='Search projects ...' />
<button className='btn new-project-btn'>New Project</button>
</div>
<div className='project-column project-left-side'>
<ul className='project-list'>
{projectList.map(project => {
return <ProjectListItem project={project}/>
})}
</ul>
</div>
<div className='project-column project-right-side'>
Preview
</div>
</div>
</>
ProjectListItem.js
<Link to={`/projects/${project.name}`}>
<li className='project-list-item'>
{project.name}
</li>
</Link>

Structuring Sidebar in React

Relatively new to React, and am wanting to recreate the design below
enter image description here
I have the base formatting down, but as you will notice, there are lines separating the logo blocks, from the login and signup blocks, with the signup and login buttons pushed to the bottom.
Below is my current code
CSS:
width: 100vw;
height: 100vh;
}
body {
margin: 0;
padding: 0;
}
.Sidebar {
height: 100%;
width: 20%;
background-color: white;
border-right: 1px solid #F0F4FB;
padding-left: 15px;
box-sizing: border-box;
}
.SidebarList {
height: auto;
width: 100%;
padding-left: 15px;
font-size: 18px;
border: 2px #FD954E;
box-sizing: border-box
}
.SidebarList .row {
width: 100%;
height: 50px;
background-color: white;
list-style-type: none;
margin: 0%;
padding-bottom: 15px;
display: flex;
color: #A7ACB6;
justify-content: center;
align-items: center;
font-family: Arial, Helvetica, sans-serif;
}
.SidebarList .row:hover {
cursor: pointer;
background-color: #E7E7E7 ;
}
.SidebarList #active {
background-color: white;
color: #FD954E
}
.SidebarList .Login {
background-color: white;
color: #FD954E;
width: 279px;
height: 39px;
right: 1596px;
top: 958px;
border: 1px solid #FD954E;
box-sizing: border-box;
border-radius: 19.5px;
}
.SidebarList .SignUp {
width: 279px;
height: 39px;
right: 1596px;
top: 1011px;
background: #FD954E;
border-radius: 19.5px;
border: none;
}
.row #icon {
flex: 30%;
display: grid;
place-items: center;
transform: scale(1.2)
}
.row #title {
flex: 70%;
}
.Logo {
padding-left: 25px;
padding-top: 25px;
padding-bottom: 30px;
border-bottom: 1px solid #F0F4FB;
width: 55%;
}
Sidebar.js
import React from "react";
import "../App.css";
import { SidebarData } from './SidebarData'
import Logo from './Logo.svg'
function Sidebar() {
return (
<div className="Sidebar">
<div>
<img src = {Logo} alt='Logo’ className=‘Logo’ />
</div>
<ul className="SidebarList">
{SidebarData.map((val, key) => {
return (
<li
key={key}
className="row"
id={window.location.pathname == val.link ? "active" : ""}
onClick={() => {
window.location.pathname = val.link;
}}
>
<div id="icon">{val.icon}</div> <div id="title">{val.title}</div>
</li>
);
})}
</ul>
<div className= "SidebarList">
<button className="Login">
Login
</button>
</div>
<div className= "SidebarList">
<button className="SignUp">
Sign Up
</button>
</div>
</div>
);
}
export default Sidebar;
How should I structure my code in order to acheive my desired result? Ex: with the logo at the top with the seperator, the list of navigation elements, and then the login and signup buttons at the bottom with the seperator?
Currently, my sidebar looks as follows, with the seperator not full width between the logo and navigation elements, and the buttons extending beyond the sidebar.
enter image description here
It would be easier to simplify the problem with just HTML and CSS as that's much easier to troubleshoot. Part of your problem is that you are defining the width of the sidebar as a percentage of the screen width but elements within the sidebar are defined with a width in pixels. When the browser window is too small, your buttons will appear outside the full width of the sidebar. You could either code all your values as percentages or in pixels. Alternatively, you could use a mix and just set a min-width for the sidebar so that you don't end up with elements out of place.
The reason that your line break is not the full width of your sidebar is because you are defining it with the border-bottom property of the logo. Your logo is not 100% the width of the sidebar so your line break will only be the width of the logo. A better solution would be to define a div that is set to width: 100%. This way, you will have more control.
Here is a simplified solution to your sidebar problem using pixels to define the widths.
HTML:
<div class="sidebar">
<div class="header">
<div class="logo">Logo</div>
</div>
<div class="line-break" />
<div class="content">
<ul class="nav">
<li>Home</li>
<li>Blog</li>
</ul>
</div>
<div class="line-break" />
<div class="footer">
<button class="login">Login</button>
<button class="sign-up">Sign up</button>
</div>
</div>
CSS:
html, body {
height: 100%;
margin: 0;
padding: 0;
}
.sidebar {
width: 300px;
height: 100%;
border-right: 1px solid grey;
}
.line-break {
height: 1px;
width: 100%;
background-color: grey;
}
.header .logo {
height: 40px;
width: 200px;
background-color: grey;
margin: 20px;
}
ul.nav {
list-style-type: none;
padding: 20px 0 0 40px;
}
ul.nav li {
margin-bottom: 14px;
}
ul.nav li:last-child {
margin-bottom: 0;
}
.footer {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px 0;
}
.footer button {
padding: 6px 0;
width: 80%;
margin-bottom: 14px;
}
.footer button:last-child {
margin-bottom: 0;
}
And here is a link to a CodePen
where you can see this in action.

Radio Input As Cards - React + Antd

I wanted to create Radio Input Buttons styled Cards.
I am using react js and ant design.
Tried to create my own native component using good old input type="radio".
Connecting them to antd forms wasen't smooth sailing, then I had another idea.
Using antd react Radio component and just passing a card component. That's the working result!
Usage.tsx
// Other Code
<Radio.Group onChange={onChange} value={value} className="cards-container">
<Radio value={FOCUS_LEVEL.Regular} className="radio-input-card-container">
<InputCard
title="First Card"
checked={value === CONSTANT1}
imgPath="../../assets/icon1.svg"
points={["This is a point explain why this card is the best!", "Wow this is also a great point"]} />
</Radio>
<Radio value={FOCUS_LEVEL.DeepFocus} className="radio-input-card-container">
<InputCard
title="Second Card"
checked={value === CONSTANT2}
imgPath="../../assets/icon2.svg"
points={["This point explains why this card is way better", "The other card as shitty points!"]} />
</Radio>
</Radio.Group>
// Other Code
Usage.scss
.cards-container {
display: flex;
justify-content: space-between;
margin-left: 20px;
}
InputCard.tsx
import React from "react"
import Title from "antd/lib/typography/Title";
import "./InputCard.scss"
export function InputCard({ title, checked, imgPath, points }): JSX.Element {
return (
<div className={checked ? "card checked" : "card"}>
<div className="header-container">
<Title className="card-title">{title}</Title>
<img src={imgPath} alt="regular focus"></img>
</div>
<ul>
{points.map((point) =>
<li key={point.toString()}>{point}</li>
)}
</ul>
</div >
);
}
InputCard.scss
.card {
height: 420px !important;
width: 360px !important;
position: relative !important;
left: -45px; // A work around. Placing the card under the native radio button
-webkit-appearance: none;
appearance: none;
border: 2px solid rgba(2,28,53,0.08);
border-radius: 14px;
box-shadow: 7px 7px 15px rgba(2,28,53,0.08);
cursor: pointer;
outline: none;
.header-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
ul {
padding: 0em 1em 0em 2.5em !important;
}
img {
margin: 0.5em 0em 1em 0em;
}
}
.card-title {
font-size: 20px !important;
margin-top: 16px !important;
}
.checked {
transition: border 0.5s ease;
border: 2px solid rgba(255,0,0,0.6);
}
The antd component creates a radio input circle right before the card childe. Moving the card to the left (left: -45px) so the card will include the radio circle is a workaround. I don't want to change too much in the parent component for me to use this InputCard component, and this is my try to do it within the component.

How can I style react-datepicker?

I'm using webpack, react-datepicker and have managed to import its css with the provided css module.
import 'react-datepicker/dist/react-datepicker-cssmodules.css
The component looks fine and dandy, but now I want to make it full width like the time element above it.
Looking at the CSS, what it needs is for the react-datepicker-wrapper element that gets dynamically added by the library to have display: block. Any modifications I make to react-datepicker-wrapper in my own css does nothing.
What should I do?
date-picker.component.jsx
import React from 'react';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker-cssmodules.css';
import './date-picker.component.bootstrap.css';
// eslint-disable-next-line no-confusing-arrow
const buildClassNames = (touched, isInvalid) =>
touched && isInvalid ? 'form-control is-invalid' : 'form-control';
export const DatePickerBootstrap = (props) => {
const { setFieldValue, setFieldTouched, errors, touched } = props;
const { name, value, label, ...rest } = props;
return (
<div className="form-group">
<label className='datePickerLabel' htmlFor={name}>{label}</label>
<DatePicker
selected={value}
onChange={(e) => {
setFieldValue(name, e);
setFieldTouched(name);
}}
className={buildClassNames(touched, !!errors)}
customInput={
<input
type="text"
id={name}
placeholder={label} />
}
{...rest}
/>
<div className="invalid-feedback">
{errors}
</div>
</div>
);
};
export default DatePickerBootstrap;
From https://github.com/Hacker0x01/react-datepicker/issues/2099#issuecomment-704194903
Try with wrapperClassName property:
<DatePicker wrapperClassName="datePicker" dateFormat="dd/MM/yyyy" />
CSS:
.datePicker {
width: 100%;
}
This way you won't modify the styles for the whole app
styled-components bonus:
import React from 'react';
import styled, { css, createGlobalStyle } from 'styled-components';
import DatePicker from 'react-datepicker';
const DatePickerWrapperStyles = createGlobalStyle`
.date_picker.full-width {
width: 100%;
}
`;
<>
<DatePicker wrapperClassName='date_picker full-width' />
<DatePickerWrapperStyles />
</>
I think you're just missing some CSS. Try this in your custom stylesheet (anywhere after the datepicker's stylesheet):
.react-datepicker-wrapper,
.react-datepicker__input-container,
.react-datepicker__input-container input {
display: block;
width: 100%;
}
Demo
styled-components
<>
<DatePickerWrapper
popperContainer={Popper}
calendarContainer={Calendar}
/>
</>
const DatePickerWrapper = styled(({ className, ...props }) => (
<DatePicker {...props} wrapperClassName={className} />
))`
width: 100%;
`;
const Calendar = styled.div`
border-radius: 10px;
box-shadow: 0 6px 12px rgba(27, 37, 86, 0.16);
overflow: hidden;
`;
const Popper = styled.div`
position: absolute;
top: 0;
left: 0;
z-index: 2;
`;
You can get your css work by putting !important at the end of the lines:
display: block !important;
And, you should import your css file at the end:
import 'library0.css';
import 'library1.css';
import 'library2.css';
import 'yourCss.css'; // Your css
overwrite the default css like
.react-datepicker__input-container input {
width: 100%;
}
working example
You can put it inside a flexbox.
If you are using bootstrap, you can use the d-flex and flex-column classes on the wrapper element.
<div className="d-flex flex-column">
<DatePickerField name="date" label="Date" />
</div>
If not, you can style the wrapper using CSS properties.
<div className="date-picker-wrapper">
<DatePickerField name="date" label="Date" />
</div>
CSS:
.date-picker-wrapper {
display: flex !important;
flex-direction: column !important;
}
You can add to the style sheet:
.react-datepicker__input-container{
input{
width: 100%;
padding: 0.375rem 2.25rem 0.375rem 0.75rem;
-moz-padding-start: calc(0.75rem - 3px);
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #212529;
background-color: #fff;
border: 1px solid #ced4da;
border-radius: 0.25rem;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
appearance: none;
}
}
Output
You can use the class of each element of the picker to override its default style, using the inspect tool you can identify each element's class, if your new style won't be applied you can use the !important property to override the default style
The following code is applied to most of the pickers elements
.react-datepicker__triangle {
display: none;
}
.react-datepicker__day.react-datepicker__day--keyboard-selected {
border: none;
border-radius: 7px;
background-color: var(--dark);
color: var(--white);
}
.react-datepicker__day.react-datepicker__day--keyboard-selected:hover {
border: none;
border-radius: 7px;
background-color: var(--dark);
color: var(--white);
}
.react-datepicker-popper .react-datepicker__navigation {
padding-top: 12px;
color: #000;
}
.react-datepicker {
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.189);
border: none !important;
font-family: "Inter" !important;
}
.react-datepicker__header {
border-bottom: solid 5px var(--light) !important;
background: white !important;
}
.react-datepicker__current-month {
color: var(--dark) !important;
}
.react-datepicker__day.react-datepicker__day--today {
border-radius: 7px;
border: solid 2px var(--brand) !important;
background-color: white !important;
color: var(--dark) !important;
width: 30px;
height: 30px;
}
.react-datepicker__day.react-datepicker__day--selected {
border: none;
border-radius: 7px;
background-color: black;
color: white;
}
.react-datepicker__day--selected:hover,
.react-datepicker__day--in-selecting-range:hover,
.react-datepicker__day--in-range:hover,
.react-datepicker__month-text--selected:hover,
.react-datepicker__month-text--in-selecting-range:hover,
.react-datepicker__month-text--in-range:hover,
.react-datepicker__quarter-text--selected:hover,
.react-datepicker__quarter-text--in-selecting-range:hover,
.react-datepicker__quarter-text--in-range:hover,
.react-datepicker__year-text--selected:hover,
.react-datepicker__year-text--in-selecting-range:hover,
.react-datepicker__year-text--in-range:hover {
border: none;
border-radius: 7px !important;
background-color: var(--brand) !important;
color: var(--dark) !important;
}
From https://github.com/Hacker0x01/react-datepicker/issues/2099#issuecomment-704194903
Try
<DatePicker calendarClassName={/* styles */}></DatePicker>

You can move React created components in CSS? Right?

I apologizes in advance for this stupid question.
I created a series of components using the creat-react-app boilerplate. I imported them into the app.js and they render as expected but if I try move the components on the page using the app.css by giving my components an id tag. Nothing happens.
What am I missing? I thought that once you import the component you can just treat it as another html element on the page.
Again I apologizes for the simple question and grateful for any help.
As requested code:
one of my components;
import React from 'react';
import {Panel, Image} from 'react-bootstrap';
import galaxy from '/Volumes/Main Drive/Test_WebSite_2/src/Assets/galaxy.jpg';
import David from '/Volumes/Main Drive/Test_WebSite_2/src/Assets/David.jpg';
import { bootstrapUtils } from 'react-bootstrap/lib/utils';
bootstrapUtils.addStyle(Panel,'main','backgroundImg');
const IntroPanel =()=>(
<div>
<style type="text/css">
{`
.panel-backgroundImg{
width: 300px;
height: 150px;
border: 1px solid gray;
border-radius: 0px;
padding-bottom: 0px !importnt;
padding-top: 0px !importnt;
}
#background{
position: fixed;
}
.galaxy-background{
width: 298px;
height: 148px;
}
#galaxy-pos{
position: fixed;
left: 1px;
top: 73px;
}
.DavidProp{
width: 80px;
height: 80px;
border-radius: 50%;
border: 1px solid gray;
box-shadow: 0 0 0 3px white, 0 0 0 4px gray;
}
#DavidPos{
position: fixed;
left: 110px;
top: 185px;
}
.panel-main {
width: 300px;
height: 150px;
border-radius: 0px;
border: 1px solid gray;
padding-bottom: 0px !importnt;
padding-top: 0px !importnt;
right: 200px;
}
#mainPanel{
position: fixed;
top: 222px;
left: 0px;
}
.Name{
font-weight: Bold;
}
#NamePos{
position: fixed;
top: 275px;
left: 95.5px;
}
.Intro{
}
#IntroPos{
position: fixed;
top: 300px;
left: 10.5px;
}
.sighting{
font-style: oblique;
font-size: 14px;
font-weight: Bold;
}
`}
</style>
<div>
<Panel bsStyle="backgroundImg" id="background">
<img src={galaxy} className="galaxy-background" id="galaxy-pos" alt="backgroundImg"/>
</Panel>
<Panel bsStyle="main" id="mainPanel">
<p className="Name" id="NamePos">
David Townsend
</p>
<p className="Intro" id="IntroPos">
"I am a Leaf on the wind, Watch how I soar"
<p>-Wash, <span className="sighting">Serenity</span></p>
</p>
</Panel>
</div>
<div>
<Image src={David} className="DavidProp" id="DavidPos" />
</div>
</div>
);
export default IntroPanel;
Here is the App.js:
import React, { Component } from 'react';
import './App.css';
import MenuBar from './Components/MenuBar.js'
import IntroPanel from './Components/IntroPanel.js'
import AboutPanel from './Components/AboutPanel.js'
class App extends Component {
render() {
return (
<div className="App">
<div>
<MenuBar Name="Inside David Townsend's Brain"
LinkName1="Thoughts" Link1="#"
LinkName2="About" Link2="#"
LinkName3="Ideas" Link3="#"
LinkName4="Resume" Link4="#" />
</div>
<div>
<IntroPanel id="test" />
</div>
<div >
<AboutPanel />
</div>
</div>
);
}
}
export default App;
Here is the App.css:
.App {
text-align: center;
}
.App-logo {
animation: App-logo-spin infinite 20s linear;
height: 80px;
}
.App-header {
background-color: #222;
height: 150px;
padding: 20px;
color: white;
}
.App-intro {
font-size: large;
}
#keyframes App-logo-spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
#test{
position: fixed;
top: 300px;
left: 10.5px;
}
I answered my own question. The answer is in two parts.
I needed to change the css position: fixed; to position: relative;
If I understand it right the css fixed position is basically the world coordinates of the web page and the css relative position is a local coordinate of the parent object.
To move the React component I created a <div> with the created React component inside of it and moved the <div> using CSS.
I have no doubt that there is probably a more elegant way but this is how I solved my issue.

Resources