UNPKG

@navinc/base-react-components

Version:
197 lines (176 loc) 4.36 kB
import React from 'react' import styled from 'styled-components' import Copy from './copy' import { Errors, Err } from './form-elements/shared.js' const CopyLabel = styled(Copy)` font-size: 14px; ` const DivLabel = styled.div`` const CheckboxItem = styled.label` display: flex; width: 100%; text-align: left; ${({ asideContent, hasBorder, theme }) => (hasBorder || asideContent) && ` align-items: center; border: 1px solid ${theme.border}; border-radius: 4px; padding: 8px; padding-left: 16px; padding-right: 16px; min-height: 62px; `} ${({ checked, checkedBackgroundColor }) => checked && checkedBackgroundColor && ` background-color: ${checkedBackgroundColor}; border-color: ${checkedBackgroundColor}; `} ` const sizeVariants = { sm: { checkRight: '7px', checkBottom: '7.5px', checkboxSize: '20px', thickness: '2.5px', }, md: { checkRight: '8px', checkBottom: '9px', checkboxSize: '24px', thickness: '3px', }, } const AsideContainer = styled.div` display: flex; flex: 1; justify-content: flex-end; margin-left: 8px; ` const BottomCheckLine = styled.div` background-color: ${({ theme }) => theme.white}; border-radius: 100px; position: absolute; bottom: 0; width: 100%; ` const LeftCheckLine = styled.div` background-color: ${({ theme }) => theme.white}; border-radius: 100px; bottom: 0; height: 50%; left: 0; position: absolute; ` const CheckContainer = styled.div` ${({ checked }) => !checked && 'display: none;'} height: 60%; transform: rotate(-45deg); position: absolute; width: 50%; ` const CheckboxContainer = styled.div` position: relative; ${({ size }) => { const { checkRight, checkBottom, checkboxSize, thickness } = sizeVariants[size] || sizeVariants.md return ` ${CheckContainer} { right: ${checkRight}; bottom: ${checkBottom}; } ${LeftCheckLine} { width: ${thickness} } ${BottomCheckLine} { height: ${thickness} } height: ${checkboxSize}; width: ${checkboxSize}; min-width: ${checkboxSize}; min-height: ${checkboxSize}; ` }} margin-right: 16px; ` const StyledCheckbox = styled.input.attrs(() => ({ type: 'checkbox' }))` appearance: none; background: ${({ checked, isInvalid, disabled, theme }) => { if (disabled) { return theme.scuttleGray100 } else if (checked) { return theme.azure } else if (isInvalid) { return theme.sebastianRed100 } else { return theme.bubbleBlue100 } }}; border-radius: 4px; border-style: solid; border-width: ${({ checked }) => (checked ? '3px' : '1px')}; border-color: ${({ checked, isInvalid, disabled, theme }) => checked ? theme.bubbleBlue300 : disabled ? theme.scuttleGray200 : isInvalid ? theme.sebastianRed100 : theme.bubbleBlue200}; height: 100%; margin: 0; padding: 0; width: 100%; transition: box-shadow 300ms ease; ${({ isInvalid, theme }) => isInvalid && ` box-shadow: 0 0 0 4px ${theme.sebastianRed200}; `} &:focus { outline: none; box-shadow: 0 0 0 4px ${({ theme }) => theme.bubbleBlue300}; } ` const Checkbox = ({ asideContent, label, checked, checkedBackgroundColor, disabled, className, hasBorder, hasSpaceForErrors, errors = [], size, isInvalid, ...props }) => { const Label = typeof label === 'string' ? CopyLabel : DivLabel return ( <CheckboxItem className={className} checked={checked} checkedBackgroundColor={checkedBackgroundColor} hasBorder={hasBorder} asideContent={asideContent} > <CheckboxContainer size={size}> <StyledCheckbox {...{ checked, disabled, isInvalid }} {...props} /> <CheckContainer checked={checked}> <BottomCheckLine /> <LeftCheckLine /> </CheckContainer> </CheckboxContainer> <div> {label && <Label>{label}</Label>} <Errors hasSpaceForErrors={hasSpaceForErrors}> {!!errors.length && errors.map((err, i) => <Err key={`err-${i}`}>{err}</Err>)} </Errors> </div> {asideContent && <AsideContainer>{asideContent}</AsideContainer>} </CheckboxItem> ) } export default styled(Checkbox)``