UNPKG

@patreon/studio

Version:

Patreon Studio Design System

65 lines (62 loc) 2.05 kB
import React, { Children, cloneElement } from 'react'; import { styled } from 'styled-components'; import { tokens } from '~/tokens'; /** Useful for when you want a group of `TextInput` and `Select` components to be rendered as one block. * Visible labels should not be used on the middle or last children or it may lead to unexpected results. */ export const InputGroup = ({ children }) => { // Filter out falsy and undefined values. const filteredChildren = Array.isArray(children) ? children.filter((child) => !!child) : children; const total = React.Children.count(filteredChildren); return (<Container> {Children.map(filteredChildren, (child, index) => { // This is just to make typescript happpy as these values will already be filtered out above. if (child) { return (<InputWrapper hasError={!!child.props.error}> {cloneElement(child, { corners: getCorners({ index, isLast: index === total - 1 }), width: 'fluid', })} </InputWrapper>); } return null; })} </Container>); }; const Container = styled.div ` display: flex; flex-direction: column; width: 100%; position: relative; `; const InputWrapper = styled.div ` z-index: ${({ hasError }) => (hasError ? 1 : 'auto')}; // Add negative margin for all children but the last to remove double borders margin-bottom: calc(-1 * ${tokens.global.borderWidth.thin}); &:last-of-type { margin-bottom: 0; } &:hover, &:active, &:focus, &:focus-within { z-index: 1; } `; const getCorners = ({ index, isLast }) => { // If there's just one child if (index === 0 && isLast) { return undefined; } // Element is on top if (index === 0) { return 'rounded-top'; } // Element is on bottom if (isLast) { return 'rounded-bottom'; } // Element is in the middle return 'square'; }; //# sourceMappingURL=InputGroup.jsx.map