Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save lucasriondel/4833c883c92a58b366d3b8a7577424c5 to your computer and use it in GitHub Desktop.
Save lucasriondel/4833c883c92a58b366d3b8a7577424c5 to your computer and use it in GitHub Desktop.
Custom checkbox react typescript styled-components
import React from "react";
import styled from "styled-components";
const CheckboxContainer = styled.div`
display: inline-block;
vertical-align: middle;
`;
const Icon = styled.svg`
fill: none;
stroke: white;
stroke-width: 2px;
`;
// Hide checkbox visually but remain accessible to screen readers.
// Source: https://polished.js.org/docs/#hidevisually
const HiddenCheckbox = styled.input.attrs({ type: "checkbox" })`
border: 0;
clip: rect(0 0 0 0);
clippath: inset(50%);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
white-space: nowrap;
width: 1px;
`;
const StyledCheckbox = styled.div<{ checked: boolean }>`
display: inline-block;
width: 16px;
height: 16px;
background: ${(props) => (props.checked ? "salmon" : "papayawhip")}
border-radius: 3px;
transition: all 150ms;
${HiddenCheckbox}:focus + & {
box-shadow: 0 0 0 3px pink;
}
${Icon} {
visibility: ${(props) => (props.checked ? "visible" : "hidden")}
}
`;
interface IProps {
className?: string;
checked: boolean;
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
labelWrap?: boolean;
}
const Checkbox: React.FC<IProps> = ({
className,
checked,
labelWrap = true,
...props
}) => {
const content = (
<CheckboxContainer className={className}>
<HiddenCheckbox checked={checked} {...props} />
<StyledCheckbox checked={checked}>
<Icon viewBox="0 0 24 24">
<polyline points="20 6 9 17 4 12" />
</Icon>
</StyledCheckbox>
</CheckboxContainer>
);
return labelWrap ? <label>{content}</label> : <>{content}</>;
};
export default Checkbox;
@sarangkkl
Copy link

it will be great help sir if you can provide a usecase that how we can use them

@lucasriondel
Copy link
Author

@sarangkkl it's been a while, but I think you can use it that way:

const [checked, setChecked] = useState()

return (
    <Checkbox checked={checked} onChange={(e) => setChecked(e.target.checked)} />
)

The labelWrap is useless imho. You can just use the checkbox as is and wrap it the way you want with a label as you would do with a regular html checkbox.

<div>
    <!-- use the checkbox component instead -->
    <input type="checkbox" id="scales" name="scales" checked> 
    <label for="scales">Scales</label>
</div>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment