Radio Input As Cards - React + Antd - reactjs

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.

Related

How can I use emotion/styled in my react project on codepen?

I need to be able to use #emotion/styled CSS-in-JS library so I can pass props to the background-color and color properties of my Button component. The background-color and color of the buttons are supposed to change with the rest of the app.
The commented out section that starts the JS section:
import EmotionStyled from "https://cdn.skypack.dev/#emotion/styled#11.10.5";
import styled from "https://cdn.skypack.dev/#emotion/styled#11.10.5"
function Button(props) {
const Button = styled.button`
margin-top: 2rem;
background-color: ${props.colorChange};
color: white;
border: none;
height: 2.5rem;
border-radius: 4px;
padding: 0 1rem;
font-size: 1rem;
&:nth-of-type(1) {
margin-right: 0.5rem;
}
&:hover {
background-color: ${props.colorChange};
opacity: 0.9;
}
`
return (
<div className='buttons'>
<div className='left'>
<Button><a href='https://twitter.com/intent/tweet?hashtags=quotes&related=freecodecamp&text=%22Everything%20has%20beauty%2C%20but%20not%20everyone%20can%20see.%22%20Confucius' id='tweet-quote'
target='_blank'
rel='noreferrer'><i className="fa-brands fa-twitter"></i></a></Button>
<Button><a href='https://www.tumblr.com/login?redirect_to=https%3A%2F%2Fwww.tumblr.com%2Fwidgets%2Fshare%2Ftool%3Fposttype%3Dquote%26tags%3Dquotes%252Cfreecodecamp%26caption%3DConfucius%26content%3DEverything%2Bhas%2Bbeauty%252C%2Bbut%2Bnot%2Beveryone%2Bcan%2Bsee.%26canonicalUrl%3Dhttps%253A%252F%252Fwww.tumblr.com%252Fbuttons%26shareSource%3Dtumblr_share_button' id='tumblr-quote'
target='_blank'
rel='noreferrer'><i className="fa-brands fa-tumblr"></i></a></Button>
</div>
<Button id='new-quote'
onClick={props.handleChange}
>New quote</Button>
</div>
)
}
is supposed to replace the Button component I have in place at the moment. Whenever I use this emotion-styled Button component, everything goes blank. Please help!
Here is a link to the codepen project: https://codepen.io/lawlessIndi/pen/gOKjNMG.

Design Bootstrap dynamic nav tabs component

I want to design a dynamic nav tabs component. when the card is clicked relevant tab is shown, with the connection arrow and border-color green.
sample code or a suggestion would be much helpful
.
You can use accordion by bootstrap. Use css flexbox to horizontally align the tabs next to each other and bind a javascript method that changes css color properties (arrow, green color) on clicking.
Here is the link - https://getbootstrap.com/docs/4.0/components/collapse/
Here is how you can do :
.js :
import React, { Component } from "react";
import { render } from "react-dom";
import "./style.css";
const App = () => {
const selectBlock = (e) => {
e.target.classList.toggle('selected');
}
return (
<div className="block" onClick={(e) => {selectBlock(e)}}>
<div>Here is the block</div>
<div className="arrow">
<FakeArrow />
</div>
</div>
);
};
const FakeArrow = () => {
return (
<div>
<span className="arrow-down-border" />
<span className="arrow-down" />
</div>
);
};
render(<App />, document.getElementById("root"));
.css :
.block {
position: relative;
width: 150px;
height: 50px;
text-align: center;
border: 2px solid black;
}
.arrow {
display: none;
}
.block.selected {
border: 2px solid #99d32c;
}
.block.selected .arrow {
display: block;
}
/* You need to fake the arrow border with another arrow behind */
.arrow-down-border {
position: absolute;
bottom: -20px;
left: 55px; /* 150px (main block) / 2 -20px (size of the triangle)*/
width: 0;
height: 0;
border-left: 20px solid transparent;
border-right: 20px solid transparent;
border-top: 20px solid #99d32c;
}
.arrow-down{
position: absolute;
bottom: -17px;
left: 58px; /* 150px (main block) / 2 -17px (size of the triangle)*/
width: 0;
height: 0;
border-left: 17px solid transparent;
border-right: 17px solid transparent;
border-top: 17px solid #ffffff;
}
Here is the repro on Stackblitz.
Of course this is just an example, you have to set a color for the arrows so my advice would be to do it with constants or props. Same thing for the position and others functionality you can add to the FakeArrow component.
Now, it would be waaaayy easier to manage it with an image if you really need a border (this is the tricky part in your requirement), or a simple arrow without border.
You can take a look at this post, it's the same question actually, i used a slightly different way to do it with css, but the result seems to be the same.

