I am very new in react and in react-select too. While trying to implement a custom looking component I read a lot of information, but it is not so user friendly IMHO.
I want my react-select component to show selected data in a row. Now it shows them in columns, I attached the picture.
BTW what is the purpose of name, label fields? What is the exact difference?
<Select
defaultValue={[models[0], models[1]]}
isMulti
options={models}
className="select-custom-class"
name="form-field-name"
options={models}
placeholder="Model: "
/>
I want to do some "chips style" dropdown VIA react-select. Is it possible? What style options I have to specify to round the corners like on the picture? I also want to add some static text inside the chips to be shown always: for example (regarding the pic below) "City: $here_come_the_values"
Maybe I should use another react component? The ending purpose of those dropdowns are to make filtering to the table, so I want to link them with react-bootstrap-table2.
Any help is appreciated! Thank you.
Well, actually I found how to make a nice-looking ONE LINE select component with dots in the end (like spread operator or ellipsis)
with modern react-jsx syntax without this
<Select
defaultValue={defaultValues}
closeMenuOnSelect={false}
isMulti
options={defaultValues}
components={{
IndicatorSeparator: () => null,
DropdownIndicator,
ClearIndicator,
MultiValueContainer: multiValueContainer
}}
and here we return all the values
const multiValueContainer = (props) => {
const label = props.data.label;
const allSelected = props.selectProps.value;
const index = allSelected.findIndex(selected => selected.label === label);
const isLastSelected = index === allSelected.length - 1;
const labelSuffix = isLastSelected ? ` (${allSelected.length})` : ", ";
const val = `${label}${labelSuffix}`;
return val;
};
and the style
const styles = {
control: (base, state) => ({
...base,
borderRadius: '16px',
border: '1px solid #E5F7FF',
boxShadow: 'none',
boxSizing: 'border - box',
wordWrap: "break-word",
'&:hover':
{
border: '1px solid #0679A8',
}
}),
valueContainer: (provided, state) => ({
...provided,
textOverflow: "ellipsis",
maxWidth: "90%",
whiteSpace: "nowrap",
overflow: "hidden",
display: "initial"
})
};
Related
I have a component that I use as a layout component, and in nearly all cases it works just fine, however there are one or two places where I need to be able to adjust the styles, and I would like to be able to do this by simply passing the exact styles that I need instead of adding some custom prop that will toggle them on or off.
The component looks like this:
const BlockLayout: React.FC<IProps> = ({
children,
id,
forceToBottom,
sxProps, // <--- What I want to add
}) => {
return (
<Box
id={id}
sx={[
{
backgroundColor: (theme) => theme.palette.background.paper,
mt: forceToBottom ? 'auto' : 1,
borderRadius: 0.5,
display: 'flex',
border: '1px solid rgba(0, 0, 0, 0.1)',
flexWrap: 'wrap-reverse',
},
sxProps, //<--- How I could use it?
(theme) => ({
...(theme.palette.mode === 'dark' && {
border: `1px solid ${lighten(
theme.palette.background.paper,
0.15
)}`,
}),
}),
]}
>
{children}
</Box>
)
}
How can this be done, and what type do the props need to have?
In the documentation they just cast the type to const.
You can add them as follows using the spread operator:
},
sxProps && ...sxProps,
(theme) => ({
how to change hover for all elements in react-select?
<Select
name="colors"
options={colourOptions}
className="basic-multi-select"
classNamePrefix="select"
/>
Source host: https://codesandbox.io/s/react-codesandboxer-example-8iq7b
To customise your select, you can use the props styles. All the different components you can change are listed here.
To target specifically the hover state you should use the follow pattern:
const styles = {
control: base => ({
...base,
"&:hover": {
borderColor: "red"
}
})
};
Other options are available such as the state inside each components depending of what you're trying to achieve.
If you want all the elements to behave depending of the state of the control component you will have to write something like this:
const styles = {
control: base => ({
...base,
"&:hover": {
borderColor: "red",
color: "red"
}
}),
dropdownIndicator: base => ({
...base,
color: "inherit"
}),
singleValue: base => ({
...base,
color: "inherit"
})
};
You would probably also kill the animation ease depending of the speed of the effect. You can see a live example here.
I have looked at this style guide and it really isn't written well at all. I have a whole list of all of the component pieces, but I have no idea how they nest. All I am looking to do is get the whole component to line up inline-block so it will fall on the same line as my label before it. But I cannot get the right part. Any help is appreciated. This component is so hard to style now for simple items.
Here is my code so far:
const customControlStyles = {
container : (provided, state) => ({
...provided,
width: 100,
backgroundColor: 'white',
display:'inline-block'
}),
menu : (provided, state) => ({
...provided,
width: 100,
backgroundColor: 'white',
color: 'black'
})
Country select of
autocomplete demo at material-ui
uses react-select and material-ui controls,
shows multiline text, select control changes it's dimensions when country doesn't fit in one line.
I see this behaviour at CodeSandbox when I decrease width of web browser.
How can I modify demo so that country will always fit in one line,
select control will not change it's dimensions?
TextField has props multiline, rows and rowsMax props that can be changed.
If that isn't what you need then you could add the following css to the text in the TextField so the text does not wrap:
overflow: hidden;
white-space: nowrap;
I managed this by mixing a few different things:
First create a class like so:
const useStyles = makeStyles((theme: Theme) =>
createStyles({
closed: {
flexWrap: "nowrap",
overflowX: "hidden",
},
// Add a linear gradient behind the buttons and over the Chips (if applies)
endAdornment: {
background:
"linear-gradient(90deg, rgba(255,255,255,0) 0%, rgba(255,255,255,.6) 22%, rgba(255,255,255,1) 60%)",
bottom: 0,
display: "flex",
alignItems: "center",
right: "0 !important",
paddingRight: 9,
paddingLeft: theme.spacing(2),
top: 0,
},
})
);
Then in your static function add this :
const onOpenChange = (open: boolean | null) => {
setIsOpen(open);
};
const inputStyle = clsx({
[classes.closed]: !isOpen, //only when isOpen === false
});
Finally on the Autocomplete component itself use:
classes={{ inputRoot: inputStyle, endAdornment: classes.endAdornment }}
onOpen={() => onOpenChange(true)}
onClose={() => onOpenChange(false)}
If you are wondering how to make each option be displayed in just one line with ellipsis, you can do the follow:
<Autocomplete
...
getOptionLabel={(option: any) => `${option.label} (${option.code})`}
renderOption={(option) => (
<React.Fragment>
<div style={{ textOverflow: 'ellipsis', overflow: "hidden", whiteSpace: "nowrap" }}>
{option.label} ({option.code})
</div>
</React.Fragment>
)}
...
/>
For the Country Demo example, you can check what I did here: https://codesandbox.io/s/autocomplete-with-ellipsis-i8hnw
I wanted to use react-select and ran into a whole array of issues after I changed the page background color from white to custom. (The issues aren't so evident on the white background as on react-select's github page)
I'm doing the above through styles prop as the className prop wouldn't work properly.
Here is the styles prop.
const colourStyles = {
control: styles => ({ ...styles, backgroundColor: '#023950', color: 'white', border: 0 }),
option: (styles) => {
return {
backgroundColor: '#023950',
color: 'white'
};
},
singleValue: styles => ({ ...styles, color: 'white' }),
};
Here is a list of issues and if someone could help out on how to fix them. Please refer to attached image.
Notice the gap between the dropdown and the options (when you click on the dropdown to open the options)
If you see here, http://jedwatson.github.io/react-select/, there is no gap but you also can't see the source code. Clicking the source link gives a 404.
All demos here, https://react-select.com/styles, have this gap problem.
There is a white gap (within the options itself) at the top and bottom. This is different from the gap from the dropdown as mentioned in point 1. That gap is transparent showing what's behind. This one is white.
A long text resulted in options results in the whole options box having a weird whitespace issue. Is there a way to clip the text and turn it into ellipsis instead of making the options box wider and have horizontal scroll?
Related to the above problem. How to turn off horizontal scroll. Want text clipping instead.
Regarding the problem with using className prop, the class does get applied. However only to 1 of the topmost divs. It doesn't apply to the children div, which end up staying white in backgroundColor.
react-select-styling-issues
In the following live example you will find the answer to your different points.
The first 4 points you mentioned can be solved by editing the style-in-JS as following:
const customStyles = {
control: (base, state) => ({
...base,
background: "#023950",
// match with the menu
borderRadius: state.isFocused ? "3px 3px 0 0" : 3,
// Overwrittes the different states of border
borderColor: state.isFocused ? "yellow" : "green",
// Removes weird border around container
boxShadow: state.isFocused ? null : null,
"&:hover": {
// Overwrittes the different states of border
borderColor: state.isFocused ? "red" : "blue"
}
}),
menu: base => ({
...base,
// override border radius to match the box
borderRadius: 0,
// beautify the word cut by adding a dash see https://caniuse.com/#search=hyphens for the compatibility
hyphens: "auto",
// kill the gap
marginTop: 0,
textAlign: "left",
// prevent menu to scroll y
wordWrap: "break-word"
}),
menuList: base => ({
...base,
// kill the white space on first and last option
padding: 0
})
};
For the last one, as the select is supposed to be styled through JS using className props will only put a class on the outer container as mentioned here. If you really want you can still prefix the component with classNamePrefix but it won't really help you for styling.
you should try it
const colourStyles = {
menuList: styles => ({
...styles,
background: 'papayawhip'
}),
option: (styles, {isFocused, isSelected}) => ({
...styles,
background: isFocused
? 'hsla(291, 64%, 42%, 0.5)'
: isSelected
? 'hsla(291, 64%, 42%, 1)'
: undefined,
zIndex: 1
}),
menu: base => ({
...base,
zIndex: 100
})
}
const options = [
{value: 'chocolate', label: 'Chocolate'},
{value: 'strawberry', label: 'Strawberry'},
]
<Select
// defaultValue={[colourOptions[2], colourOptions[3]]}
name="colors"
options={options}
className="basic-multi-select"
classNamePrefix="select"
styles={colourStyles}
/>
This code solves my issue
const colourStyles = {
menuList: styles => ({
...styles,
background: 'papayawhip'
}),
option: (styles, {isFocused, isSelected}) => ({
...styles,
background: isFocused
? 'hsla(291, 64%, 42%, 0.5)'
: isSelected
? 'hsla(291, 64%, 42%, 1)'
: undefined,
zIndex: 1
}),
menu: base => ({
...base,
zIndex: 100
})
}
const options = [
{value: 'chocolate', label: 'Chocolate'},
{value: 'strawberry', label: 'Strawberry'},
]
<Select
// defaultValue={[colourOptions[2], colourOptions[3]]}
name="colors"
options={options}
className="basic-multi-select"
classNamePrefix="select"
styles={colourStyles}
/>
thanks..