chore: Move to Typescript (#2783)
This PR moves the entire project to Typescript. Due to the ~1000 ignores this will lead to a messy codebase for a while, but the churn is worth it – all of those ignore comments are places that were never type-safe previously. closes #1282
This commit is contained in:
106
app/components/Switch.tsx
Normal file
106
app/components/Switch.tsx
Normal file
@@ -0,0 +1,106 @@
|
||||
import * as React from "react";
|
||||
import styled from "styled-components";
|
||||
import { LabelText } from "~/components/Input";
|
||||
|
||||
type Props = {
|
||||
width?: number;
|
||||
height?: number;
|
||||
label?: string;
|
||||
checked?: boolean;
|
||||
disabled?: boolean;
|
||||
onChange: (event: React.ChangeEvent<HTMLInputElement>) => unknown;
|
||||
id?: string;
|
||||
};
|
||||
|
||||
function Switch({ width = 38, height = 20, label, disabled, ...props }: Props) {
|
||||
const component = (
|
||||
<Wrapper width={width} height={height}>
|
||||
<HiddenInput
|
||||
type="checkbox"
|
||||
width={width}
|
||||
height={height}
|
||||
disabled={disabled}
|
||||
{...props}
|
||||
/>
|
||||
<Slider width={width} height={height} />
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
if (label) {
|
||||
return (
|
||||
<Label disabled={disabled} htmlFor={props.id}>
|
||||
{component}
|
||||
<LabelText>{label}</LabelText>
|
||||
</Label>
|
||||
);
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
const Label = styled.label<{ disabled?: boolean }>`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
${(props) => (props.disabled ? `opacity: 0.75;` : "")}
|
||||
`;
|
||||
|
||||
const Wrapper = styled.label<{ width: number; height: number }>`
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: ${(props) => props.width}px;
|
||||
height: ${(props) => props.height}px;
|
||||
margin-bottom: 4px;
|
||||
margin-right: 8px;
|
||||
`;
|
||||
|
||||
const Slider = styled.span<{ width: number; height: number }>`
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: ${(props) => props.theme.slate};
|
||||
-webkit-transition: 0.4s;
|
||||
transition: 0.4s;
|
||||
border-radius: ${(props) => props.height}px;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: ${(props) => props.height - 8}px;
|
||||
width: ${(props) => props.height - 8}px;
|
||||
left: 4px;
|
||||
bottom: 4px;
|
||||
background-color: white;
|
||||
border-radius: 50%;
|
||||
-webkit-transition: 0.4s;
|
||||
transition: 0.4s;
|
||||
}
|
||||
`;
|
||||
|
||||
const HiddenInput = styled.input<{ width: number; height: number }>`
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
visibility: hidden;
|
||||
|
||||
&:disabled + ${Slider} {
|
||||
opacity: 0.75;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
&:checked + ${Slider} {
|
||||
background-color: ${(props) => props.theme.primary};
|
||||
}
|
||||
|
||||
&:focus + ${Slider} {
|
||||
box-shadow: 0 0 1px ${(props) => props.theme.primary};
|
||||
}
|
||||
|
||||
&:checked + ${Slider}:before {
|
||||
transform: translateX(${(props) => props.width - props.height}px);
|
||||
}
|
||||
`;
|
||||
|
||||
export default Switch;
|
||||
Reference in New Issue
Block a user