How to create dropdown list with description in React - reactjs

I am trying to create a dropdown list with description in React. For reference you can see the image below:
Is there any other way using bootstrap or Material-UI so I can achieve this?
I am using react-select npm package for dropdown list. you can find live link and code below:
https://codesandbox.io/embed/react-select-selected-option-background-color-forked-jpu99?fontsize=14&hidenavigation=1&theme=dark
const colourOptions = [
{ value: "red", label: "Red" ,description:"Test description for red"},
{ value: "green", label: "Green", description:"Test description for green" },
{ value: "blue", label: "Blue", description:"Test description for blue" }
];
//for styling
const colourStyles = {
option: (styles, { data, isDisabled, isFocused, isSelected }) => {
// const color = chroma(data.color);
console.log({ data, isDisabled, isFocused, isSelected });
return {
...styles,
backgroundColor: isFocused ? "#00A3BE" : "#191D2F",
font: "Segoe UI",
color: "#F9FAFC"
};
}
};
export default () => (
<Select
defaultValue={colourOptions[1]}
label="Single select"
options={colourOptions}
styles={colourStyles}
/>
);

You can override the Option component and provide your own Option that can display both title and description:
import Select, { components } from "react-select";
const colourStyles = {
option: (styles, { data, isDisabled, isFocused, isSelected }) => {
return {
...styles,
backgroundColor: isFocused ? "#00A3BE" : "",
color: isFocused ? "#F9FAFC" : "#191D2F",
display: "flex",
paddingLeft: 0,
"& .left": {
display: "flex",
justifyContent: "center",
width: 60,
marginTop: 3
},
"& .right": {
width: "100%"
},
"& .right > .title": {
display: "block",
margin: "5px 0"
}
};
}
};
const Option = (props) => {
return (
<components.Option {...props}>
<div className="left">{props.isSelected ? "✔" : ""}</div>
<div className="right">
<strong className="title">{props.data.label}</strong>
<div>{props.data.description}</div>
</div>
</components.Option>
);
};
export default () => (
<Select
defaultValue={colourOptions[1]}
label="Single select"
options={colourOptions}
styles={colourStyles}
components={{ Option }}
/>
);
Live Demo

Related

React component not passing value to correct component

