Skip to content

Instantly share code, notes, and snippets.

@Cloudo
Created June 11, 2020 18:37
Show Gist options
  • Save Cloudo/761852856a9b92c783247b148f0241ef to your computer and use it in GitHub Desktop.
Save Cloudo/761852856a9b92c783247b148f0241ef to your computer and use it in GitHub Desktop.
import ReactSelect, { Props } from 'react-select'
import { customStyles, getTheme } from './styles'
import { ReactNode, useMemo } from 'react'
import { FormControl } from '../FormControl'
export const SelectRaw = (props: Props) => {
const theme = useMemo(() => getTheme(props.error), [props.error])
return (
<ReactSelect
classNamePrefix="react-select"
styles={customStyles}
theme={theme}
isSearchable={false}
placeholder=""
{...props}
/>
)
}
SelectRaw.defaultProps = {
noOptionsMessage: () => ':(',
}
export const Select = (
props: Props & {
name: string
label?: ReactNode
isRequired?: boolean
error?: string
}
) => {
const { name, error, label, isRequired, isInvalid, mb, ...other } = props
return (
<FormControl
name={name}
label={label}
error={error}
isInvalid={isInvalid}
isRequired={isRequired}
mb={mb}
>
<SelectRaw error={error} inputId={name} {...other} />
</FormControl>
)
}
import t from 'theme'
import { StylesConfig } from 'react-select'
const red = t.colors.red.alert
export const customStyles: StylesConfig = {
placeholder: (provided) => ({ ...provided, color: t.colors.gray['500'] }),
valueContainer: (provided) => ({ ...provided, paddingLeft: '0.75rem' }),
menuList: (provided) => {
return {
...provided,
padding: 0,
'& > .react-select__option:first-child': {
borderTopLeftRadius: 4,
borderTopRightRadius: 4,
},
'& > .react-select__option:last-child': {
borderBottomLeftRadius: 4,
borderBottomRightRadius: 4,
},
}
},
control: (provided, state) => {
const errorStyling = state.selectProps.error
? {
boxShadow: `0 0 0 1px ${red}`,
}
: {}
const disabledStyling = state.isDisabled
? {
backgroundColor: t.colors.white,
opacity: 0.4,
'&:hover': { cursor: 'not-allowed' },
}
: {}
return {
...provided,
...errorStyling,
...disabledStyling,
}
},
// @ts-ignore
container: (provided, state) => {
const disabledStyling = state.isDisabled
? {
pointerEvents: 'inherit',
}
: {}
return {
...provided,
fontSize: t.fontSizes.sm,
// fontWeight: t.fontWeights.medium,
color: t.colors.gray['900'],
...disabledStyling,
}
},
option: (provided, state) => {
return {
...provided,
backgroundColor: state.isSelected
? t.colors.blue['100']
: provided.backgroundColor,
color: t.colors.gray['900'],
}
},
menu: (provided) => ({
...provided,
boxShadow: t.shadows.select,
borderRadius: t.radii.lg,
}),
indicatorSeparator: () => ({
opacity: 0,
}),
}
export const getTheme = (isError?: boolean) => (rctheme) => {
const errorStyling = isError
? {
primary: red,
neutral10: red,
neutral30: red,
neutral20: red,
neutral60: red,
}
: {}
return {
...rctheme,
borderRadius: t.radii.lg,
colors: {
...rctheme.colors,
neutral20: t.colors.gray['200'],
neutral30: t.colors.gray['200'],
neutral50: t.colors.gray['900'],
primary25: t.colors.gray['50'],
primary50: t.colors.gray['50'],
primary75: t.colors.gray['200'],
primary: t.colors.gray['200'],
...errorStyling,
},
spacing: {
...rctheme.spacing,
controlHeight: 48,
menuGutter: 12,
},
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment