React-Select: Unable to set default value and changing border - reactjs

I'm having issues with setting the default value and changing border color of the select when it's click already tried with :active,:blur,:focus and it's not working.
Current code:
const controlStyles = {
control: (styles: any) => ({
...styles,
fontFamily: `Gilroy`,
fontStyle: `normal`,
fontWeight: `700`,
fontSize: `18px`,
lineHeight: `22px`,
color: `#979B9B`,
width: `280px`,
height: `57px`,
border: `1px solid #007749`,
background: `#FFFFFF`,
":hover": {
border: `1px solid #007749`,
},
/*":active": {
border: `1px solid #007749`,
},
":focus": {
border: `1px solid #007749`,
},
":blur": {
border: `1px solid #007749`,
},*/
}),
};
And in setting the default value, already tried defaultValue and inputDefaultValue still not working
Current code:
<Select
styles={controlStyles}
//value={badgeData[0]}
//defaultValue={badgeData[0]}
//defaultInputValue={badgeData[0]}
//getOptionLabel={(e) => e.badge_name}
getOptionValue={(e) => e.id}
options={badgeData}
formatOptionLabel={(badgeData) => (
<div className="badge-option">
<img
src={badgeData.imgBase64}
alt={badgeData.badge_name}
className="me-4"
/>
<span>{badgeData.badge_name}</span>
</div>
)}
/>
Sample data for options:
Any ideas what Am I missing here? Thank you!

Related

Changing Button Background Color Conditionally in Material UI

i got a button that the its background color suppose to change base on state condition , green color for correct , and red for incorrect , so i just made three different css classes , all have similar attributes except the background color , classes changes base on a state with the optionBt class as a default value , how to add an interpolation to optionBt backgroundColor so i only have one class for this button?
const useStyles = makeStyles({
optionBt: {
width: "80%",
color: "#fff",
height: "2.5rem",
marginTop: "0.5rem",
borderRadius: "05%",
border: "2px solid #555",
cursor: "pointer",
},
optioncorrect: {
width: "80%",
color: "#fff",
height: "2.5rem",
marginTop: "0.5rem",
borderRadius: "05%",
border: "2px solid #555",
cursor: "pointer",
backgroundColor: "green",
},
optionuncorrect: {
width: "80%",
color: "#fff",
height: "2.5rem",
marginTop: "0.5rem",
borderRadius: "05%",
border: "2px solid #555",
cursor: "pointer",
backgroundColor: "red",
},
},
},
const QuestionOptions = ({ country, correctness }) => {
const classes = useStyles();
const [myColor, setMyColor] = useState(classes.optionBt);
return (
<Box className={myColor}>
<Button
variant="contained"
onClick={() => {
changeColor();
}}
>
{country}
</Button>
</Box>
);
};
const style={
button: {
width: "80%",
color: "#fff",
height: "2.5rem",
marginTop: "0.5rem",
borderRadius: "05%",
border: "2px solid #555",
cursor: "pointer",
'&:[is-correct="true"]'{
backgroundColor: "green"
},
'&:[is-correct="false"]'{
backgroundColor: "red"
}
}
}
const QuestionOptions = ({ country, correctness }) => {
// set state for true false condition
[isCorrect, setIsCorrect] = useState(undifind)
return (
<Box
<Button
is-correct={isCorrect === true ? 'true': isCorrect === false ? 'false':undifind}
className={style.button}
variant="contained"
onClick={() => {
// if correct set to true or false is uncorrect
setIsCorrect(true);
}}
>
{country}
</Button>
</Box>
);
};
If you want only one class you can do :
const useStyles = makeStyles({
optionBt: {
width: "80%",
color: "#fff",
height: "2.5rem",
marginTop: "0.5rem",
borderRadius: "05%",
border: "2px solid #555",
cursor: "pointer",
},
optioncorrect: {
width: "80%",
color: "#fff",
height: "2.5rem",
marginTop: "0.5rem",
borderRadius: "05%",
border: "2px solid #555",
cursor: "pointer",
backgroundColor: "green",
},
optionuncorrect: {
width: "80%",
color: "#fff",
height: "2.5rem",
marginTop: "0.5rem",
borderRadius: "05%",
border: "2px solid #555",
cursor: "pointer",
backgroundColor: "red",
},
},
},
const QuestionOptions = ({ country, correctness }) => {
const classes = useStyles();
const [myColor, setMyColor] = useState(classes.optionBt);
// set state for true false condition
[correctOrNot, setCorrectOrNot] = useState(null)
return (
<Box className={myColor}>
<Button
variant="contained"
onClick={() => {
// if correct set to true or false is uncorrect
setCorrectOrNot(true);
setsetMyColor(correctOrNot ? classes.optioncorrect : classes.optionuncorrect);
}}
>
{country}
</Button>
</Box>
);
};

How can I add Adornment inside MUI InputBase?

