@kiwicom/orbit-components
Version:
<div align="center"> <a href="https://orbit.kiwi" target="_blank"> <img alt="orbit-components" src="https://orbit.kiwi/wp-content/uploads/2018/08/orbit-components.png" srcset="https://orbit.kiwi/wp-content/uploads/2018/08/orbit-components@2x.png 2x"
206 lines (183 loc) • 5.68 kB
JavaScript
// @flow
import * as React from "react";
import styled from "styled-components";
import defaultTokens from "../defaultTokens";
import FormLabel from "../FormLabel";
import ChevronDown from "../icons/ChevronDown";
import FormFeedback from "../FormFeedback";
import TYPE_OPTIONS from "../FormFeedback/consts";
import SIZE_OPTIONS from "./consts";
import type { Props } from "./index";
const Label = styled.label`
width: 100%;
`;
const StyledSelect = styled(
({ className, children, value, disabled, onChange, onFocus, onBlur }) => (
<select
value={value}
className={className}
onChange={onChange}
onFocus={onFocus}
onBlur={onBlur}
disabled={disabled}
>
{children}
</select>
),
)`
appearance: none;
background: ${({ theme }) => theme.orbit.backgroundInput};
border-radius: ${({ theme }) => theme.orbit.borderRadiusNormal};
cursor: pointer;
color: ${({ theme, filled }) =>
filled ? theme.orbit.colorTextInput : theme.orbit.colorPlaceholderInput};
font-family: ${({ theme }) => theme.orbit.fontFamily};
font-size: ${({ theme, size }) =>
size === SIZE_OPTIONS.SMALL ? theme.orbit.fontSizeInputSmall : theme.orbit.fontSizeInputNormal};
height: ${({ theme, size }) =>
size === SIZE_OPTIONS.SMALL ? theme.orbit.heightInputSmall : theme.orbit.heightInputNormal};
padding: ${({ theme, size }) =>
size === SIZE_OPTIONS.SMALL
? `0 ${theme.orbit.spaceXLarge} 0 ${theme.orbit.spaceSmall}`
: `0 ${theme.orbit.spaceXXLarge} 0 ${theme.orbit.spaceSmall}`};
outline: none;
width: 100%;
transition: box-shadow ${({ theme }) => theme.orbit.durationFast} ease-in-out;
z-index: 2;
&::-ms-expand {
display: none;
}
/* With prefix */
padding-left: ${({ prefix, theme }) => prefix && theme.orbit.paddingLeftSelectPrefix};
/* Based on state of select */
border: 0;
box-shadow: inset 0 0 0
${({ theme, error }) =>
`${theme.orbit.borderWidthInput} ${
error ? theme.orbit.borderColorInputError : theme.orbit.borderColorInput
}`};
&:hover {
box-shadow: inset 0 0 0
${({ theme, error }) =>
`${theme.orbit.borderWidthInput} ${
error ? theme.orbit.borderColorInputErrorHover : theme.orbit.borderColorInputHover
}`};
}
&:focus {
box-shadow: inset 0 0 0
${({ theme }) => `${theme.orbit.borderWidthInputFocus} ${theme.orbit.borderColorInputFocus}`};
}
&:disabled {
color: ${({ theme }) => theme.orbit.colorTextInputDisabled};
background: ${({ theme }) => theme.orbit.backgroundInputDisabled};
cursor: default;
&:hover {
box-shadow: inset 0 0 0 1px ${({ theme }) => theme.orbit.borderColorInput};
}
}
`;
StyledSelect.defaultProps = {
theme: defaultTokens,
};
export const SelectContainer = styled(({ className, children }) => (
<div className={className}>{children}</div>
))`
position: relative;
display: flex;
align-items: center;
background: ${({ theme }) => theme.orbit.backgroundInput};
width: 100%;
box-sizing: border-box;
cursor: pointer;
`;
SelectContainer.defaultProps = {
theme: defaultTokens,
};
const SelectPrefix = styled(({ className, children }) => (
<div className={className}>{children}</div>
))`
display: flex;
align-items: center;
position: absolute;
padding: ${({ theme }) => `0 ${theme.orbit.spaceSmall}`};
pointer-events: none;
z-index: 3;
`;
SelectPrefix.defaultProps = {
theme: defaultTokens,
};
const SelectSuffix = styled(({ children, className }) => (
<div className={className}>{children}</div>
))`
position: absolute;
right: ${({ theme }) => theme.orbit.spaceXSmall};
color: ${({ theme, disabled }) =>
disabled ? theme.orbit.colorTextInputDisabled : theme.orbit.colorTextInput};
pointer-events: none;
z-index: 3;
& > * {
width: ${({ theme, size }) => size === SIZE_OPTIONS.SMALL && theme.orbit.widthIconSmall};
height: ${({ theme, size }) => size === SIZE_OPTIONS.SMALL && theme.orbit.heightIconSmall};
margin-bottom: ${({ size, theme }) => size === SIZE_OPTIONS.SMALL && theme.orbit.spaceXXXSmall};
}
`;
SelectSuffix.defaultProps = {
theme: defaultTokens,
};
const Select = ({
size = SIZE_OPTIONS.NORMAL,
label,
placeholder,
value,
disabled = false,
error,
help,
onChange,
onBlur,
onFocus,
options,
dataTest,
prefix,
}: Props) => {
const filled = !!value;
return (
<Label data-test={dataTest}>
{label && (
<FormLabel filled={filled} disabled={disabled}>
{label}
</FormLabel>
)}
<SelectContainer disabled={disabled}>
{prefix && <SelectPrefix prefix={prefix}>{prefix}</SelectPrefix>}
<StyledSelect
size={size}
disabled={disabled}
error={error}
value={value}
prefix={prefix}
onFocus={onFocus}
onBlur={onBlur}
onChange={onChange}
filled={filled}
>
{placeholder && (
<option label={placeholder} value="" selected disabled>
{placeholder}
</option>
)}
{options.map(option => (
<option key={`option-${option.value}`} value={option.value} disabled={option.disabled}>
{option.label}
</option>
))}
</StyledSelect>
<SelectSuffix size={size} disabled={disabled}>
<ChevronDown />
</SelectSuffix>
</SelectContainer>
{help && !error && <FormFeedback type={TYPE_OPTIONS.HELP}>{help}</FormFeedback>}
{error && <FormFeedback type={TYPE_OPTIONS.ERROR}>{error}</FormFeedback>}
</Label>
);
};
export default Select;