Skip to content

Instantly share code, notes, and snippets.

@robinsandborg
Created February 23, 2018 15:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robinsandborg/3646d7aa22a39be6a8729c381ecb8be6 to your computer and use it in GitHub Desktop.
Save robinsandborg/3646d7aa22a39be6a8729c381ecb8be6 to your computer and use it in GitHub Desktop.
Weird styled-components bug
import React from "react"
import PropTypes from "prop-types"
import styled from "styled-components"
const CaretIcon = styled.svg`
width: 12px;
transition: fill 0.2s ease;
`
const Caret = ({ className }) => (
<CaretIcon className={className} viewBox="0 0 24 16">
<path d="M3.81 0a.54.54 0 0 0-.38.16L.16 3.47a.56.56 0 0 0 0 .78l11.45 11.59a.54.54 0 0 0 .78 0L23.84 4.25a.56.56 0 0 0 0-.78L20.57.17a.54.54 0 0 0-.77 0L12 8.04 4.2.16A.54.54 0 0 0 3.81 0z" />
</CaretIcon>
)
Caret.propTypes = { className: PropTypes.string }
export default Caret
import React from "react"
import PropTypes from "prop-types"
import styled from "styled-components"
const CloseIcon = styled.svg`
width: 12px;
transition: fill 0.2s ease;
`
const Close = ({ className }) => (
<CloseIcon viewBox="0 0 24 24">
<path d="M11.96 8a.54.54 0 0 1 .08 0L19.8.17a.54.54 0 0 1 .77 0l3.27 3.3c.21.22.21.56 0 .78L16.18 12l7.66 7.76c.2.21.2.56 0 .78l-3.27 3.3a.54.54 0 0 1-.77 0L12.04 16a.54.54 0 0 1-.08 0L4.2 23.85a.54.54 0 0 1-.77 0L.16 20.54a.56.56 0 0 1 0-.78L7.82 12 .16 4.25a.56.56 0 0 1 0-.78L3.43.16a.54.54 0 0 1 .77 0L11.96 8z" />
</CloseIcon>
)
Close.propTypes = { className: PropTypes.string }
export default Close
import React from "react"
import PropTypes from "prop-types"
import styled from "styled-components"
import Downshift from "downshift"
import multiplyPixelValue from "../../../functions/multiplyPixelValue"
import Label from "../Label/Label"
import Input from "../Input/Input"
import Caret from "../../Icons/Caret"
import Close from "../../Icons/Close"
const DefaultOptionElementWrapper = styled.div`
border: 1px solid ${p => p.theme.color.line};
border-top-width: 0;
`
const SelectedWrapper = styled.div`
position: relative;
`
const IconButton = styled.button`
position: absolute;
right: ${p => p.theme.spacing.small};
bottom: ${p => multiplyPixelValue(p.theme.targetSize.normal, 0.5)};
width: ${p => p.theme.targetSize.small};
height: ${p => p.theme.targetSize.small};
border: 0;
padding: 0 ${p => p.theme.spacing.tiny};
text-align: center;
background-color: transparent;
fill: ${p => p.theme.color.gray};
transform: translateY(50%);
transition: fill 0.2s ease;
&:active,
&:hover,
&:focus {
outline: none;
svg {
fill: ${p => p.theme.color.primary};
}
}
`
const DefaultPlaceholderElement = Input
const Select = ({
children,
onChange,
label,
renderSelectedElement,
selectedElement,
renderOptionsWrapperElement,
optionsWrapperElement,
renderPlaceHolderElement,
placeHolderElement,
placeHolderLabel,
iconCaret,
iconClose
}) => {
const Selected = renderSelectedElement || selectedElement
const OptionsWrapper =
renderOptionsWrapperElement ||
optionsWrapperElement ||
DefaultOptionElementWrapper
const Placeholder =
renderPlaceHolderElement || placeHolderElement || DefaultPlaceholderElement
const CaretIcon = iconCaret || Caret
const CloseIcon = iconClose || Close
return (
<Downshift
onChange={onChange}
itemToString={item => (item ? item.text : "")}
render={({
getInputProps,
getButtonProps,
getItemProps,
isOpen,
inputValue,
selectedItem,
highlightedIndex,
toggleMenu,
clearSelection
}) => (
<div>
<Label>{label}</Label>
{selectedItem ? (
<SelectedWrapper>
<Selected
onClick={() => toggleMenu()}
selectedItem={selectedItem}
buttonProps={{ ...getButtonProps() }}
inputProps={{ ...getInputProps() }}
toggleMenu={toggleMenu}
/>
<IconButton onClick={() => clearSelection()}>
<CloseIcon />
</IconButton>
</SelectedWrapper>
) : (
<SelectedWrapper>
<Placeholder
{...getInputProps({
placeholder: placeHolderLabel || ""
})}
onClick={() => toggleMenu()}
/>
<IconButton onClick={() => toggleMenu()}>
<CaretIcon />
</IconButton>
</SelectedWrapper>
)}
{isOpen && (
<OptionsWrapper>
{children.map((child, index) => {
const item = child.props.data
return React.cloneElement(child, {
...getItemProps({ item }),
...child.props,
highlighted: highlightedIndex === index,
selected: selectedItem === child
})
})}
</OptionsWrapper>
)}
</div>
)}
/>
)
}
Select.propTypes = {
children: PropTypes.arrayOf(PropTypes.element).isRequired,
renderSelectedElement: (props, propName, componentName) => {
if (!props.renderSelectedElement && !props.selectedElement) {
return new Error(
`One of props 'renderSelectedElement' or 'selectedElement' was not specified in '${componentName}'.`
)
}
},
selectedElement: (props, propName, componentName) => {
if (!props.renderSelectedElement && !props.selectedElement) {
return new Error(
`One of props 'renderSelectedElement' or 'selectedElement' was not specified in '${componentName}'.`
)
}
},
items: PropTypes.array,
onChange: PropTypes.func,
optionsWrapperElement: PropTypes.func,
renderOptionsWrapperElement: PropTypes.func,
label: PropTypes.string,
placeHolderLabel: PropTypes.string,
renderPlaceHolderElement: PropTypes.func,
placeHolderElement: PropTypes.func,
iconCaret: PropTypes.element,
iconClose: PropTypes.element
}
export default Select
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment