import styled, { css, FlattenInterpolation, ThemeProps, DefaultTheme, } from 'styled-components'; import { InputHTMLAttributes } from 'react'; const StyledInput = styled.input< { themeDisabled: boolean; } & InputHTMLAttributes >` appearance: none; position: relative; height: ${({ theme }) => theme.sizes.radio.height}; width: ${({ theme }) => theme.sizes.radio.width}; flex-shrink: 0; border-radius: ${({ theme }) => theme.radii.radio.default}; border: ${({ theme }) => theme.borderWidths.radio.default} solid ${({ theme }) => theme.colors.radio.defaultBorder}; margin: 0; padding: 0; &:after { content: ''; position: absolute; height: ${({ theme }) => theme.sizes.radio.checkmarkHeight}; width: ${({ theme }) => theme.sizes.radio.checkmarkWidth}; top: 50%; left: 50%; transform: translateX(-50%) translateY(-50%); border-radius: ${({ theme }) => theme.radii.radio.default}; } &:focus { outline: none; } ${({ themeDisabled, theme }) => { switch (themeDisabled) { case false: return css` cursor: pointer; color: ${theme.colors.radio.defaultText}; &:hover { border-color: ${theme.colors.radio.hoverBorder}; } &:checked { border-color: ${theme.colors.radio.activeBorder}; &::after { background-color: ${theme.colors.radio.defaultCheckmark}; } } `; case true: return css` cursor: not-allowed; color: ${theme.colors.radio.disabledText}; background-color: ${theme.colors.radio.disabledBackground}; &:checked { border-color: ${theme.colors.radio.disabledBorder}; &::after { background-color: ${theme.colors.radio.disabledCheckmark}; } } `; } }}; `; const StyledLabel = styled.label<{ themeDisabled: boolean; }>` font-size: ${({ theme }) => theme.fontSizes.radio.default}; display: flex; align-items: center; line-height: ${({ theme }) => theme.lineHeights.radio.default}; font-weight: ${({ theme }) => theme.fontWeights.radio.default}; margin: 0; padding: 0; ${({ themeDisabled, theme }) => { switch (themeDisabled) { case false: return css` cursor: pointer; color: ${theme.colors.radio.defaultText}; `; case true: return css` cursor: not-allowed; color: ${theme.colors.radio.disabledText}; `; } }}; > ${StyledInput} { margin: ${({ theme }) => theme.space.radio.margin}; } `; const StyledText = styled.div` margin: 0; padding: 0; `; const StyledWrapper = styled.div<{ themeLayout: 'vertical' | 'horizontal' }>` margin: 0; padding: 0; ${({ themeLayout }) => { switch (themeLayout) { case 'vertical': return css``; case 'horizontal': return css` display: flex; `; } }}; `; const Spacer = styled.div<{ themeLayout: 'vertical' | 'horizontal' }>` margin: 0; padding: 0; ${({ themeLayout, theme }) => { switch (themeLayout) { case 'vertical': return css` margin-top: ${theme.space.radio.groupVerticalMargin}; `; case 'horizontal': return css` margin-left: ${theme.space.radio.groupHorizontalMargin}; `; } }}; `; const StyledRadioButton = styled.span<{ themeSize: 'small' | 'medium' | 'large'; }>` display: inline-flex; align-items: center; box-sizing: border-box; border: ${({ theme }) => theme.borderWidths.radio.default} solid ${({ theme }) => theme.colors.radio.defaultBorder}; border-radius: ${({ theme }) => theme.radii.radio.button}; line-height: 100%; color: ${({ theme }) => theme.colors.radio.defaultText}; background: transparent; cursor: pointer; font-weight: ${({ theme }) => theme.fontWeights.radio.default}; margin: 0; padding: 0; &:hover { color: ${({ theme }) => theme.colors.radio.hoverText}; border-color: ${({ theme }) => theme.colors.radio.hoverBorder}; } ${({ themeSize, theme }) => { switch (themeSize) { case 'small': return css` font-size: ${theme.fontSizes.radio.buttonSmall}; padding: ${theme.space.radio.buttonSmallPadding}; height: ${theme.sizes.radio.buttonSmall}; `; case 'medium': return css` font-size: ${theme.fontSizes.radio.buttonMedium}; padding: ${theme.space.radio.buttonMediumPadding}; height: ${theme.sizes.radio.buttonMedium}; `; case 'large': return css` font-size: ${theme.fontSizes.radio.buttonLarge}; padding: ${theme.space.radio.buttonLargePadding}; height: ${theme.sizes.radio.buttonLarge}; `; } }}; `; type ThemeStatus = 'disabled' | 'enabled'; type AdvancedIntent = 'primary' | 'danger' | 'success' | 'warning' | 'error'; const HOVER_COLORS = { primary: 'hoverPrimary', danger: 'hoverDanger', success: 'hoverSuccess', warning: 'hoverWarning', error: 'hoverError', } as const; const getAdvancedIntentStyles = ( intent: AdvancedIntent ): FlattenInterpolation> => css` & ~ ${StyledRadioButton} { border-color: ${({ theme }) => theme.colors.radio[HOVER_COLORS[intent]]}; color: ${({ theme }) => theme.colors.radio[intent]}; } &:checked ~ ${StyledRadioButton} { color: ${({ theme }) => theme.colors.radio.enabledSelectedText}; border-color: ${({ theme }) => theme.colors.radio[HOVER_COLORS[intent]]}; background-color: ${({ theme }) => theme.colors.radio[intent]}; } &:hover ~ ${StyledRadioButton} { border-color: ${({ theme }) => theme.colors.radio[HOVER_COLORS[intent]]}; background-color: ${({ theme }) => theme.colors.radio[intent]}; color: ${({ theme }) => theme.colors.radio.enabledSelectedText}; } `; const StyledRadioButtonInput = styled.input<{ themeIntent: 'basic' | AdvancedIntent; themeStatus: ThemeStatus; }>` display: none; margin: 0; padding: 0; ${({ themeIntent, theme }) => { switch (themeIntent) { case 'basic': return css` &:checked ~ ${StyledRadioButton} { color: ${theme.colors.radio.enabledSelectedText}; border-color: ${theme.colors.radio.hoverBorder}; background-color: ${theme.colors.radio.buttonCheckedBackground}; &:hover { color: ${theme.colors.radio.enabledSelectedText}; } } `; case 'primary': return getAdvancedIntentStyles('primary'); case 'danger': return getAdvancedIntentStyles('danger'); case 'success': return getAdvancedIntentStyles('success'); case 'warning': return getAdvancedIntentStyles('warning'); case 'error': return getAdvancedIntentStyles('error'); } }}; ${({ themeStatus, theme }) => { switch (themeStatus) { case 'disabled': return css` ~ ${StyledRadioButton} { cursor: not-allowed; color: ${theme.colors.radio.disabledText}; background-color: ${theme.colors.radio.buttonDisabledBackground}; &:hover { color: ${theme.colors.radio.disabledText}; border-color: ${theme.colors.radio.disabledBorder}; } } &:checked ~ ${StyledRadioButton} { color: ${theme.colors.radio.disabledSelectedText}; background-color: ${theme.colors.radio .buttonDisabledCheckedBackground}; border: none; } `; case 'enabled': return css``; } }}; `; const StyledRadioButtonLabel = styled.label` display: inline-flex; align-items: center; margin: 0; padding: 0; `; const StyledRadioButtonGroupWrapper = styled.div<{ preCheckedIndex: number; themeLayout: 'no-gap' | 'gap-small' | 'gap-medium' | 'gap-large'; }>` display: inline-flex; align-items: center; flex-wrap: wrap; margin: 0; padding: 0; ${({ themeLayout, theme, preCheckedIndex }) => { switch (themeLayout) { case 'no-gap': return css` > ${StyledRadioButtonLabel} > ${StyledRadioButton} { border-radius: 0; } > ${StyledRadioButtonLabel}:first-child > ${StyledRadioButton} { border-top-left-radius: ${theme.radii.radio.button}; border-bottom-left-radius: ${theme.radii.radio.button}; } > ${StyledRadioButtonLabel}:last-child > ${StyledRadioButton} { border-top-right-radius: ${theme.radii.radio.button}; border-bottom-right-radius: ${theme.radii.radio.button}; } > ${StyledRadioButtonLabel}:not(:first-child) > ${StyledRadioButton} { border-left-width: 0px; &:hover { border-left-width: ${theme.borderWidths.radio.default}; margin-left: -${theme.borderWidths.radio.default}; } } > ${StyledRadioButtonLabel}:nth-child(${preCheckedIndex + 1}) > ${StyledRadioButton} { border-right-width: ${theme.borderWidths.radio.default}; border-right-style: solid; border-right-color: ${theme.colors.radio.hoverBorder}; } `; case 'gap-small': return css` margin: ${theme.space.radio.buttonGroupSmallMargin}; width: ${theme.sizes.radio.buttonGroupSmallWidth}; > * { margin: ${theme.space.radio.buttonSmallMargin}; } `; case 'gap-medium': return css` margin: ${theme.space.radio.buttonGroupMediumMargin}; width: ${theme.sizes.radio.buttonGroupMediumWidth}; > * { margin: ${theme.space.radio.buttonMediumMargin}; } `; case 'gap-large': return css` margin: ${theme.space.radio.buttonGroupLargeMargin}; width: ${theme.sizes.radio.buttonGroupLargeWidth}; > * { margin: ${theme.space.radio.buttonLargeMargin}; } `; } }}; `; export { StyledInput, StyledLabel, StyledText, StyledWrapper, Spacer, StyledRadioButton, StyledRadioButtonInput, StyledRadioButtonLabel, StyledRadioButtonGroupWrapper, };