How to customize width and height of Floating Action Button material ui component in React. Also the button does not show the edit icon correctly

I want to add a Floating Action Button (FAB) on my app. Where I want to adjust its width and height to reduce its size using css. Also the button does not show the edit icon inside the button as expected.
Below are the code that I tried,
Code Sandbox
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import './profile/profile.css';
import ProfileInfo from './profile/profile';
ReactDOM.render(
<ProfileInfo />,
document.getElementById('root')
);
profile.js
import React from 'react';
import './profile.css';
import Fab from '#material-ui/core/Fab';
import Icon from '#material-ui/core/Icon';
class ProfileInfo extends React.Component{
render(){
return(
<div className='prof-main-container'>
<div className='prof-items-container'>
<div className='prof-pic-container'><img src="https://ik.imagekit.io/upgrad1/upgradlogo.png" className="prof-pic" alt="profile pic" /></div>
<div className='prof-info-data-container'>
<div className='user-name'>User Name</div>
<div className='posts-follows-container'>
{/* <span className='posts-follows-item-first'>Posts:6</span>
<span className='posts-follows-item'>Follows:4</span>
<span className='posts-follows-item'>Followed By:6</span> */}
<span>Posts:6</span>
<span className='posts-follows-item'>Follows:4</span>
<span>Followed By:6</span>
</div>
<div className='full-name-container'>
<div className='full-name'>UpGrad Education</div>
<div className='full-name-edit-btn'>
{/* <Button variant="fab" color="secondary" size='medium'>
Edit
</Button> */}
<Fab color="secondary" aria-label="Edit" className='edit-btn'>
<Icon>edit_icon</Icon>
</Fab>
</div>
</div>
</div>
</div>
</div>
)
}
}
export default ProfileInfo
profile.css
.prof-main-container {
display: flex;
background-color: #5995DA; /* Blue */
padding: 20px 0;
}
.prof-items-container {
border: 1px solid #fff;
width: 100%;
display: flex;
/* justify-content: space-around; */
padding: 0% 20%;
/* padding-left: 500px; */
}
.prof-info-data-container{
display: flex;
/* justify-content: space-between; */
flex-direction: column;
margin: 0px 40px;
}
.prof-pic-container{
padding: 15px 0px 0px 0px;
}
.prof-pic{
width: 50px;
height: 50px;
}
.posts-follows-item{
margin: 0px 60px;
}
.posts-follows-container{
font-size: 11px;
margin: 2px 0px;
}
.full-name-container{
display: flex;
flex-direction: row;
}
.full-name{
font-size: 12px;
margin: 10px 0px;
}
.user-name{
font-size: 12px;
font-weight: bold;
margin: 5px 0px;
}
.full-name-edit-btn{
margin: 5px 20px;
}
.edit-btn{
width: 20px;
height: 20px;
}
The expected edit icon is as below.
But actually it is rendering as below. Note that, no edit icon is displaying inside the button as expected instead it is showing "EC" inside the button.Please ignore the background color here.
Also, I should be able to adjust the width and height of the below edit button to reduce its size.But I am not able to do it using css. I tried adding a class named "edit-btn" inside profile.css but it does not work.
Did you try using classes prop instead of className on your Fab element.
According to the documentation you should use the former.
Refer this link for the same :
Material UI FAB props
I have updated my answer. Your .edit-btn class will work fine if you give it more specificity. Refer my code sandbox for the same.
Regarding your <Icon> can you help me understand what is edit_icon?
code sandbox
Do give it a try and see if it works. Also please share what you have tried so far.Thanks!

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>

why first two item is not working in react?

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.

Resources