import * as React from 'react'; import styled from 'styled-components'; import { Heading } from 'ts/components/text'; import { colors } from 'ts/style/colors'; interface ToggleProps { className?: string; name?: string; value?: string; isChecked?: boolean; isDisabled?: boolean; onToggle?: (e: React.ChangeEvent) => void; width?: string; height?: string; borderWidth?: string; borderColor?: string; backgroundColor?: string; backgroundColorDisabled?: string; radius?: string; radiusBackground?: string; knobRadius?: string; knobWidth?: string; knobHeight?: string; knobGap?: string; knobColor?: string; } const ToggleContainer = styled.label``; const DEFAULT_TOGGLE_STYLES = { WIDTH: '48px', HEIGHT: '24px', KNOB_WIDTH: '12px', KNOB_HEIGHT: '12px', }; export const ToggleBase = styled.span` position: relative; box-sizing: border-box; display: inline-grid; align-items: center; width: ${p => p.width || DEFAULT_TOGGLE_STYLES.WIDTH}; height: ${p => p.height || DEFAULT_TOGGLE_STYLES.HEIGHT}; vertical-align: text-top; margin: 0 4px; input[type='checkbox'] { position: absolute; margin-left: -9999px; visibility: hidden; // off state & + label { display: inline-grid; box-sizing: border-box; align-items: center; outline: none; user-select: none; width: ${p => p.width || DEFAULT_TOGGLE_STYLES.WIDTH}; height: ${p => p.height || DEFAULT_TOGGLE_STYLES.HEIGHT}; background-color: ${p => p.knobColor || '#EAEAEA'}; border-radius: ${p => p.radius || '256px'}; cursor: pointer; transition: background ease-out 0.3s; &:before { content: ''; display: block; position: absolute; border-radius: ${p => p.radiusBackground || '256px'}; width: calc(${p => p.width || DEFAULT_TOGGLE_STYLES.WIDTH} - 2 * ${p => p.borderWidth || '2px'}); height: calc(${p => p.height || DEFAULT_TOGGLE_STYLES.HEIGHT} - 2 * ${p => p.borderWidth || '2px'}); background-color: ${p => p.backgroundColor || colors.white}; left: ${p => p.borderWidth || '2px'}; } &:after { display: block; position: absolute; content: ''; width: ${p => p.knobWidth || DEFAULT_TOGGLE_STYLES.KNOB_WIDTH}; height: ${p => p.knobHeight || DEFAULT_TOGGLE_STYLES.KNOB_HEIGHT}; border-radius: ${p => p.knobRadius || '100%'}; background-color: ${p => p.knobColor || '#EAEAEA'}; transition: all ease-out 0.4s; margin-left: ${p => p.knobGap || '4px'}; } } // on state &:checked { & + label { background-color: ${p => p.borderColor || colors.brandLight}; &:before { background-color: ${p => p.backgroundColor || colors.white}; } &:after { margin-left: calc( 100% - ${p => p.knobWidth || DEFAULT_TOGGLE_STYLES.KNOB_WIDTH} - ${p => p.knobGap || '4px'} ); transition: all ease-out 0.2s; background-color: ${p => p.knobColor || colors.brandLight}; } } &:disabled { & + label { background-color: ${p => p.backgroundColorDisabled || '#eee'}; &:after { box-shadow: none; } } } } // disabled &:disabled { & + label { background-color: ${p => p.backgroundColorDisabled || '#eee'}; cursor: default; &:after { box-shadow: none; background-color: ${p => p.backgroundColorDisabled || '#eee'}; } } } } `; export const Toggle = React.forwardRef((props: ToggleProps, ref: React.Ref) => { const { className, name, isChecked = false, isDisabled = false, value = '', onToggle = () => true } = props; return ( ); }); const SwitchWrapper = styled.div` display: flex; justify-content: space-between; padding: 0.75rem 0; `; export interface SwitchProps { label: string; isChecked?: boolean; onToggle: (checked: boolean) => void; } export class Switch extends React.Component { public switchRef: React.RefObject = React.createRef(); constructor(props: SwitchProps) { super(props); } public render(): React.ReactNode { const onToggle = () => { this.props.onToggle(this.switchRef.current.checked); }; return ( {this.props.label} ); } }