Closed SimeonC closed 2 years ago
Ran into this problem today. Took over an hour to tease out what generic named colour was used for what aspect of the select box (in retrospect I should have just looked at the source, it's relatively easy to see the usages there). Using semantic names would definitely be way better.
Working with the theme is just terrible.
Maybe it'll be helpful to somebody.
const colors = {
/*
* multiValue(remove)/color:hover
*/
danger: 'var(--danger)',
/*
* multiValue(remove)/backgroundColor(focused)
* multiValue(remove)/backgroundColor:hover
*/
dangerLight: 'var(--danger-light)',
/*
* control/backgroundColor
* menu/backgroundColor
* option/color(selected)
*/
neutral0: 'var(--neutral-0)',
/*
* control/backgroundColor(disabled)
*/
neutral5: 'var(--neutral-5)',
/*
* control/borderColor(disabled)
* multiValue/backgroundColor
* indicators(separator)/backgroundColor(disabled)
*/
neutral10: 'var(--neutral-10)',
/*
* control/borderColor
* option/color(disabled)
* indicators/color
* indicators(separator)/backgroundColor
* indicators(loading)/color
*/
neutral20: 'var(--neutral-20)',
/*
* control/borderColor(focused)
* control/borderColor:hover
*/
neutral30: 'var(--neutral-30)',
/*
* menu(notice)/color
* singleValue/color(disabled)
* indicators/color:hover
*/
neutral40: 'var(--neutral-40)',
/*
* placeholder/color
*/
neutral50: 'var(--neutral-50)',
/*
* indicators/color(focused)
* indicators(loading)/color(focused)
*/
neutral60: 'var(--neutral-60)',
neutral70: 'var(--neutral-70)',
/*
* input/color
* multiValue(label)/color
* singleValue/color
* indicators/color(focused)
* indicators/color:hover(focused)
*/
neutral80: 'var(--neutral-80)',
neutral90: 'var(--neutral-90)',
/*
* control/boxShadow(focused)
* control/borderColor(focused)
* control/borderColor:hover(focused)
* option/backgroundColor(selected)
* option/backgroundColor:active(selected)
*/
primary: 'var(--primary)',
/*
* option/backgroundColor(focused)
*/
primary25: 'var(--primary-25)',
/*
* option/backgroundColor:active
*/
primary50: 'var(--primary-50)',
primary75: 'var(--primary-75)',
};
@JedWatson is there any way for users to use their own, existing Emotion theme object?
I figured when we resorted to custom sub-components like a custom <Option />
, we'd be able to use our theme
object.
Edit: We ended up wrapping the parent of our react-select
component with withTheme()
and then overriding the built in theme by passing that to the custom components. Pretty clunky, but workable. It would be a lot better if React-Select didn't override the user theme by default.
@hovoodd thank you so much for posting that, it was so helpful! I'm quite meh at frontend, so I had to jam a lot of colors (ie. pink, purple) while debugging to see what would happen. I don't think I would have been able to work if you hadn't posted that!!!
My use case : I needed to make react-select work with light/dark mode in Material UI's theme system, so I'm posting my code I used to make that work for someone who has to do something similar.
import useTheme from '@material-ui/core/styles/useTheme';
const getSelectTheme = (theme) => {
return ({
/*
* multiValue(remove)/color:hover
*/
danger: 'purple',
/*
* multiValue(remove)/backgroundColor(focused)
* multiValue(remove)/backgroundColor:hover
*/
dangerLight: theme.palette.grey[200],
/*
* control/backgroundColor
* menu/backgroundColor
* option/color(selected)
*/
neutral0: theme.palette.background.default,
/*
* control/backgroundColor(disabled)
*/
neutral5: "orange",
/*
* control/borderColor(disabled)
* multiValue/backgroundColor
* indicators(separator)/backgroundColor(disabled)
*/
neutral10: 'pink',
/*
* control/borderColor
* option/color(disabled)
* indicators/color
* indicators(separator)/backgroundColor
* indicators(loading)/color
*/
neutral20: theme.palette.grey['A200'],
/*
* control/borderColor(focused)
* control/borderColor:hover
*/
// this should be the white, that's normally selected
neutral30: theme.palette.text.primary,
/*
* menu(notice)/color
* singleValue/color(disabled)
* indicators/color:hover
*/
neutral40: 'green',
/*
* placeholder/color
*/
// seen in placeholder text
neutral50: theme.palette.grey['A200'],
/*
* indicators/color(focused)
* indicators(loading)/color(focused)
*/
neutral60: 'purple',
neutral70: 'purple',
/*
* input/color
* multiValue(label)/color
* singleValue/color
* indicators/color(focused)
* indicators/color:hover(focused)
*/
neutral80: theme.palette.text.primary,
// no idea
neutral90: "pink",
/*
* control/boxShadow(focused)
* control/borderColor(focused)
* control/borderColor:hover(focused)
* option/backgroundColor(selected)
* option/backgroundColor:active(selected)
*/
primary: theme.palette.text.primary,
/*
* option/backgroundColor(focused)
*/
primary25: theme.palette.background.dark,
/*
* option/backgroundColor:active
*/
primary50: theme.palette.background.paper,
primary75: theme.palette.background.paper,
})}
export const useActivityLogDataForm = ({
const theme = useTheme()
const formThemeColors = getSelectTheme(theme)
return (<Select options={options}
theme={theme => ({
...theme,
colors: {
...formThemeColors
}})}
/>)
(A demo of working react-selects should be on the forms w/light and dark themes on https://app.betterself.io/demo later tonight)
Did anything ever come of this @JedWatson? Trying to deal with overriding the theme to support a dark mode.
Super helpful resource here: https://stackoverflow.com/a/60993034/3198983
Especially when you don't know on your back-end which theme will be loaded, for example when using Tailwindcss
My final approach has been to inject styles for dark mode using jsx:
id
and a classNamePrefix
: <Select
id={this.props.id}
classNamePrefix={this.props.id}
...
/>
I inject the styles for dark mode using jsx (this works by default in Next.js, I'm not sure what the requirements are for other stacks):
<style global jsx>{`
@media (prefers-color-scheme: dark) {
#${this.props.id} .${this.props.id}__control {
background-color: #6b727f !important;
border-color: #2b2b2b00;
padding: 4px;
}
#${this.props.id} .${this.props.id}__placeholder {
color: #d1d5db !important;
}
#${this.props.id} .${this.props.id}__multi-value {
background-color: slategray;
color: #fff;
}
#${this.props.id} .${this.props.id}__input-container {
color: #d1d5db;
border: none;
}
#${this.props.id} .${this.props.id}__input-container:focus {
border: none !important;
outline: none !important;
}
#${this.props.id} .${this.props.id}__input:focus {
border: none !important;
outline: none !important;
}
#${this.props.id} .${this.props.id}__input::after {
border: none !important;
display: none;
}
#${this.props.id} .${this.props.id}__multi-value__label {
color: #fff;
}
#${this.props.id} .${this.props.id}__menu {
background-color: #2d3748;
}
#${this.props.id} .${this.props.id}__option {
color: #fff;
}
#${this.props.id} .${this.props.id}__option--is-focused {
background-color: slategray;
}
}
`}</style>
In my case, I detect the user preference using a media query. However, you might be using a class set higher up the hierarchy; in that case, you could do:
<style global jsx>{`
body.dark #${this.props.id} .${this.props.id}__control {
...
I've been working with integrating ReactSelect with our own theming library and I've come across a few issues.
ThemeProvider
I have acolors
key with a different format that means that I end up having a weird hybrid of the colors object passed down and this causes issues. It would be better for react select to pass downtheme={{ 'react-select': theme }}
instead oftheme={theme}
as this allows prevents collisions.primary
primary75
primary50
andprimary25
- I can't control what colors are used in what situations so it would make more sense to use named values likemenuBorder
activeBackground
activeText
etc so we know what we are theming and what it affects.I know this is a pretty opinionated and technically I can work around this by replacing all Components with custom ones but this feels like it defeats the purpose of a "theme" option. To me, it makes more sense to name the theme colors as for what they are actually used for rather than having to figure out that
primary25
is used only for when an element is "focused". Another issue is that due to us usingneutral0
for both the selected text color and the control background I can't theme these individually, not to mention there is no text color available for when a value is focussed so using darker colors there won't work - for example when implementing a Dark Theme.