I am trying to place MUI Adornment inside of MUI InputBase, but so far I can only get it to render outside of the input:
<InputField
id={id}
ref={ref}
error={error}
type={type}
multiline={multiline}
minRows={minRows}
inputProps={inputProps}
endAdornment={
<InputAdornment position="end">adornment</InputAdornment>
}
{...props}
/>
https://codesandbox.io/s/ecstatic-pond-yvi19?file=/src/CustomTextField.js:1320-1956
Just move below styles to InputContainer instead of InputField:
box-shadow: 0 1px 2px 0 rgba(184, 200, 224, 0.22);
border: 1px solid
${(props) => (props.error ? props.theme.palette.error.dark : "#d8e0f0")};
border-radius: 14px;
So, based on mentioned description, you have:
export const InputField = styled(InputBase)`
& > .MuiInputBase-input {
font-family: Raleway;
padding: 10px 16px;
}
`;
export const InputContainer = styled("div")`
display: flex;
flex-direction: column;
box-shadow: 0 1px 2px 0 rgba(184, 200, 224, 0.22);
border: 1px solid
${(props) => (props.error ? props.theme.palette.error.dark : "#d8e0f0")};
border-radius: 14px;
`;
`const useStyles = makeStyles((theme) => ({
inputfield: {
"& .MuiInputBase-root": {
borderRadius: 4,
backgroundColor: "#FCFCFC",
border: "1px solid #D4DEF5",
fontSize: 16,
padding: "10px 12px",
boxSizing: "border-box",
width: 280,
height: 35,
"&:hover": {
borderColor: "#1565c0",
},
},
"&.Mui-focused": {
boxShadow: `${alpha(theme.palette.primary.main, 0.25)} 0 0 0 0.2rem`,
borderColor: theme.palette.primary.main,
},
},
}));
<div className={classes.inputfield}>
<InputBase
startAdornment={
<InputAdornment position="start">
<CalendarIcon />
</InputAdornment>
}
/>
</div>`
style to MuiInputBase-root not MuiInputBase-input

How to group CSS selectors with Material-UI?

I am wondering if there is a way to group CSS selectors with Material-UI to avoid repetition, from something like this:
const useStyles = makeStyles(() => ({
root: {
backgroundColor: '#000000',
color: '#ffffff',
'&::before': {
content: '""',
position: 'absolute',
borderTop: '1px solid white',
},
'&::after': {
content: '""',
position: 'absolute',
borderTop: '1px solid white',
}
},
}));
To something that would look more or less like this?
const useStyles = makeStyles(() => ({
root: {
backgroundColor: '#000000',
color: '#ffffff',
'&::before',
'&::after': {
content: '""',
position: 'absolute',
borderTop: '1px solid white',
}
},
}));
Thanks for your help!
I actually found the solution, it was as simple as using a comma between the 2 CSS selectors:
const useStyles = makeStyles(() => ({
root: {
backgroundColor: '#000000',
color: '#ffffff',
'&::before, &::after': {
content: '""',
position: 'absolute',
borderTop: '1px solid white',
}
},
}));

Why intersection observer triggers on component mount?

Following is the sample example I was trying to understand intersection observer:
function Test(props) {
const loadingRef = useRef(null);
useEffect(() => {
let options = {
root: null,
rootMargin: '0px',
threshold: 1.0
}
let observer = new IntersectionObserver(handleIntersection, options);
observer.observe(loadingRef.current)
}, [])
function handleIntersection(x, y) {
console.log("Why this triggers on component mount?");
}
return (
<div>
<div style={{width: '100%', height: '100px', background: '#c4c4c4', borderBottom: '1px solid #f4f4f4'}}></div>
<div style={{width: '100%', height: '100px', background: '#c4c4c4', borderBottom: '1px solid #f4f4f4'}}></div>
<div style={{width: '100%', height: '100px', background: '#c4c4c4', borderBottom: '1px solid #f4f4f4'}}></div>
<div style={{width: '100%', height: '100px', background: '#c4c4c4', borderBottom: '1px solid #f4f4f4'}}></div>
<div style={{width: '100%', height: '100px', background: '#c4c4c4', borderBottom: '1px solid #f4f4f4'}}></div>
<div style={{width: '100%', height: '100px', background: '#c4c4c4', borderBottom: '1px solid #f4f4f4'}}></div>
<div style={{width: '100%', height: '100px', background: '#c4c4c4', borderBottom: '1px solid #f4f4f4'}}></div>
<div style={{width: '100%', height: '100px', background: '#c4c4c4', borderBottom: '1px solid #f4f4f4'}}></div>
<div style={{width: '100%', height: '100px', background: '#c4c4c4', borderBottom: '1px solid #f4f4f4'}}></div>
<div style={{width: '100%', height: '100px', background: '#c4c4c4', borderBottom: '1px solid #f4f4f4'}}></div>
<div style={{width: '100%', height: '100px', background: '#c4c4c4', borderBottom: '1px solid #f4f4f4'}}></div>
<div ref={loadingRef}></div>
</div>
);
}
I can't understand as to why this triggers on component mount even when target element doesn't intersect with the source element.
Your useEffect has a second argument:
useEffect(() => {
let options = {
root: null,
rootMargin: '0px',
threshold: 1.0
}
let observer = new IntersectionObserver(handleIntersection, options);
observer.observe(loadingRef.current)
}, [])
^^
||
These here.
This means that it is run when the component mounts. There is a part of the Hooks FAQ on reactjs.org that mentions this.

