React: How to override input class in Material-UI Autocomplete - reactjs

I am working on a React project, where I have been using Bootstrap for front-end. I have integrated Autocomplete library from Material-UI.
#ref: https://material-ui.com/components/autocomplete/
Problem: I am trying to integrate form-control class inside the input tag. But it's not working.
Tried:
<Autocomplete
id="combo-box-demo"
options={this.props.customers}
onChange={(_, value) => {
console.log(value);
}}
getOptionLabel={(option) => option.name}
style={{ width: 300 }}
renderInput={(params) => (
<div ref={params.InputProps.ref}>
<input
className="form-control"
placeholder="Search by client name"
type="text"
{...params.inputProps}
/>
</div>
)}
/>
Result
Expectation

I ended up having a solution with CSS. I copied the css code of .form-control class and put in combo-box-demo ID.
input#combo-box-demo {
display: block;
width: 100%;
padding: 0.375rem 0.75rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: #212529;
background-color: #fff;
background-clip: padding-box;
border: 1px solid #ced4da;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border-radius: 0.25rem;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}

Related

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.

styled-components for input type password

how can I give styles for input type='password' in styled-components?
// export const Input = styled.input`
// width: 100%;
// height: 50px;
// border-radius: 4px;
// background-color: rgba(104, 105, 102, 0.1);
// border: 1px solid #354545;
// margin-top: 20px;
// outline: none;
// padding-left: 40px;
// color: white;
// font-size: 22px;
// `;
This should work. Unlike normal css, styled-components takes the attribute as props. You'll need to use props to style the elements conditionally.
export const Input = styled.input`
${props => props.type === 'password' && `
width: 100%;
height: 50px;
border-radius: 4px;
background-color: rgba(104, 105, 102, 0.1);
border: 1px solid #354545;
margin-top: 20px;
outline: none;
padding-left: 40px;
color: white;
font-size: 22px;
`}
`;
From styled-components documentation FAQ:
export const PasswordInput = styled.input.attrs(props => ({
// Every <PasswordInput /> should be type="password"
type: "password"
}))`
width: 100%;
height: 50px;
border-radius: 4px;
background-color: rgba(104, 105, 102, 0.1);
border: 1px solid #354545;
margin-top: 20px;
outline: none;
padding-left: 40px;
color: white;
font-size: 22px;`;
Both examples are a bit overkill for just styling purposes and can be easily avoided by using &[type="password"]
import styled from "styled-components";
export const Input = styled.input`
&[type="password"] {
border: 1px solid black;
background: red;
}
`;
export default function App() {
return (
<div>
<div>
<label htmlFor="username">Username</label>
<Input id="username" type="text" />
</div>
<div>
<label htmlFor="password">Password</label>
<Input type="password" />
</div>
</div>
);
}
Or, if you want to extend of of a base input component
import styled from "styled-components";
export const Input = styled.input`
border: 1px solid black;
`;
export const PasswordInput = styled(Input)`
&[type="password"] {
background: red;
}
`;
export default function App() {
return (
<div>
<div>
<label htmlFor="username">Username</label>
<Input id="username" type="text" />
</div>
<div>
<label htmlFor="password">Password</label>
<PasswordInput type="password" />
</div>
</div>
);
}

Track Color in input type Range in react

