Можно использовать
нативный скрытый checkbox. Использовать его можно будет как контролируемый, так и как самостоятельный элемент. Слушать
onChange или использовать
ref. Стилизовать его можно под что угодно. Чтобы работало, надо обязательно использовать элемент
label.
Думаю, это самый универсальный и оптимальный вариант для этой задачи.
Пример с использованием
StyledComponents:
spoilerimport * as React from 'react';
import styled from 'styled-components';
const Wrapper = styled.label`
position: relative;
display: inline-block;
width: 40px;
height: 24px;
`;
const Input: any = styled.input`
display: none;
`;
const Slider = styled.div`
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
transition: .2s;
border-radius: 34px;
&:before {
position: absolute;
content: "";
height: 22px;
width: 22px;
left: 1px;
bottom: 1px;
background-color: white;
transition: .2s;
border-radius: 50%;
}
${Input}:checked + & {
background-color: ${props => props.theme.someColor1};
}
${Input}:focus + & {
box-shadow: 0 0 1px ${props => props.theme.someColor2};
}
${Input}:checked + &:before {
transform: translateX(16px);
}
`;
interface Props = {
name?: string
checked?: boolean
onChange?: Function
innerRef?: Function
className?: string
}
const ToggleSwitch = ({ innerRef, checked, onChange, className, name }: Props) => {
return (
<Wrapper className={className}>
<Input
innerRef={innerRef}
checked={checked}
onChange={onChange}
name={name}
type="checkbox"
/>
<Slider />
</Wrapper>
);
}
Ни одно свойство не является обязательным.