I have a simple React app that uses react-dnd to build a grid of draggable squares that have an initial color and text value and two components to change the color and change the text.
The color change (via ColorPicker2, using react-color library) works okay. The text change (using TextInput from #carbon/react) doesn't work as desired.
I thought I was applying the same logic with both components, but whilst the color-picker updates the color and retains that color when the square is moved, the text seems to render inside the TextInput and not the square itself and I can't figure out the logical difference.
The Code Sandbox is here: https://codesandbox.io/s/wild-waterfall-z8s1de?file=/src/App.js
This is the current code:
ColorPicker2.js
import "./styles.css";
import React from "react";
import { BlockPicker } from "react-color";
const presetColors = ["#9E9E9E", "#4CAF50", "#FFEB3B", "#F44336", "#2196F3"];
const ColorPicker2 = (props) => {
const handleChangeComplete = (color) => {
if (props.updateColor) {
props.updateColor(color.hex);
}
};
return (
<div className="palette">
<BlockPicker
className="palette"
colors={presetColors}
onChangeComplete={handleChangeComplete}
presetColors={Object.values(presetColors)}
color={props.currentColor}
/>
</div>
);
};
export default ColorPicker2;
App.js
import "./styles.css";
import React, { useState } from "react";
import { DndProvider, useDrag, useDrop } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import edit from "./edit.svg";
import palette from "./palette.svg";
import ColorPicker2 from "./ColorPicker2";
import { TextInput } from "#carbon/react";
const DndWrapper = (props) => {
return <DndProvider backend={HTML5Backend}>{props.children}</DndProvider>;
};
const DraggableSquare = ({ index, text, color, moveSquare }) => {
const [{ isDragging }, drag] = useDrag({
type: "square",
item: { index },
collect: (monitor) => ({
isDragging: monitor.isDragging()
})
});
const [isHovered, setIsHovered] = useState(false);
const [, drop2] = useDrop({
accept: "square",
drop: (item, monitor) => {
const didDrop = monitor.didDrop();
if (!didDrop) {
moveSquare(item.index, index);
}
},
hover: (item, monitor) => {
setIsHovered(monitor.isOver());
},
collect: (monitor) => {
setIsHovered(monitor.isOver());
}
});
const [isPaletteOpen, setIsPaletteOpen] = useState(false);
const [isTextInputOpen, setIsTextInputOpen] = useState(false);
const [newText, setNewText] = useState(text);
const opacity = isDragging ? 0.5 : 1;
return (
<div className="square-div" ref={drop2}>
<div
className="grey-square"
ref={drag}
style={{
opacity,
backgroundColor: color,
width: "200px",
height: "200px",
textAlign: "center",
paddingTop: "30px",
position: "relative",
border: isHovered ? "3px solid blue" : "none",
borderRadius: "5px",
}}
onMouseOver={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
<img
src={edit}
onClick={() => {
setIsTextInputOpen(!isTextInputOpen);
if (!isTextInputOpen) {
moveSquare(index, newText, color, undefined);
}
}}
style={{
width: "15px",
height: "15px",
position: "absolute",
right: "5px",
top: "5px"
}}
alt="edit icon"
/>
{isTextInputOpen && (
<TextInput
id="newtext"
labelText=""
value={newText}
onChange={(e) => setNewText(e.target.value)}
/>
)}
<img
src={palette}
onClick={() => setIsPaletteOpen(!isPaletteOpen)}
style={{
width: "15px",
height: "15px",
position: "absolute",
right: "25px",
top: "5px"
}}
alt="palette icon"
/>
{isPaletteOpen && (
<ColorPicker2
className="palette"
currentColor={color}
updateColor={(newColor) =>
moveSquare(index, index, newText, newColor)
}
/>
)}
</div>
</div>
);
};
const Grid = () => {
const [grid, setGrid] = useState([
{ text: "1", color: "grey" },
{ text: "2", color: "grey" },
{ text: "3", color: "grey" },
{ text: "4", color: "grey" },
{ text: "5", color: "grey" },
{ text: "6", color: "grey" },
{ text: "7", color: "grey" },
{ text: "8", color: "grey" },
{ text: "9", color: "grey" },
{ text: "10", color: "grey" },
{ text: "11", color: "grey" },
{ text: "12", color: "grey" },
{ text: "13", color: "grey" },
{ text: "14", color: "grey" },
{ text: "15", color: "grey" }
]);
const moveSquare = (fromIndex, toIndex, newText, newColor) => {
setGrid((grid) => {
const newGrid = [...grid];
const item = newGrid[fromIndex];
newGrid.splice(fromIndex, 1);
newGrid.splice(toIndex, 0, {
text: newText || item.text,
color: newColor || item.color
});
return newGrid;
});
};
return (
<>
<DndWrapper>
<div
className="grid"
style={{
display: "grid",
gridTemplateColumns: "repeat(5, 190px)",
gridGap: "15px",
gridColumnGap: "20px",
gridRowGap: "10px",
position: "absolute"
}}
>
{grid.map((square, index) => (
<DraggableSquare
key={index}
index={index}
text={square.text}
color={square.color}
moveSquare={moveSquare}
//grid={grid}
//setGrid={setGrid}
/>
))}
</div>
</DndWrapper>
</>
);
};
export default Grid;
Any thoughts from fresh eyes would be helpful.
I think this is just a simple issue with using index as the key while mapping. Adjusting your code pen to have a unique key fixed it for me but the input text is not being saved anywhere so returned to the default text={square.text} when moved as expected.
Unique Id in objects:
const [grid, setGrid] = useState([
{ text: "1", color: "grey", id: crypto.randomUUID() },
{ text: "2", color: "grey", id: crypto.randomUUID() },
{ text: "3", color: "grey", id: crypto.randomUUID() },...])
Adding key to mapped object:
{grid.map((square, index) => (
<DraggableSquare
key={square.id}
index={index}
text={square.text}
color={square.color}
moveSquare={moveSquare}
//grid={grid}
//setGrid={setGrid}
/>}

Trying to get Yup validation working on Controller and custom components based on react-select for overall form validity and error style

New to React here so I do appreciate any insight others may have on this.
I am trying to validate a custom select component based on react-select. I am having trouble with the following:
Showing the error styling for the select field while also having it work for the overall form validity. I am using react-hook-form and Yup validation.
I have a custom component here called CreditAppCustomSelect:
import { TextField } from '#mui/material';
import Image from 'next/image';
import React from 'react';
import Select, { components } from 'react-select';
import Arrow from '../../assets/images/icon/Icon.png';
export interface CustomStyles {
isHover: boolean;
isFocused: boolean;
isSelected: boolean;
}
const colourStyles = (isError: boolean) => ({
control: (styles: object, { isHover, isFocused }: CustomStyles) => {
return {
...styles,
borderRadius: '0px',
backgroundColor: 'white',
border: isFocused
? '0.1875rem solid #00B0C7'
: isError
? '0.1875rem solid #F6AE55'
: '0.1875rem solid #000000',
boxShadow: isHover ? '0.1875rem solid #00B0C7' : undefined,
'&:hover': {
border: isHover ? '0.1875rem solid #00B0C7' : undefined,
},
fontFamily: 'Avenir',
fontStyle: 'normal',
fontWeight: 500,
fontSize: '1.25rem',
/* or 30px */
color: '#969696',
textTransform: 'capitalize',
'#media only screen and (max-width:991px)': {
// #ts-ignore
...styles['#media only screen and (max-width:991px)'],
height: '3rem',
},
minHeight: '3rem',
};
},
dropdownIndicator: (
styles: object,
{ isFocused, isSelected, isHover }: CustomStyles
) => {
return {
color: '#242424',
marginInline: '0.2rem',
width: '0.625rem',
minWidth: '0.5rem',
};
},
option: (styles: object, { isFocused, isSelected }: CustomStyles) => {
return {
...styles,
backgroundColor: isFocused ? '#BBE8EE' : undefined,
color: 'black',
cursor: 'default',
'&:active': {
backgroundColor:
isSelected || isFocused ? 'rgba(176, 117, 251, 0.3)' : undefined,
},
};
},
menu: (styles: object) => {
return {
...styles,
boder: '0.0625rem solid #242424',
outline: '0.0625rem solid #242424',
color: '#242424',
// top: "0rem",
margin: '0 0.0625rem',
boxSizing: 'border-box',
width: 'calc(100% - 2px)',
borderRadius: '0px',
zIndex: 99,
fontFamily: 'Avenir',
fontStyle: 'normal',
fontWeight: 500,
fontSize: '1.25rem',
textTransform: 'capitalize',
};
},
input: (styles: object) => ({
...styles,
fontSize: '1.25rem',
}),
placeholder: (styles: object) => {
return {
...styles,
fontFamily: 'Avenir',
fontStyle: 'normal',
fontWeight: 500,
fontSize: '1.25rem',
/* or 30px */
color: '#969696',
textTransform: 'capitalize',
};
},
container: (
styles: object,
{ isFocused, isSelected, isHover }: CustomStyles
) => {
return {
...styles,
// borderRadius: "4px",
outline: 'none',
height: '3rem',
};
},
singleValue: (styles: object, { isFocused, isSelected }: CustomStyles) => {
return {
...styles,
fontSize: '1.25rem',
color: '#211e3b',
};
},
valueContainer: (styles: object) => {
return {
...styles,
paddingLeft: '0.75rem',
};
},
});
const CreditAppCustomSelect = (props: any) => (
<div className='credit-app-select-container'>
<label className={props.isError ? 'error' : ''}>
{props.label}
<Select
{...props}
styles={colourStyles(props.isError)}
components={{
IndicatorSeparator: () => null,
// eslint-disable-next-line #next/next/no-img-element
DropdownIndicator: (props) => (
<components.DropdownIndicator {...props}>
<Image src={Arrow} alt='down' />
</components.DropdownIndicator>
),
}}
isSearchable={false}
placeholder={props.placeholder}
onChange={props.onChange}
value={props.value} // This can be set like this as a result of the change
/>
{props.isError ? <span>{props.message}</span> : ''}
</label>
</div>
);
export default CreditAppCustomSelect;
in my form schema I have the following - one works for overall form validity and the other works for error styling - I know I can't use both so not sure what to do?:
// this works for overall form validity based on having a selected value (isValid)
employeeNumbers: Yup.object().shape({
label: Yup.string().nullable().required('Required'),
value: Yup.string().nullable().required('Required'),
}),
// the following works for the error styling and message but I know I can't do both this and the above
// employeeNumbers: Yup.string().nullable().required('Required'),
I am using a Controller around the CreditAppCustomSelect component:
<Controller
defaultValue=''
control={control}
{...register('employeeNumbers', { required: true })}
render={({ field }: any) => (
<CreditAppCustomSelect
{...field}
label='Number of Employees/Contractors'
name='employeeNumbers'
placeholder='Select range'
isError={
errors.employeeNumbers &&
errors.employeeNumbers.type === 'required'
}
message={'Required'}
options={numberEmployeesOptions}
/>
)}
/>
The options look like this
const numberEmployeesOptions = [
{ label: '1 - 4', value: '1 - 4' },
{ label: '5 - 9', value: '5 - 9' },
{ label: '10 - 19', value: '10 - 19' },
{ label: '20 - 49', value: '20 - 49' },
{ label: '50 - 99', value: '50 - 99' },
{ label: '100+', value: '100+' },
];
in the interface for the form I have the following for employee numbers:
employeeNumbers: { label: string; value: string };
I have not posted the entire form since it is so long but I am using mode:onBlur for the overall form and working in tsx files. Just trying to reconcile how I can achieve both form validity as well as error styling. I have searched for related issues in StackOverflow and I know there probably are solutions but have not yet managed to solve this and have been spinning my wheels for a while.
Thanks for any suggestions anyone may have!

Material ui TextField Label text problem, why is not label text visible?

I learn ReactJs and material-ui and now I have a problem with material TextField.
The code below creates this:
The problem I have is that the label="Tag Name" does not show the label text in the TextField.
When I click the TextField it looks like this:
The label label="Tag Name" should be visible in the TextFiled like this:
Please advice what is wrong?
import React from 'react';
import { connect } from 'react-redux';
import Dots from 'react-activity/lib/Dots';
import 'react-activity/lib/Dots/Dots.css';
import { Button, FormControl, InputLabel, Select, TextField, MenuItem } from '#material-ui/core';
import { withStyles } from '#material-ui/core/styles';
import { compose } from 'recompose';
import { changeDisplayName } from '../../../../../redux/userData/user.actions';
const styles = theme => ({
root: {
backgroundColor: theme.palette.primary.light,
// textAlign: 'center',
padding: '10px',
margin: 'auto',
display: 'flex',
justifyContent: 'space-around',
},
tagTextField: {
textAlign: 'left',
padding: '8px',
margin: '5px',
border: 'none',
borderRadius: '2px',
fontSize: '12pt',
// background: 'blue',
},
input: {
background: 'white',
color: 'black',
},
changeNameButton: {
backgroundColor: theme.palette.primary.main,
boxShadow: theme.shadows[5],
border: 'none',
borderRadius: '2px',
color: 'white',
margin: '5px',
padding: '8px',
cursor: 'pointer',
'&:hover': {
cursor: 'pointer',
backgroundColor: theme.palette.primary.dark,
},
'&:active': {
cursor: 'pointer',
backgroundColor: theme.palette.primary.dark,
},
'&:disabled': {
cursor: 'default',
color: 'gray',
backgroundColor: theme.palette.primary.main,
},
},
});
class AddTag extends React.Component {
constructor(props) {
super(props);
this.state = {
tagName: '',
categoryName: 'aaa',
categoryNames: ['aaaa', 'bbbb', 'cccc', 'dddd', 'fff'],
};
}
submit = () => {
// let todoListCopy = [...this.state.todoList];
// todoListCopy.push({
// todoName: this.state.todoName,
// userName: this.state.userName,
// });
// this.setState({
// todoName: '',
// todoList: todoListCopy,
// });
};
changeCategoryName = categoryName => {
this.setState({
categoryName,
});
};
changeTagName = tagName => {
this.setState({
tagName,
});
};
render() {
const { classes } = this.props;
const { tagName, categoryName, categoryNames } = this.state;
return (
<div className={classes.root}>
<TextField
className={classes.tagTextField}
id="outlined-basic"
label="Tag Name"
variant="outlined"
value={tagName}
onChange={e => this.changeTagName(e.target.value)}
autoComplete="off"
InputProps={{
className: classes.input,
}}
/>
<FormControl>
<InputLabel id="demo-simple-select-helper-label">Category</InputLabel>
<Select
labelId="demo-simple-select-helper-label"
id="demo-simple-select-helper"
value={categoryName}
onChange={e => this.changeCategoryName(e.target.value)}
>
{categoryNames &&
categoryNames.map((element, index) => {
return (
<MenuItem value={element} key={index}>
{element}
</MenuItem>
);
})}
</Select>
</FormControl>
<Button
className={classes.changeNameButton}
onClick={() => this.submit()}
variant="contained"
color="primary"
disabled={!tagName && !categoryName}
>
Save Tag
</Button>
</div>
);
}
}
const mapDispatchToProps = dispatch => ({
changeUserDisplayName: displayName => dispatch(changeDisplayName(displayName)),
});
const mapStateToProps = state => {
return {
savingDisplayName: state.user.isSavingDisplayName,
newDisplayName: state.user.displayName,
changeDisplayNameErr: state.user.changeDisplayNameErrMsg,
};
};
const enhance = compose(withStyles(styles), connect(mapStateToProps, mapDispatchToProps));
export default enhance(AddTag);
There is prop for this placeholder

Styling of disabled and enabled button

I have one button (from material ui) which is greyed out if the date is not set. If you set a date it should be clickable. I want to style the button for those cases.
This is the button:
<Button style={{
marginTop: 10
}} disabled={this.props.date ? false : true} onClick={this.sendRequest} variant="contained" color="primary">Send Request</Button>
Those are my button-classes for styling:
'.enabledButton': {
background: '#ffb303!important',
},
'.defaultButton': {
background: '#cfcfcf!important',
},
I tried to apply it in the false / true check. If its true it should apply the .enabledButton and for the false case it should apply the .defaultButton.
Can someone help me with it?
Thank you very much!
You can override css which is injected by material ui
you can use rule name
Both options are covered in the working demo here
Code snippet
const useStyles = makeStyles(theme => ({
root: {
"& > *": {
margin: theme.spacing(1)
},
// using classname
"& .Mui-disabled": {
background: "#ffb303"
}
}
}));
const useStyles2 = makeStyles(theme => ({
root: {
"& > *": {
margin: theme.spacing(1)
},
"&$disabled": {
background: "rgba(0, 0, 0, 0.12)",
color: "red",
boxShadow: "none"
}
},
disabled: {}
}));
export default function ContainedButtons(props) {
const classes = useStyles();
const classes2 = useStyles2();
return (
<>
<div className={classes.root}>
<Button
variant="contained"
color="primary"
disabled={props.date ? false : true}
>
Button (using css name)
</Button>
</div>
<div>
<Button
classes={{ root: classes2.root, disabled: classes2.disabled }}
variant="contained"
color="primary"
disabled={props.date ? false : true}
>
Button (using rule name)
</Button>
</div>
</>
);
}
In your case you can use classes atribute by material-ui. I made you a full example using a functional component:
import React from 'react'
import Button from '#material-ui/core/Button'
import { makeStyles } from '#material-ui/core/styles'
const useStyles = makeStyles(theme => ({
button: {
backgroundColor: '#ffb303',
},
disabledButton: {
backgroundColor: '#cfcfcf',
}
}))
export default () => {
const [disabled, setDisabled] = React.useState(false)
const classes = useStyles()
const toggleDisabled = () => setDisabled(prev => !prev)
return (
<>
<Button
disabled={disabled}
onClick={toggleDisabled}
classes={{
root: classes.button,
disabled: classes.disabled
}}
variant="contained"
>
Toggle
</Button>
<Button
disabled={!disabled}
onClick={toggleDisabled}
classes={{
root: classes.button,
disabled: classes.disabled
}}
variant="contained"
>
Toggle
</Button>
</>
)
}
const useStyles = makeStyles({
enabledButton: {
background: '#ffb303!important',
'&:disabled': {
background: '#cfcfcf!important',
}
},
});
function Componenet() {
const classes = useStyles();
...
...
return (
<Button
className={classes.enabledButton}
disabled={!this.props.date}
onClick={this.sendRequest}
variant="contained"
color="primary"
>
Send Request
</Button>
);
}
You can try it in 2 ways:
1st Method:
You can add the styles directly and do the validation like this (but its not preferrable to inject styles directly)
<div className={classes.root}>
<Button variant="contained">Default</Button>
<Button style={{
marginTop: 10,
backgroundColor: `${this.props.date ? '#ffb303':'#cfcfcf'}`
}} disabled={this.props.date ? false : true}
variant="contained" color="primary">Send Request</Button>
2nd Method:
You can use styles and do the validation in your code.
const useStyles = makeStyles((theme) => ({
enabledButton: {
backgroundColor: '#ffb303',
},
defaultButton: {
backgroundColor: '#cfcfcf',
},
}));
const classes = useStyles();
<div className={classes.root}>
<Button variant="contained">Default</Button>
<Button style={{
marginTop: 10,
}} disabled={this.props.date ? false : true}
className={this.props.date ? classes.enabledButton : classes.defaultButton}
variant="contained" color="primary">Send Request</Button>
simple and easy to use my snippet:
<TextField
fullWidth={fullWidth}
disabled={disabled}
onChange={onChange}
InputProps={{
classes: {
underline: classes.underline,
disabled: disabled ? classes.disabled : {},
},
}}
{...rest}
/>
)
classes
const useStyles = makeStyles((theme) => ({
label: {
paddingRight: theme.spacing(1),
fontFamily: 'Montserrat Light',
fontSize: `0.875rem`,
},
underline: {
marginTop: 0,
marginBottom: 0,
fontFamily: 'Montserrat Light',
color: `${$white}`,
fontSize: `0.875rem`,
'&::after': {
borderBottom: `1px solid ${$white}`,
},
'&::before': {
borderBottom: `1px solid rgba(255, 255, 255, 0.36)`,
},
'&:hover&::before': {
borderBottom: `1px solid ${$white}`,
},
},
disabled: {
'&:hover&::before': {
borderBottom: `1px dotted rgba(255, 255, 255, 0.36)`,
},
},
}))

react-autosuggest how to style input and autosuggestion when using along with Material-ui

I am using react-autosuggest in my Material-UI component to get suggestions when user types. And just not able to style the input field and the suggestions text.
Probably I am missing something basic here, and any guidance will be immensly helpful. The official dox of react-autosuggest is here for using the theme technique that uses react-themeable. But I could not implement that in my Material-UI component.
The below is my code that I am trying with.
import React, { useEffect, useState } from 'react'
import PropTypes from 'prop-types'
import { makeStyles } from '#material-ui/core/styles'
import Autosuggest from 'react-autosuggest';
import { defaultTheme } from 'react-autosuggest/dist/theme';
const useStyles = makeStyles(theme => ({
container: {
margin: 'auto',
backgroundColor: theme.background.default,
},
innerTableContainer: {
height: 'calc(100vh - 190px)',
borderRadius: theme.shape.borderRadius,
backgroundColor: theme.background.paper,
},
react_autosuggest__container: {
"position": "relative",
"width": "440px",
},
react_autosuggest__input: {
"width": "240px",
"height": "30px",
"padding": "10px 20px",
"fontFamily": "Helvetica, sans-serif",
"fontWeight": "300",
"fontSize": "16px",
"border": "1px solid #aaa",
"borderRadius": "4px"
},
react_autosuggest__input__focused: {
"outline": "none"
},
react_autosuggest__input__open: {
"borderBottomLeftRadius": "0",
"borderBottomRightRadius": "0"
},
react_autosuggest__suggestions_container__open: {
"display": "block",
"position": "absolute",
"top": "51px",
"width": "280px",
"border": "1px solid #aaa",
"backgroundColor": "#fff",
"fontFamily": "Helvetica, sans-serif",
"fontWeight": "300",
"fontSize": "16px",
"borderBottomLeftRadius": "4px",
"borderBottomRightRadius": "4px",
"zIndex": "2"
},
react_autosuggest__suggestions_list: {
"margin": "0",
"padding": "0",
"listStyleType": "none"
},
react_autosuggest__suggestion: {
"cursor": "pointer",
"padding": "10px 20px"
},
react_autosuggest__suggestion__highlighted: {
"backgroundColor": "#ddd"
}
}))
const GithubMostPopularList = () => {
const classes = useStyles()
const [value, setValue] = useState('')
const [suggestions, setSuggestions] = useState([])
const onChange = (event, { newValue, method }) => {
setValue(newValue)
};
const onSuggestionsFetchRequested = ({ value }) => {
setSuggestions(getSuggestions(value))
};
const onSuggestionsClearRequested = () => {
setSuggestions([])
};
const inputProps = {
placeholder: "Start typing your city name",
value,
onChange: onChange,
};
return (
<div className={classes.container}>
<div className={classes.react_autosuggest__container} >
<Autosuggest
suggestions={suggestions}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
onSuggestionsClearRequested={onSuggestionsClearRequested}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
inputProps={inputProps}
/>
</div>
)}
</div>
)
}
export default GithubMostPopularList
I have also tried this solution given in one of Github issue
<Autosuggest
//misc extra props I've cut out for brevity
theme={{
...defaultTheme,
...{
container: {
...defaultTheme.container,
display: 'visible',
width: '340px',
},
//more overrides
}
}}
/>
But in this case the component is not compiling at all.
Answering my own question.
I was able to solve it as below, the useStyles = makeStyles() portion remains the same and the below is how to change the defulat theme of react-autosuggest.
import { defaultTheme } from 'react-autosuggest/dist/theme';
....
....
const GithubMostPopularList = () => {
.....
.....
return (
<div className={classes.container}>
{console.log('GITHUB USER ', JSON.stringify(globalStore.githubUser))}
<div className={classes.tableAndFabContainer}>
{globalStore.loading ? (
<div className={classes.spinner}>
<LoadingSpinner />
</div>
) : (
<div className={classes.table}>
{console.log('VALUE IS ', value)}
<div className={classes.inputandButtonContainer} >
<Autosuggest
suggestions={suggestions}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
onSuggestionsClearRequested={onSuggestionsClearRequested}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
inputProps={inputProps}
theme={{
...defaultTheme,
container: classes.react_autosuggest__container,
input: classes.react_autosuggest__input,
inputOpen: classes.react_autosuggest__input__open,
inputFocused: classes.react_autosuggest__input__focused,
suggestionsContainer: classes.react_autosuggest__suggestions_container,
suggestionsContainerOpen: classes.react_autosuggest__suggestions_container__open,
suggestionsList: classes.react_autosuggest__suggestions_list,
suggestion: classes.react_autosuggest__suggestion,
suggestionHighlighted: classes.react_autosuggest__suggestion__highlighted,
}
}
/>
</div>
</div>
)}
</div>
</div>
)
}
export default GithubMostPopularList
Not sure about what you did. This is what I did, and it works well :
One component with the definition of your styling, and the Autosuggest component you render :
import { makeStyles } from '#material-ui/styles';
const useStyles = makeStyles({
container: {
position: "relative",
},
input: {
width: "240px",
height: "30px",
width: '80%',
padding: "10px 20px",
fontFamily: "Helvetica, sans-serif",
fontWeight: "bold",
fontSize: "16px",
border: "1px solid #aaa",
borderRadius: "4px"
},
inputFocused: {
outlineStyle: "none"
}
// add other styling here...
});
const MyAutosuggest = (props) => {
const inputProps = {
placeholder: 'Type a programming language',
value: props.value,
onChange: props.onChange
};
const theme = useStyles();
return(
<Autosuggest
suggestions={props.suggestions}
onSuggestionsFetchRequested={props.onSuggestionsFetchRequested}
onSuggestionsClearRequested={props.onSuggestionsClearRequested}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
inputProps={inputProps}
theme={theme}
/>
)
}
I import MyAutosuggest in the component where I implement autosuggest :
import MyAutosuggest from './Autosuggest';
<MyAutosuggest
value={this.state.value}
onChange={this.onChange}
suggestions={this.state.suggestions}
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
/>

Resources