Changing height of react-select component

I am using the react-select component along with bootstrap v4
all of bootstraps stuff is based on 35px height it seems, the default height of the react-select component is 38px, which looks a little odd.
Any ideas how I can change the height of the component?
It is using some weird JS styling library I have never come across before. I have managed to get it to mimic the outline on focus using it, but the height escapes me, any help much appreceiated
You can play with it here
Spending hours, I end up with this to get exact 30px height of react select with border 1px:
const customStyles = {
control: (provided, state) => ({
...provided,
background: '#fff',
borderColor: '#9e9e9e',
minHeight: '30px',
height: '30px',
boxShadow: state.isFocused ? null : null,
}),
valueContainer: (provided, state) => ({
...provided,
height: '30px',
padding: '0 6px'
}),
input: (provided, state) => ({
...provided,
margin: '0px',
}),
indicatorSeparator: state => ({
display: 'none',
}),
indicatorsContainer: (provided, state) => ({
...provided,
height: '30px',
}),
};
You can add your styles to any part of the select components, take a look at the relevant docs
here is a working demo of what you ask for.
In your case the code that you need to add will look something like this:
const customStyles = {
control: base => ({
...base,
height: 35,
minHeight: 35
})
};
and in the select component:
<Select
className="basic-single"
classNamePrefix="select"
defaultValue={colourOptions[0]}
isDisabled={isDisabled}
isLoading={isLoading}
isClearable={isClearable}
isRtl={isRtl}
isSearchable={isSearchable}
name="color"
options={colourOptions}
styles={customStyles}
/>
The reason why you're not able to make it less than 36px is that the dropdownIndicator and indicatorContainer(clear icon is displayed) are taking 20px (icon) + 8px padding in all sides. If you reduce that padding, the minHeight will actually work.
dropdownIndicator: (styles) => ({
...styles,
paddingTop: 7,
paddingBottom: 7,
}),
clearIndicator: (styles) => ({
...styles,
paddingTop: 7,
paddingBottom: 7,
}),
You can play around with the padding of the dropdownIndicator and clearIndicator.
I noticed that you can't go under 30px in minHeight because of the valueContainer, unless you change its height/padding.
CSS Way
You can specify classNamePrefix and use it to override CSS styles.
<Select classNamePrefix="mySelect" />
.mySelect__value-container{
height: 35px;
}
I was barely able to make the Select component as small as 32px (in my browser) using the theme attribute. It works well when the height is greater than 45px. You can also omit the baseUnit attribute.
It didn't work for small sizes.
const theme = (theme: Theme) => ({
...theme,
spacing: {
...theme.spacing,
controlHeight: 30,
baseUnit: 0,
}
});
<Select options={props.options} theme={theme}/>
I was able to over write the menu-list's css style:
/* over write css in react-select module */
.Select__menu-list {
max-height: 120px !important;
}
If you only want to resize the box use this.
.create-select {
width: 160px;
float: right;
color: #000;
[class$="ValueContainer"] {
min-height: 28px !important;
max-height: 28px;
}
[class$="IndicatorsContainer"] {
min-height: 28px !important;
max-height: 28px;
}
[class$="-Input"] {
min-height: 28px !important;
max-height: 28px;
padding: 0px;
}
[class$="-control"] {
min-height: 28px !important;
max-height: 28px;
}
}
Cause
The .control has a min-height of 38px defined.
Fix
Change the min-height on the .control to your desired height.
const customStyles = {
control: (provided, state) => ({
...provided,
minHeight: '30px',
...additionalStyles
}),
};
In my case, I had to just set the css height property for the class
__value-container
Here is the code:
.react-select__value-container {
height: 3rem;
}
export const customStyles = {
control: (provided: Record<string, unknown>, state: any) => ({
...provided,
height: 42,
boxShadow: 'none',
borderColor: 'none',
'&:hover': {
color: '#60B3D1'
},
border: state.isFocused ? '1.5px solid #60B3D1' : '1.5px solid #cbd5e1'
}),
option: (styles: any, state: any) => ({
...styles,
color: state.isSelected ? '#FFF' : styles.color,
backgroundColor: state.isSelected ? '#60B3D1' : styles.color,
borderBottom: '1px solid rgba(0, 0, 0, 0.125)',
'&:hover': {
color: '#FFF',
backgroundColor: '#60B3D1'
}
}),
input: (base: any) => ({
...base,
'input:focus': {
boxShadow: 'none',
border: '1px solid #60B3D1'
}
}),
menuPortal: (base: any) => ({ ...base, zIndex: 9999 })
}
<Select styles={customStyles } />
This really works well for me

Resources