UNPKG

@navinc/base-react-components

Version:
137 lines (120 loc) 3.17 kB
import React, { useRef, useEffect } from 'react' import styled from 'styled-components' import Copy from './copy' import { focusWithoutScroll } from '@navinc/utils' const getLabelStyling = ({ isInvalid, theme }) => ` margin: 0; padding: 0; color: ${isInvalid ? theme.error : 'inherit'}; ` const CopyLabel = styled(({ isInvalid, ...props }) => <Copy {...props} />)` ${getLabelStyling} ` const DivLabel = styled.div` ${getLabelStyling} ` const RadioItem = styled.label` display: flex; flex-flow: row nowrap; align-items: center; flex: 1 1 auto; margin-bottom: 0; cursor: pointer; text-align: left; ${({ asideContent, hasBorder, theme }) => (asideContent || hasBorder) && ` border-radius: 12px; border: 1px solid ${theme.border}; padding: 8px; padding-left: 16px; padding-right: 16px; min-height: 62px; `} ${({ checked, checkedBackgroundColor }) => checked && checkedBackgroundColor && ` background-color: ${checkedBackgroundColor}; border-color: ${checkedBackgroundColor}; `} & > :first-child { margin-right: 16px; } ` const AsideContainer = styled.div` display: flex; flex: 1; justify-content: flex-end; margin-left: 8px; ` const RadioIndicator = styled.input.attrs(() => ({ type: 'radio' }))` box-sizing: border-box; border-radius: 50%; background-color: ${({ checked, theme }) => (checked ? theme.navBlue : 'transparent')}; height: 12px; width: 12px; appearance: none; margin: 0; font-size: inherit; transition: background-color 300ms ease; ` const RadioSpot = styled.div` display: flex; justify-content: center; align-items: center; box-sizing: border-box; border-radius: 50%; border-style: solid; border-width: ${({ checked }) => (checked ? '2px' : '1px')}; border-color: ${({ disabled, theme }) => (disabled ? theme.scuttleGray300 : theme.bubbleBlue200)}; background: ${({ disabled, theme }) => (disabled ? theme.neutral100 : theme.bubbleBlue100)}; height: 24px; flex: 0 0 auto; width: 24px; transition: box-shadow 300ms ease; &:focus-within { box-shadow: 0 0 0 8px ${({ theme }) => theme.bubbleBlue300}; & > ${RadioIndicator} { outline: none; } } ` export const Radio = ({ asideContent, autoFocus, checkedBackgroundColor, children, label, className, checked, disabled, hasBorder, isInvalid, ...props }) => { const inputRef = useRef(null) useEffect(() => { if (autoFocus) { focusWithoutScroll(inputRef.current) } }, [autoFocus]) const Label = typeof label === 'string' ? CopyLabel : DivLabel return ( <RadioItem asideContent={asideContent} checked={checked} className={className} hasBorder={hasBorder} checkedBackgroundColor={checkedBackgroundColor} > <RadioSpot {...{ checked, disabled }}> <RadioIndicator ref={inputRef} {...{ checked, disabled }} {...props} /> </RadioSpot> <Label isInvalid={isInvalid}>{label}</Label> {asideContent && <AsideContainer>{asideContent}</AsideContainer>} </RadioItem> ) } const StyledRadio = styled(Radio)`` export default StyledRadio