I have the next input type range in react:
inputElement = <div className={styles.InputElementRange}>
<input
min={props.min}
max={props.min}
value={props.value}
onChange={props.changed}
></input>
<input
type="text"
value={props.value}
onChange={props.changed}
style={props.stylesElement}
/>
</div>
and I got this:
The input type range works very well but I couldn't change the styles of the track.
How can I change the blue color by default? I want to replace the blue color for orange color.
Thanks in advance.
See this link to see how you can style the HTML slider
I found a solution:
inputElement = <div className={styles.InputElementRange}>
<input
min={props.min}
max={props.min}
value={props.value}
onChange={props.changed}
style={{'background': `linear-gradient(to right, orange ${(parseInt(props.value)-props.min)*100/(props.max-props.min)}%, #ccc 0px`}}
></input>
<input
type="text"
value={props.value}
onChange={props.changed}
style={props.stylesElement}
/>
</div>
and these are the styles:
input[type="range"] {
-webkit-appearance: none;
width: 100%;
height: 10px;
margin-right: 10px;
border-radius: 6px;
outline: 0;
background: #ccc;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
height: 18px;
width: 18px;
border-radius: 3px;
background: orange;
border-radius: 50%;
border: 0;
cursor: pointer;
}
/* All the same stuff for Firefox */
input[type=range]::-moz-range-thumb {
height: 18px;
width: 18px;
border-radius: 3px;
background: orange;
border: 0;
border-radius: 50%;
cursor: pointer;
}
/* All the same stuff for IE */
input[type=range]::-ms-thumb {
height: 18px;
width: 18px;
border-radius: 3px;
background: orange;
border-radius: 50%;
border: 0;
cursor: pointer;
}
I thought my answer based in this answer: Ver link
Here's an easy one pretty straight forward.
Note that I'm using styled components but you can use the same with vanilla css or sass as well
import React, { useState } from 'react'
import styled from 'styled-components'
export const Slider = () => {
const [bgSize, setBgSize] = useState(0)
const handleSlide = (e) => {
setBgSize(e.target.value)
}
return (
<SliderContainer>
<ColorSlider
onChange={(e) => {
handleSlide(e)
}}
bgSize={bgSize}
min={0}
max={100}
type={'range'}
/>
</SliderContainer>
)
}
export const SliderContainer = styled.div``
export const ColorSlider = styled.input`
-webkit-appearance: none; /* Override default CSS styles */
appearance: none;
background-image: linear-gradient(#ff4500, #ff4500);
background-size: ${({ bgSize }) => bgSize}% 100%;
background-repeat: no-repeat;
border: 1px solid;
&::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
margin-top: -0.5em;
// position: relative;
appearance: none;
height: 25px;
width: 25px;
border: 1px solid black;
background: #4d4945;
border-radius: 100%;
cursor: pointer;
border: 1px solid black;
}
&::-webkit-slider-runnable-track {
-webkit-appearance: none;
appearance: none;
width: 100%;
max-width: 500px;
outline: none;
height: 10px;
border-radius: 10px;
background-image: transparent;
}
`

Styled components for nested html elements (React)

I am new to styled-components, and want to know how you would write it given the following html snippet:
<div class="segmentedControlContainer">
<input type="radio" name="segmentedControlExample" value="1" id="1" />
<label for="1"> One </label>
<input type="radio" name="segmentedControlExample" value="2" id="2" />
<label for="2"> Two </label>
<input type="radio" name="segmentedControlExample" value="3" id="3" />
<label for="3"> Three </label>
<div>
so far, I have defined
export const SegmentedControlWrapper = styled.div`
display: flex;
width: 100%;
position: relative;
z-index: 1;
user-select: none;
margin: 0 auto;
font-size: 16px;
border-radius: 3px;
border: solid 1px #bcbcbc
`
export const Input = styled.input`
display: none;
&:checked + label {
color: #fff;
background: #blah;
}
`
export const Label = styled.label`
flex: 1;
color: #blah;
padding: 15px;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
&:checked {
}
&:not(:last-child){
....
}
`
and use it in react as:
<SegmentedControlWrapper>
<Input />
<Label />
</SegmentedControlWrapper>
Most of this is correct, and I think the checked state isn't styled propelry. Any pointer would be appreciated. As I am confused with using &, >, etc.
Pass checked or not checked as props to style class. It will help to style in good way.
export const Input = styled.input
display: none;
&:checked + label {
color: #fff;
background: {$props => {this.props.checked ? "some" : "some"}}
}
<Input checked={this.state.checked}/>

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>

Resources