import styled, { keyframes, css } from 'styled-components'; const animationDuration = '0.25s'; const StyledWrapper = styled.div<{ themeLoading: boolean }>` display: flex; align-items: center; margin: 0; padding: 0; ${({ themeLoading }) => { switch (themeLoading) { case true: return css` pointer-events: none; `; case false: return css``; } }}; `; const StyledInputWrapper = styled.label<{ themeSize: 'small' | 'medium'; }>` position: relative; display: inline-block; margin: 0; padding: 0; ${({ themeSize, theme }) => { switch (themeSize) { case 'small': return css` width: ${theme.sizes.switch.smallWidth}; height: ${theme.sizes.switch.smallHeight}; `; case 'medium': return css` width: ${theme.sizes.switch.mediumWidth}; height: ${theme.sizes.switch.mediumHeight}; `; } }}; `; const StyledSlider = styled.span<{ themeDisabled: boolean; themeSize: 'small' | 'medium'; }>` position: absolute; top: 0; left: 0; right: 0; bottom: 0; margin: 0; padding: 0; ${({ themeSize, theme }) => { switch (themeSize) { case 'small': return css` border-radius: ${theme.radii.switch.small}; `; case 'medium': return css` border-radius: ${theme.radii.switch.medium}; `; } }}; ${({ themeDisabled, theme }) => { switch (themeDisabled) { case true: return css` cursor: not-allowed; background-color: ${theme.colors.switch.disabledBackground}; `; case false: return css` cursor: pointer; background-color: ${theme.colors.switch.background}; `; } }}; &:before { position: absolute; content: ''; background-color: ${({ theme }) => theme.colors.switch.handleBackgroundColor}; transition: ${animationDuration}; border-radius: 50%; right: auto; ${({ themeSize, theme }) => { switch (themeSize) { case 'small': return css` width: ${theme.sizes.switch.sliderSmall}; height: ${theme.sizes.switch.sliderSmall}; top: ${theme.space.switch.sliderSmallTop}; left: ${theme.space.switch.sliderSmallLeft}; `; case 'medium': return css` width: ${theme.sizes.switch.sliderMedium}; height: ${theme.sizes.switch.sliderMedium}; top: ${theme.space.switch.sliderMediumTop}; left: ${theme.space.switch.sliderMediumLeft}; `; } }}; } `; const getIconPositionStyle = ( { themeChecked, themeDisabled, }: { themeChecked: boolean; themeDisabled: boolean }, value: string ) => themeDisabled === true && themeChecked === false ? css` right: ${value}; ` : css` left: ${value}; `; const DISABLED_ICON_SIZE_MAP = { small: 'disabledIconSmall', medium: 'disabledIconMedium', } as const; const StyledIconWrapper = styled.div<{ themeChecked?: boolean; themeDisabled: boolean; themeSize: 'small' | 'medium'; }>` position: absolute; color: ${({ theme }) => theme.colors.switch.iconColor}; margin: 0; padding: 0; ${({ themeSize, themeChecked = false, themeDisabled, theme }) => { switch (themeSize) { case 'small': return css` top: 0; ${getIconPositionStyle( { themeChecked, themeDisabled }, theme.space.switch.iconSmallLeft )} line-height: ${theme.fontSizes.switch.iconSmall}; margin-left: ${theme.space.switch.iconSmallMarginLeft}; height: ${theme.sizes.switch.smallHeight}; font-size: ${theme.fontSizes.switch.iconSmall}; `; case 'medium': return css` top: 0; ${getIconPositionStyle( { themeChecked, themeDisabled }, theme.space.switch.iconMediumLeft )} line-height: ${theme.fontSizes.switch.iconMedium}; margin-left: ${theme.space.switch.iconMediumMarginLeft}; height: ${theme.sizes.switch.mediumHeight}; font-size: ${theme.fontSizes.switch.iconMedium}; `; } }}; ${({ themeDisabled, themeSize, theme }) => { switch (themeDisabled) { case true: return css` cursor: not-allowed; font-size: ${theme.fontSizes.switch[ DISABLED_ICON_SIZE_MAP[themeSize] ]}; `; case false: return css` cursor: pointer; `; } }}; `; const StyledLoadingIconWrapper = styled.div<{ themeDisabled: boolean; themeSize: 'small' | 'medium'; }>` position: absolute; transition: ${animationDuration}; display: flex; align-items: center; justify-content: center; margin: 0; padding: 0; ${({ themeDisabled, theme }) => { switch (themeDisabled) { case true: return css` color: ${theme.colors.switch.disabledLoadingIconColor}; cursor: not-allowed; `; case false: return css` color: ${theme.colors.switch.loadingIconColor}; cursor: pointer; `; } }}; ${({ themeSize, theme }) => { switch (themeSize) { case 'small': return css` top: ${theme.space.switch.sliderSmallTop}; font-size: ${theme.fontSizes.switch.loadingIconSmall}; height: ${theme.sizes.switch.sliderSmall}; width: ${theme.sizes.switch.sliderSmall}; `; case 'medium': return css` top: ${theme.space.switch.sliderMediumTop}; font-size: ${theme.fontSizes.switch.loadingIconMedium}; height: ${theme.sizes.switch.sliderMedium}; width: ${theme.sizes.switch.sliderMedium}; `; } }}; `; const fadeIn = keyframes` from { opacity: 0; transform: scale(0); } to { opacity: 1; transform: scale(1); } `; const StyledInput = styled.input<{ themeDisabled: boolean; themeSize: 'small' | 'medium'; }>` opacity: 0; width: 0; height: 0; margin: 0; padding: 0; ${({ themeDisabled, theme }) => { switch (themeDisabled) { case true: return css` &:checked ~ ${StyledSlider} { background-color: ${theme.colors.switch.checkedDisabledBackground}; } &:checked ~ ${StyledLoadingIconWrapper} { color: ${theme.colors.switch.checkedDisabledLoadingIconColor}; } `; case false: return css` &:checked ~ ${StyledSlider} { background-color: ${theme.colors.switch.checkedBackground}; } &:checked ~ ${StyledLoadingIconWrapper} { color: ${theme.colors.switch.checkedLoadingIconColor}; } `; } }}; ${({ themeSize, theme }) => { switch (themeSize) { case 'small': return css` &:checked ~ ${StyledSlider}:before { left: ${theme.space.switch.sliderSmallCheckedLeft}; } ~ ${StyledLoadingIconWrapper} { left: ${theme.space.switch.loadingIconSmallLeft}; } &:checked ~ ${StyledLoadingIconWrapper} { left: ${theme.space.switch.sliderSmallCheckedLeft}; } `; case 'medium': return css` &:checked ~ ${StyledSlider}:before { left: ${theme.space.switch.sliderMediumCheckedLeft}; } ~ ${StyledLoadingIconWrapper} { left: ${theme.space.switch.loadingIconMediumLeft}; } &:checked ~ ${StyledLoadingIconWrapper} { left: ${theme.space.switch.sliderMediumCheckedLeft}; } `; } }}; ~ ${StyledIconWrapper} { display: none; } &:checked ~ ${StyledIconWrapper}, &:disabled ~ ${StyledIconWrapper} { display: flex; align-items: center; animation-name: ${fadeIn}; animation-duration: ${animationDuration}; } `; export { StyledWrapper, StyledInputWrapper, StyledInput, StyledSlider, StyledIconWrapper, StyledLoadingIconWrapper, };