@axeptio/design-system
Version:
Design System for Axeptio
249 lines (232 loc) • 6.01 kB
JSX
import React from 'react';
import ReactSelect, { components } from 'react-select';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { axeptio } from '../../../Presets';
const DropdownIndicator = props => {
return (
<components.DropdownIndicator {...props}>
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 22 22" className="select-icon">
<path d="M7.41,8.59L12,13.17l4.59-4.58L18,10l-6,6l-6-6L7.41,8.59z" />
</svg>
</components.DropdownIndicator>
);
};
const RootMobile = styled.select`
font-family: ${props => props.theme.fonts.text};
width: 100%;
outline: none !important;
appearance: none !important;
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' fill='%23acacac' width='22' height='22' viewBox='0 0 22 22'><path d='M7.41,8.59L12,13.17l4.59-4.58L18,10l-6,6l-6-6L7.41,8.59z'></path></svg>")
right no-repeat;
background-position: right 8px bottom 15px;
font-size: 13px;
font-weight: 400;
line-height: 1.25;
height: auto;
min-height: 34px;
border-radius: 6px;
color: ${props => props.theme.colors.grey.v500};
background-color: ${props => props.theme.colors.white};
border: 1px solid ${props => props.theme.colors.grey.v300};
cursor: pointer;
transition: all 100ms ease;
&:focus {
border: 1px solid ${props => props.theme.colors.primary};
box-shadow: 0 0 0 3px rgb(255 200 35 / 25%);
}
${props =>
props.small &&
`
padding: 4px;
`};
${props =>
props.large &&
`
min-height: 56px;
padding: 8px;
`};
`;
const Root = styled(ReactSelect)`
font-family: ${props => props.theme.fonts.text};
.select-icon {
fill: ${props => props.theme.colors.grey.v400};
}
&:hover .select-icon {
fill: ${props => props.theme.colors.secondary};
}
${props =>
props.small &&
`
.axeptio-select__control {
padding: 2px 0;
}
.axeptio-select__indicators .axeptio-select__indicator{
padding: 4px;
}
`};
${props =>
props.large &&
`
.axeptio-select__control {
min-height: 54px;
padding: 8px 0;
}
`};
.axeptio-select__indicator-separator {
display: none;
}
`;
const customStyles = {
option: (provided, state) => ({
...provided,
cursor: 'pointer',
zIndex: 2000,
fontSize: '13px',
fontWeight: state.isSelected ? 'bold' : 'normal',
color: axeptio.colors.grey.v500,
backgroundColor: state.isFocused ? axeptio.colors.grey['grey-50'] : 'transparent',
':active': {
...provided[':active'],
backgroundColor: state.isSelected ? axeptio.colors.grey.v200 : axeptio.colors.primaryPalette.v50
},
borderLeft: state.isSelected ? '2px solid' + axeptio.colors.primary : 'none'
}),
control: (provided, state) => ({
...provided,
outline: 'none !important',
appearance: 'none !important',
fontFamily: axeptio.fonts.text,
fontSize: '13px',
fontWeight: '400',
lineHeight: '1.25',
height: 'auto',
minHeight: '34px',
borderRadius: '6px',
color: axeptio.colors.grey.v500,
backgroundColor: axeptio.colors.white,
border: state.isFocused ? '1px solid ' + axeptio.colors.primary : '1px solid ' + axeptio.colors.grey.v300,
cursor: 'pointer',
transition: 'all 100ms ease',
boxShadow: state.isFocused ? '0 0 0 3px rgb(255 200 35 / 25%)' : 'none',
':hover': {
...provided[':hover'],
borderColor: state.isFocused ? axeptio.colors.primary : ''
}
}),
multiValue: provided => ({
...provided,
color: axeptio.colors.grey.v500,
backgroundColor: axeptio.colors.primary
}),
menu: provided => ({
...provided,
zIndex: 10000,
fontFamily: axeptio.fonts.text
})
};
const Select = props => {
const {
name,
multi,
value,
options,
onChange,
onClear,
placeholder,
closeMenuOnSelect,
small,
large,
optionsMessage,
hideSelectedOptions,
isSearchable,
isDisabled,
menuIsOpen,
browser
} = props;
if (browser && !multi) {
return (
<RootMobile
name={name}
value={value?.label}
options={options}
onChange={val => {
onChange(val.target.value);
}}
placeholder={placeholder}
small={small}
large={large}
isDisabled={isDisabled}
>
{options.map((data, index) => {
return (
<option key={index} value={data.value}>
{data.label}
</option>
);
})}
</RootMobile>
);
}
return (
<Root
styles={customStyles}
classNamePrefix="axeptio-select"
components={{ DropdownIndicator }}
name={name}
isMulti={multi}
value={value}
options={options}
onChange={val => {
onChange(val);
}}
clearValue={() => {
onClear();
}}
placeholder={placeholder}
closeMenuOnSelect={closeMenuOnSelect}
small={small}
large={large}
noOptionsMessage={() => {
return <span>{optionsMessage}</span>;
}}
hideSelectedOptions={hideSelectedOptions}
isSearchable={isSearchable}
isDisabled={isDisabled}
menuIsOpen={menuIsOpen}
{...props}
/>
);
};
Select.propTypes = {
name: PropTypes.string,
small: PropTypes.bool,
large: PropTypes.bool,
multi: PropTypes.string,
value: PropTypes.any,
options: PropTypes.array,
onChange: PropTypes.func,
onClear: PropTypes.func,
placeholder: PropTypes.string,
closeMenuOnSelect: PropTypes.bool,
optionsMessage: PropTypes.string,
hideSelectedOptions: PropTypes.bool,
isSearchable: PropTypes.bool,
isDisabled: PropTypes.bool,
menuIsOpen: PropTypes.bool,
browser: PropTypes.bool
};
Select.defaultProps = {
name: '',
small: false,
large: true,
multi: false,
value: null,
options: [],
onChange: null,
placeholder: '',
closeMenuOnSelect: true,
isSearchable: false,
browser: false
};
export default Select;