Chakra-React-Select
This contains the[`chakra-react-select`](https://github.com/csandman/chakra-react-select#chakra-react-select), a wrapper for the popular react component [react-select](https://react-select.com/home) made using the UI library Chakra UI. It is customized with the Tidal design components, but full documentation can be found https://github.com/csandman/chakra-react-select#chakra-react-select.
This contains thechakra-react-select
, a wrapper for the popular react component react-select made using the UI library Chakra UI. It is customized with the Tidal design components, but full documentation can be found https://github.com/csandman/chakra-react-select#chakra-react-select
For complete documentation, please refer to thechakra-react-select
repo.
Thank-you @csandman
for creating this wrapper and the great documentation.
CodeSandbox Examples:#
TypeScript: https://codesandbox.io/s/chakra-react-select-chakrastyles-5yh6q?file=/app.tsx
TypeScript: https://codesandbox.io/s/chakra-react-select-styled-like-a-default-chakra-select-qwq3o?file=/app.tsx
Import#
import {ChakraReactSelect,CreatableSelect,AsyncCreatableSelect,AsyncSelect,} from '@fluidtruck/core'
ChakraReactSelect
:react-select
composed ofchakra-ui
components. TheselectComponents
are the customized components overridingreact-select
defaultcomponents
. ThisChakraReactSelect
component takes theMenu
component theme file as part of it's component styles.. ThetidalSelectComponents
are the Tidal customized components overridingchakra-react-select
defaultchakraComponents
, Specifically theDropdownIndicator
. Both are export and can be used as needed for customizing.
import {ChakraReactSelect,CreatableSelect,AsyncCreatableSelect,AsyncSelect,selectComponents,tidalSelectComponents,} from '@fluidtruck/core'
Usage#
const options = [{ label: 'Green', value: 'green', colorScheme: 'green' },{ label: 'Green-Yellow', value: 'greenyellow' },{ label: 'Red', value: 'red' },{ label: 'Violet', value: 'violet' },{ label: 'Forest', value: 'forest' },{ label: 'Tangerine', value: 'tangerine' },{ label: 'Blush', value: 'blush' },{ label: 'Purple', value: 'purple' },]function SelectUsage() {const [state, setState] = React.useState()const [inputState, setInputState] = React.useState('')handleState = (value) => setState(value.value)return (<HStack spacing={6}><FormControl><FormLabel>Color Palette</FormLabel><ChakraReactSelectisMulticloseMenuOnSelect={false}defaultMenuIsOpendefaultValue={options[0]}options={options}id="colorsOne"onChange={handleState}/><chakra.p py={4}><b>State:</b> {state}</chakra.p></FormControl></HStack>)}render(<SelectUsage />)
Custom Components & Styling#
const iconStyle = {mr: 2,w: 8,h: 'auto',}const options = [{label: 'Purple',value: 'purple, blue',colorScheme: 'purple'},{label: 'Yellow',value: 'gold, yellow',colorScheme: 'yellow'},{label: 'Pink',value: 'pink, red',colorScheme: 'pink'},{label: 'Forest',value: 'green, forest',colorScheme: 'green'},{label: 'Sand',value: 'brown, sand, dirt',colorScheme: 'red'},{label: 'Candy',value: 'candy, pink',colorScheme: 'pink'},{label: 'Sky',value: 'sky, blue',colorScheme: 'blue'},]const components = {Option: ({children,...props}) => (<selectComponents.Option {...props}><Flex flexDir="column"><Flex>{children}</Flex><Text fontSize="xs">{props.data.label}</Text></Flex></selectComponents.Option>),Menu: ({ children, ...props }) => (<selectComponents.Menu {...props}><Box sx={{bgColor: 'white',color: 'black',shadow: 'base','> *': {shadow: 'base',}}}>{children}</Box></selectComponents.Menu>),ValueContainer: ({ children, ...props }) => (<selectComponents.ValueContainer {...props}><Flex px={2} align="center" gap={2}><SearchIcon color="fluidBlue" /> {children}</Flex></selectComponents.ValueContainer>),MultiValueContainer: ({ children, ...props }) => (<selectComponents.MultiValueContainer {...props}>{children}</selectComponents.MultiValueContainer>),};const filterOptions = (inputValue) => {return options.filter((i) =>i.value.includes(inputValue.toLowerCase()))};const promiseOptions = (inputValue) =>new Promise((resolve) => {setTimeout(() => {resolve(filterOptions(inputValue));}, 1000);});function SelectUsage() {const [state, setState] = React.useState()const [inputState, setInputState] = React.useState('')handleState = (value) => setState(value.value)return (<HStack spacing={6}><FormControl><FormLabel>Color Palette</FormLabel><AsyncCreatableSelectisMultidefaultMenuIsOpencloseMenuOnSelect={false}defaultValue={options[0].value}loadOptions={promiseOptions}id="bank"onChange={handleState}components={{...tidalSelectComponents,...components}}/></FormControl></HStack>)}render(<SelectUsage />)
Custom Components & Styling#
Notice the ...selectComponents
, this must be passed if overriding any components.
const iconStyle = {mr: 2,w: 8,h: 'auto',}const options = [{label: 'Visa 2300',value: '2300',icon: <Icon as={CardVisaIcon} {...iconStyle} />},{label: 'Discover 7657',value: '7657',icon: <Icon as={CardDiscoverIcon} {...iconStyle} />},{label: 'Amex 4775',value: '4775',icon: <Icon as={CardAmexIcon} {...iconStyle} />},{label: 'CC 5535',value: '5535',icon: <Icon as={CardGenericIcon} {...iconStyle} />},]const Option = ({ children, ...props }) => (<selectComponents.Option {...props}><Flex justifyContent="center">{props.data.icon} {children}</Flex></selectComponents.Option>);const SingleValue = ({ children, ...props }) => (<selectComponents.SingleValue pl={0} {...props}><Flexsx={{ '& > .chakra-icon': { color: 'fluidBlue' } }}>{props.data.icon} {children}</Flex></selectComponents.SingleValue>);function SelectUsage() {const [state, setState] = React.useState()const [inputState, setInputState] = React.useState('')handleState = (value) => setState(value.value)return (<HStack spacing={6}><FormControl><FormLabel>Color Palette</FormLabel><ChakraReactSelectdefaultValue={options[0].value}options={options}id="bank"onChange={handleState}components={{Option,SingleValue,}}/></FormControl></HStack>)}render(<SelectUsage />)
chakraStyleProps
: Custom style props#
In case one of the variants is not the design you need, you can override any component you need.
Please Refer to the default variants.tsx
file in the src code.
chakraStyles
#
- NOTE: this overrides the default styles declared in the variants.ts file. It will fallback to the Menu's theme styles.
- you can access the variants by importing
selectVariants
, which contains the defaultmenuBase
andvariantOutline
. import { selectVariants } from '@fluidtruck/core'
(provided: SystemStyleObject)
-- The component's default Chakra styles(state: Object)
-- The component's current state e.g.isFocused
(this gives all of the same props that are passed into the component)- returns a
SystemStyleObject
-- An output style object which is forwarded to the component'ssx
prop
const options = [{ label: 'Violet', value: 'violet' },{ label: 'Forest', value: 'forest' },{ label: 'Tangerine', value: 'tangerine' },{ label: 'Blush', value: 'blush' },{ label: 'Purple', value: 'purple' },]function SelectUsage() {const [state, setState] = React.useState()handleState = (value) => setState(value.value)const styles = {multiValue: (provided) => ({...provided,bgColor: 'blue.500',color: 'white',}),input: (provided) => ({...provided,color: 'blue.600',fontSize: 'lg',fontWeight: 'bold',}),singleValue: (provided) => ({...provided,color: 'blue.600',fontSize: 'lg',fontWeight: 'bold',}),placeholder: (provided) => ({...provided,color: 'blue.600',fontSize: 'lg',fontWeight: 'bold',}),dropdownIndicator: (provided) => ({...provided,color: 'blue.600',}),control: (provided) => ({...provided,bg: 'transparent',borderColor: 'blue.600'}),valueContainer: (provided) => ({...provided,paddingStart: 1,paddingEnd: 1,}),...selectVariants.menuBase,}return (<HStack padding={4} spacing={6}><FormControl><FormLabel color="blue.800">Color Palette</FormLabel><ChakraReactSelectisMultidefaultValue={options[0].value}options={options}id="custom-styles"onChange={handleState}chakraStyles={styles}variant="default"/></FormControl></HStack>)}render(<SelectUsage />)
Variants#
Pass the variant: string
- default
, outline
, & dark
default
actually is rendered from theMenu
component theme filedark
is actually on a transparent background, meant fordark-mode
.- if you would like to create a new variant, add the new variant zobject styles to the
variants
file.
const options = [{ label: 'Violet', value: 'violet' },{ label: 'Forest', value: 'forest' },{ label: 'Tangerine', value: 'tangerine' },{ label: 'Blush', value: 'blush' },]function SelectUsage() {const [state, setState] = React.useState()const [inputState, setInputState] = React.useState('')handleState = (value) => setState(value.value)return (<Grid gap={4}><HStack spacing={6}><FormControl><FormLabel>Default</FormLabel><ChakraReactSelectdefaultValue={options[0].value}options={options}id="default-light"onChange={handleState}/></FormControl></HStack><HStack spacing={6}><FormControl><FormLabel>Outline</FormLabel><ChakraReactSelectdefaultValue={options[0].value}options={options}id="outline-variant"onChange={handleState}variant="outline"/></FormControl></HStack><HStack spacing={6}><FormControl><FormLabel>Dark BG</FormLabel><Box bgColor="blue.700" py={3}><ChakraReactSelectdefaultValue={options[0].value}options={options}id="outline-variant"onChange={handleState}variant="dark"/></Box></FormControl></HStack></Grid>)}render(<SelectUsage />)
AsycSelect, MulitValue Select and CreatableSelect#
const options = [{ label: 'Green', value: 'green', colorScheme: 'green' },{ label: 'Green-Yellow', value: 'greenyellow', colorScheme: 'yellow' },{ label: 'Red', value: 'red', colorScheme: 'red' },{ label: 'Violet', value: 'violet', colorScheme: 'purple' },{ label: 'Forest', value: 'forest', colorScheme: 'green' },{ label: 'Tangerine', value: 'tangerine', colorScheme: 'orange' },{ label: 'Blush', value: 'blush', colorScheme: 'pink' },{ label: 'Purple', value: 'purple', colorScheme: 'purple' },]function SelectUsage() {const [stateOne, setStateOne] = React.useState()const [stateTwo, setStateTwo] = React.useState()const [stateThree, setStateThree] = React.useState()handleStateOne = (value) => setStateOne(value.value)handleStateTwo = (value) => setStateTwo(value.value)handleStateThree = (value) => setStateThree(value.value)const filterColors = (inputValue) => {return options.filter((i) =>i.label.toLowerCase().includes(inputValue.toLowerCase()));};const promiseOptions = (inputValue) =>new Promise((resolve) => {setTimeout(() => {resolve(filterColors(inputValue));}, 1000);});return (<Grid gap={6}><FormControl><FormLabel>AsyncSelect</FormLabel><AsyncSelectloadOptions={promiseOptions}onChange={handleStateOne}/></FormControl><FormControl><FormLabel>CreateableSelect</FormLabel><CreatableSelectoptions={options}onChange={handleStateTwo}closeMenuOnSelect={false}/></FormControl><FormControl><FormLabel>MulitValue Select</FormLabel><ChakraReactSelectisMultioptions={options}onChange={handleStateThree}// overrides the the variants style in variants.ts// will fallback on the menu.ts styles in the themechakraStyles={{...selectVariants.menuBase,multiValue: (provided) => ({ ...provided })}}/></FormControl></Grid>)}render(<SelectUsage />)
Props#
Full List of React-Select Props: https://react-select.com/props
Internal Components#
interface SelectComponents<Option, IsMulti extends boolean, Group extends GroupBase<Option>> {ClearIndicator: ComponentType<ClearIndicatorProps<Option, IsMulti, Group>>;Control: ComponentType<ControlProps<Option, IsMulti, Group>>;DropdownIndicator: ComponentType<DropdownIndicatorProps<Option, IsMulti, Group>> | null;Group: ComponentType<GroupProps<Option, IsMulti, Group>>;GroupHeading: ComponentType<GroupHeadingProps<Option, IsMulti, Group>>;IndicatorsContainer: ComponentType<IndicatorsContainerProps<Option, IsMulti, Group>>;IndicatorSeparator: ComponentType<IndicatorSeparatorProps<Option, IsMulti, Group>> | null;Input: ComponentType<InputProps<Option, IsMulti, Group>>;LoadingIndicator: ComponentType<LoadingIndicatorProps<Option, IsMulti, Group>>;Menu: ComponentType<MenuProps<Option, IsMulti, Group>>;MenuList: ComponentType<MenuListProps<Option, IsMulti, Group>>;LoadingMessage: ComponentType<NoticeProps<Option, IsMulti, Group>>;NoOptionsMessage: ComponentType<NoticeProps<Option, IsMulti, Group>>;MultiValue: ComponentType<MultiValueProps<Option, IsMulti, Group>>;MultiValueContainer: ComponentType<MultiValueGenericProps<Option, IsMulti, Group>>;MultiValueLabel: ComponentType<MultiValueGenericProps<Option, IsMulti, Group>>;MultiValueRemove: ComponentType<MultiValueRemoveProps<Option, IsMulti, Group>>;Option: ComponentType<OptionProps<Option, IsMulti, Group>>;Placeholder: ComponentType<PlaceholderProps<Option, IsMulti, Group>>;SelectContainer: ComponentType<ContainerProps<Option, IsMulti, Group>>;SingleValue: ComponentType<SingleValueProps<Option, IsMulti, Group>>;ValueContainer: ComponentType<ValueContainerProps<Option, IsMulti, Group>>;}
Style keys#
- clearIndicator - Box (uses theme styles for Chakra's CloseButton)
- container - Box
- control - Box (uses theme styles for Chakra's Input)
- dropdownIndicator - Box (uses theme styles for Chrakra's InputRightAddon)
- group - Box
- groupHeading - Box (uses theme styles for Chakra's Menu group title)
- indicatorsContainer - Box
- indicatorSeparator - Divider
- input - chakra.input (wrapped in a Box)
- inputContainer - Box
- loadingIndicator - Spinner
- loadingMessage - Box
- menu - Box
- menuList - Box (uses theme styles for Chakra's Menu)
- multiValue - chakra.span (uses theme styles for Chakra's Tag)
- multiValueLabel - chakra.span (uses theme styles for Chakra's TagLabel)
- multiValueRemove - Box (uses theme styles for Chakra's TagCloseButton)
- noOptionsMessage - Box
- option - Box (uses theme styles for Chakra's MenuItem)
- placeholder - Box
- singleValue - Box
- valueContainer - Box
TypeScript#
Detailed TypeScript for react-select
import { GroupBase, OptionBase, Select } from "chakra-react-select";/*** `OptionBase` is a custom type exported by this package meant to be extended* to make your custom option types. It includes all of the keys that can be* used by this package to customize the styles of your selected options** ```* type OptionBase = {* variant?: string;* colorScheme?: string;* isFixed?: boolean;* isDisabled?: boolean;* };* ```*/interface ColorOption extends OptionBase {label: string;value: string;}const colorOptions = [{label: "Red",value: "red",colorScheme: "red", // This is allowed because of the key in the `OptionBase` type},{label: "Blue",value: "blue",}]function CustomMultiSelect() {return {<ChakraReactSelect<ColorOption, true, GroupBase<ColorOption>>isMultiname="colors"options={colorOptions}placeholder="Pick a color!"/>}}
-
This will make the custom prop available both when using the Select component as well as when accessing selectProps when customizing components.
-
You can use module augmentation to add custom props to the Select prop types
declare module 'react-select/dist/declarations/src/Select' {export interface Props<Option,IsMulti extends boolean,Group extends GroupBase<Option>> {myCustomProp: string;}}
type OptionType = { [string]: any }type OptionsType = Array<OptionType>type GroupType = {[string]: any, // group labeloptions: OptionsType,}type ValueType = OptionType | OptionsType | null | voidtype CommonProps = {clearValue: () => void,getStyles: (string, any) => {},getValue: () => ValueType,hasValue: boolean,isMulti: boolean,options: OptionsType,selectOption: OptionType => void,selectProps: any,setValue: (ValueType, ActionTypes) => void,emotion: any,}
Extra Props#
size
colorScheme
tagVariant
isInvalid
/isReadOnly
focusBorderColor
/errorBorderColor
useBasicStyles
selectedOptionStyle
selectedOptionColorScheme
variant
size
— Options: ResponsiveValue<"sm" | "md" | "lg">
— Default: md
#
You can pass the size
prop with either sm
, md
, or lg
(default is md
).
These will reflect the sizes available on the
Chakra <Input />
component
(except for xs
because it's too small to work). Alternatively, you can pass a
responsive style array or object
of size
values to allow it to change depending on your theme's breakpoints.
If no size
is passed, it will default to defaultProps.size
from the theme
for Chakra's Input
component. If your component theme for Input
is not
modified, it will be md
.
return (<><Select size="sm" /><Select size="md" /> {/* Default */}<Select size="lg" /></>);