React-Select offers a flexible, light-weight styling framework which is a thin abstraction over simple javascript objects using emotion.
/**
* @param {Object} provided -- the component's default styles
* @param {Object} state -- the component's current state e.g. `isFocused`
* @returns {Object}
*/
function styleFn(provided, state) {
return { ...provided, color: state.isFocused ? 'blue' : 'red' };
}
Each component is keyed, and ships with default styles. The component's default style object is passed as the first argument to the function when it's resolved.
The second argument is the current state of the select, features like
isFocused
, isSelected
etc. allowing you to
implement dynamic styles for each of the components.
clearIndicator
container
control
dropdownIndicator
group
groupHeading
indicatorsContainer
indicatorSeparator
input
loadingIndicator
loadingMessage
menu
menuList
menuPortal
multiValue
multiValueLabel
multiValueRemove
noOptionsMessage
option
placeholder
singleValue
valueContainer
Spreading the provided styles into your returned object lets you extend it however you like while maintaining existing styles. Alternatively, you can omit the provided styles and completely take control of the component's styles.
const customStyles = {
option: (provided, state) => ({
...provided,
borderBottom: '1px dotted pink',
color: state.isSelected ? 'red' : 'blue',
padding: 20,
}),
control: () => ({
// none of react-select's styles are passed to <Control />
width: 200,
}),
singleValue: (provided, state) => {
const opacity = state.isDisabled ? 0.5 : 1;
const transition = 'opacity 300ms';
return { ...provided, opacity, transition };
}
}
const App = () => (
<Select
styles={customStyles}
options={...}
/>
);
In the second argument state
, you have access to selectProps
which will allow you to gain access to
your own arguments passed into the Select
body.
const customStyles = {
menu: (provided, state) => ({
...provided,
width: state.selectProps.width,
borderBottom: '1px dotted pink',
color: state.selectProps.menuColor,
padding: 20,
}),
control: (_, { selectProps: { width }}) => ({
width: width
}),
singleValue: (provided, state) => {
const opacity = state.isDisabled ? 0.5 : 1;
const transition = 'opacity 300ms';
return { ...provided, opacity, transition };
}
}
const App = () => (
<Select
styles={customStyles}
width='200px'
menuColor='red'
options={...}
/>
);
In the event that you need to rewrite a particular component, you'll also have to compose together the styling functionality. Thankfully all the requisite parts are supplied to you via props as below:
cx is an internal utility function that manages the composition of emotion style declarations, className/classNamePrefixes and additional BEM style modifiers into a selector value for each component. It has the following signature:
(prefix ?: string,
cssKey?: string,
state?: {},
className?: string) => string
Each component gets passed a getStyles method which has the following signature:
(key: string, props: Object) => stylesObject;
The key is a lowercased string value corresponding to the component that the styles apply to, i.e. option for the Option component, menuplacer for the MenuPlacer component.
The props argument is an object of relevant properties/ state values that are relevant to computing styles, i.e. isFocused or isSelected. Additional props can be added here for computation using the styles api.
In the end configuring your custom component with the correct styling functionality should look like this
import { css } from 'emotion';
const CustomOption = ({ cx, children, getStyles, innerRef, ...props }) => (
<div
ref={innerRef}
className={cx(
css(getStyles('option', props)),
{
'option': true,
'option--is-disabled': isDisabled,
'option--is-focused': isFocused,
'option--is-selected': isSelected,
}
)}
>
{children}
</div>
)
If you provide the className
prop to react-select, the SelectContainer will be given a className based on the provided value.
If you provide the classNamePrefix
prop to react-select, all inner elements will be given a className
with the provided prefix.
For example, given className='react-select-container'
and classNamePrefix="react-select"
,
the DOM structure is similar to this:
<div class="react-select-container">
<div class="react-select__control">
<div class="react-select__value-container">...</div>
<div class="react-select__indicators">...</div>
</div>
<div class="react-select__menu">
<div class="react-select__menu-list">
<div class="react-select__option">...</div>
</div>
</div>
</div>
While we encourage you to use the new Styles API, you still have the option of styling via CSS classes. This ensures compatibility with styled components, CSS modules and other libraries.
The default styles are derived from a theme object, which you can mutate like styles
.
The theme
object is available for the styles
functions as well.
primary
primary75
primary50
primary25
danger
dangerLight
neutral0
neutral5
neutral10
neutral20
neutral30
neutral40
neutral50
neutral60
neutral70
neutral80
neutral90
Copyright © Jed Watson, 2019. MIT Licensed.